I'd like to get stories on how people are handling tracing and logging in real applications. Here are some questions that might help to explain your answer.
Frameworks
What frameworks do you use?
- log4net
- System.Diagnostics.Trace
- System.Diagnostics.TraceSource
- Logging application block
- Other?
If you use tracing, do you make use of Trace.Correlation.StartLogicalOperation?
Do you write this code manually, or do you use some form of aspect oriented programming to do it? Care to share a code snippet?
Do you provide any form of granularity over trace sources? E.g., WPF TraceSources allow you to configure them at various levels:
- System.Windows - settings for all of WPF
- System.Windows.Animation - override specifically for Animation.
Listeners
What log outputs do you use?
- Text files
- XML files
- Event log
- Other?
If using files, do you use rolling logs or just a single file? How do you make the logs available for people to consume?
Viewing
What tools to you use for viewing the logs?
- Notepad
- Tail
- Event viewer
- Systems Center Operations Manager/Microsoft Operations Manger
- WCF Service Trace Viewer
- Other?
If you are building an ASP.NET solution, do you also use ASP.NET Health Monitoring? Do you include trace output in the health monitor events? What about Trace.axd?
What about custom performance counters?
I'm not qualified to comment on logging for .Net, since my bread and butter is Java, but we've had a migration in our logging over the last 8 years you may find a useful analogy to your question.
We started with a Singleton logger that was used by every thread within the JVM, and set the logging level for the entire process. This resulted in huge logs if we had to debug even a very specific part of the system, so lesson number one is to segment your logging.
Our current incarnation of the logger allows multiple instances with one defined as the default. We can instantiate any number of child loggers that have different logging levels, but the most useful facet of this architecture is the ability to create loggers for individual packages and classes by simply changing the logging properties. Lesson number two is to create a flexible system that allows overriding its behavior without changing code.
We are using the Apache commons-logging library wrapped around Log4J.
Hope this helps!
* Edit *
After reading Jeffrey Hantin's post below, I realized that I should have noted what our internal logging wrapper has actually become. It's now essentially a factory and is strictly used to get a working logger using the correct properties file (which for legacy reasons hasn't been moved to the default position). Since you can specify the logging configuration file on command line now, I suspect it will become even leaner and if you're starting a new application, I'd definitely agree with his statement that you shouldn't even bother wrapping the logger.
We use log4net on our web applications.
It's ability to customize logging at run-time by changing the XML configuration file is very handy when an application is malfunctioning at run-time and you need to see more information.
It also allows you to target specific classes or attributes to log under. This is very handy when you have an idea where the error is occurring. A classic example is NHibernate where you want to see just the SQL going to the database.
Edit:
We write all events to a database and the Trace system. The event log we use for errors or exceptions. We log most events to a database so that we can create custom reports and let the users view the log if they want to right from the application.
There are lots of great recommendations in the answers.
A general best practice is to consider who will be reading the log. In my case it will be an administrator at the client site. So I log messages that gives them something they can act on. For Example, "Unable to initialize application. This is usually caused by ......"
As the authors of the tool, we of course use SmartInspect for logging and tracing .NET applications. We usually use the named pipe protocol for live logging and (encrypted) binary log files for end-user logs. We use the SmartInspect Console as the viewer and monitoring tool.
There are actually quite a few logging frameworks and tools for .NET out there. There's an overview and comparison of the different tools on DotNetLogging.com.
I have to join the chorus recommending log4net, in my case coming from a platform flexibility (desktop .Net/Compact Framework, 32/64-bit) point of view.
However, wrapping it in a private-label API is a major anti-pattern.
log4net.ILogger
is the .Net counterpart of the Commons Logging wrapper API already, so coupling is already minimized for you, and since it is also an Apache library, that's usually not even a concern because you're not giving up any control: fork it if you must.Most house wrapper libraries I've seen also commit one or more of a litany of faults:
Exception
argument, leading to multiple problems:ILayout
decorator that performs detailed drill-down on an exception to determine the chain of events.IsLevelEnabled
properties, which discards the ability to skip formatting code when areas or levels of logging are turned off.I don't often develop in asp.net, however when it comes to loggers I think a lot of best practices are universal. Here are some of my random thoughts on logging that I have learned over the years:
Frameworks
Logger Output
</xxx>
tag, your log is broken.This is my logging statement - Repeated 100 times
Also see this question of mine.