tags:

views:

330

answers:

3

Anybody here has actually implemented any logging strategy when application is running as XBAP ? Any suggestion (as code) as to how to implement a simple strategy base on your experience.

My app in desktop mode actually logs to a log file (rolling log) using integrated asop log4net implementation but in xbap I can't log cause it stores the file in cache (app2.0 or something folder) so I check if browser hosted and dont log since i dont even know if it ever logs...(why same codebase)....if there was a way to push this log to a service like a web service or post error to some endpoint...

My xbap is full trust intranet mode.

+3  A: 

I would log to isolated storage and provide a way for users to submit the log back to the server using either a simple PUT/POST with HttpWebRequest or, if you're feeling frisky, via a WCF service.

Keep in mind an XBAP only gets 512k of isolated storage so you may actually want to push those event logs back to the server automatically. Also remember that the XBAP can only speak back to it's origin server, so the service that accepts the log files must run under the same domain.

Here's some quick sample code that shows how to setup a TextWriterTraceListener on top of an IsolatedStorageFileStream at which point you can can just use the standard Trace.Write[XXX] methods to do your logging.

IsolatedStorageFileStream traceFileStream = new IsolatedStorageFileStream("Trace.log", FileMode.OpenOrCreate, FileAccess.Write);

TraceListener traceListener = new TextWriterTraceListener(traceFileStream);

Trace.Listeners.Add(traceListener);


UPDATE

Here is a revised answer due to the revision you've made to your question with more details.

Since you mention you're using log4net in your desktop app we can build upon that dependency you are already comfortable working with as it is entirely possible to continue to use log4net in the XBAP version as well. Log4net does not come with an implementation that will solve this problem out of the box, but it is possible to write an implementation of a log4net IAppender which communicates with WCF.

I took a look at the implementation the other answerer linked to by Joachim Kerschbaumer (all credit due) and it looks like a solid implementation. My first concern was that, in a sample, someone might be logging back to the service on every event and perhaps synchronously, but the implementation actually has support for queuing up a certain number of events and sending them back to the server in batch form. Also, when it does send to the service, it does so using an async invocation of an Action delegate which means it will execute on a thread pool thread and not block the UI. Therefore I would say that implementation is quite solid.

Here's the steps I would take from here:

  1. Download Joachim's WCF appender implementation
  2. Add his project's to your solution.
  3. Reference the WCFAppender project from your XBAP
  4. Configure log4net to use the WCF appender. Now, there are several settings for this logger so I suggest checking out his sample app's config. The most important ones however are QueueSize and FlushLevel. You should set QueueSize high enough so that, based on how much you actually are logging, you won't be chattering with the WCF service too much. If you're just configuring warnings/errors then you can probably set this to something low. If you're configuring with informational then you want to set this a little higher. As far as FlushLevel you should probably just set this to ERROR as this will just guarantee that no matter how big the queue is at the time an error occurs everything will be flushed at the moment an error is logged.
  5. The sample appears to use LINQ2SQL to log to a custom DB inside of the WCF service. You will need to replace this implementation to log to whatever data source best suits your needs.

Now, Joachim's sample is written in a way that's intended to be very easy for someone to download, run and understand very quickly. I would definitely change a couple things about it if I were putting it into a production solution:

  1. Separate the WCF contracts into a separate library which you can share between the client and the server. This would allow you to stop using a Visual Studio service reference in the WCFAppender library and just reference the same contract library for the data types. Likewise, since the contracts would no longer be in the service itself, you would reference the contract library from the service.
  2. I don't know that wsHttpBinding is really necessary here. It comes with a couple more knobs and switches than one probably needs for something as simple as this. I would probably go with the simpler basicHttpBinding and if you wanted to make sure the log data was encrypted over the wire I would just make sure to use HTTPS.
Drew Marsh
Someone downvoted my answer, but gives no explanation and provides no answer of their own. Interesting.
Drew Marsh
Yes, probably a competitor intending to post an answer of their own. I thought your answer was good one. +1
Ray Burns
Sheesh, well I wouldn't mind if they gave a reason for it so I could maybe learn something myself. Thanks for the upvote though. ;)
Drew Marsh
Can you explain what I need to get things working as bullet points? And guaranteed it should work and be a solution.
abmv
some updates from me in orginal question above
abmv
Before I answer any further since I've been downvoted twice now and other answerers are basically providing the same details, can you clarify what zone you intend to run this XBAP in? Internet or intranet? An XBAP could be run with full trust at which point you can do everything you want in .NET, but I was making the assumption that you might not have that ability.
Drew Marsh
Sorry for the delay but I am going to run it in full trust intranet environment.
abmv
Good to know. So the above approach is still perfectly valid and still a very good way to do it. The only thing I would consider is that, since you will have the ability to log information to disk without capacity under full trust, maybe you want to use a RollingFileAppender and change the strategy to just submit entire log files on a regular schedule instead. It just depends on the needs of your application. If you need to know about problems in real-time then the already proposed solution is the best.
Drew Marsh
are you sure I can log to disk ? cause I see that app gets cached and presentationhost run it?
abmv
If the XBAP is running full trust, you can do anything .NET offers. You'll have to sign the ClickOnce Manifest with a key that your intranet clients trust to do this (in case you didn't already know). Here's a great link on how to do that: http://blogs.microsoft.co.il/blogs/maxim/archive/2008/03/05/wpf-xbap-as-full-trust-application.aspx
Drew Marsh
i aleady did that,well i have to look into how I can log to text now mmm.. in the case of xbap
abmv
A: 

My approach has been to log to a remote service, keyed by a unique user ID or GUID. The overhead isn't very high with the usual async calls.

You can cache messages locally, too, either in RAM or in isolated storage -- perhaps as a backup in case the network isn't accessible.

Be sure to watch for duplicate events within a certain time window. You don't want to log 1,000 copies of the same Exception over a period of a few seconds.

Also, I like to log more than just errors. You can also log performance data, such as how long certain functions take to execute (particularly out-of-process calls), or more detailed data in response to the user explicitly entering into a "debug and report" mode. Checking for calls that take longer than a certain threshold is also useful to help catch regressions and preempt user complaints.

RickNZ
A: 

If you are running your XBAP under partial trust, you are only allowed to write to the IsolatedStorage on the client machine. And it's just 512 KB, which you would probably want to use in a more valuable way (than for logging), like for storing user's preferences.

You are not allowed to do any Remoting stuff as well under partial trust, so you can't use log4net RemotingAppender.

Finally, under partial trust XBAP you have WebPermission to talk to the server of your app origin only. I would recommend using a WCF service, like described in this article. We use similar configuration in my current project and it works fine.

Then, basically, on the WCF server side you can do logging to any place appropriate: file, database, etc. You may also want to keep your log4net logging code and try to use one of the wcf log appenders available on the internets (this or this).

Yacoder