As mentioned earlier, NLog and log4net are both good logging frameworks. As Jeff mentions above, System.Diagnostics is also a reasonable choice (for more than just logging to the EventLog). Trying to add some value to my answer, rather than just parroting what has already been said, you can enhance your System.Diagnostics logging by using TraceSources and by using the free Ukadc.Diagnostics library from codeplex.
With TraceSources you can created "named loggers", similar to how you can do it in NLog and log4net. These TraceSources can be configured to log at certain levels (varying per TraceSource) and they can be sent to various destinations (TraceListeners). All TraceSources can log to the same listener or some can log to some listeners while others log to other listeners. Any TraceSource can also be sent to multiple TraceListeners.
Here is how you would use TraceSources in code (assume that TraceSource "abc" has been configured in the app.config file to log "Info" and higher priority messages and has been configured to log to the file "log.txt").
public class MyClass
{
static TraceSource ts = new TraceSource("abc"); //Common idiom for NLog and log4net, not sure if as common for TraceSource
public void Func1(int x)
{
ts.Information("Entering Func1");
ts.Verbose("x = {0}", x); //Won't log if "abc" is configured to log Info and HIGHER messgaes
ts.Information("Exiting Func1");
}
}
One huge benefit of Ukadc.Diagnostics, over "plain" TraceSources, is that you can configure NLog/log4net style output formatting so you can have much more control over what fields show up in your logging output and what format.
Three things that are pretty useful from NLog/log4net that are not available in System.Diagnostics are:
1. Ability to automatically log call site information (method/function)
2. Additional logging context (GDC - global logging properties, MDC - thread logging properties in NLog/log4net parlance). System.Diagnostics does have Trace.CorrelationManager.LogicalOperationStack, which is similar to NDC.
3. Hierarichal loggers.
Hierarichical loggers means that you could configure an "ancestor" logger and any "descendent" loggers will inherit those settings. For example, say that you have a class whose fully (namespace) qualified type name is Namespace1.Namespace2.Class. With NLog/log4net you could configure logging information (level, destination) for "Namespace1" and if you requested a logger based on the fully qualified name of any type in Namespace1, it would inherit Namespace1's settings. You can achieve something similar to this using TraceSources by looking at how Castle implemented their TraceSource-based logging abstraction. In particular, look at the Initialize function. It is pretty easy to get working (in your own thin wrapper around TraceSource) and, as a side benefit, makes the configuration of your TraceSources a little bit easier since you don't have to configure every single TraceSource individually. Note that you could easily add the ability to have a "root" configuration by configuring a TraceSource called "" and adding some code in the Castle scheme to default to the "" configuration if no actual ancestors are found. You could then, for example, configure "*" to log at, say Verbose, and then specifically configure certain TraceSources (either by class or by namespace) to be off or at a different level. Without hierarichal loggers, to do the same thing with TraceSources would required you to configure every single TraceSource to log at "Verbose" that you want at verbose.
While I talked a lot about loggers for classes and namespaces, NLog, log4net, and TraceSources all also allow you to define your logger names as arbitrary strings. As such, you cold define a logger hierarchy by functional area rather than by namespace/class:
Database
Database.Connect
Database.Query
Database.Update
Database.SQL
Amazon
Amazon.Books
Amazon.Books.Fiction
Amazon.Books.Nonfiction
Amazon.Electronics
Amazon.Electronics.Video
Amazon.Electronics.Music
Amazon.Electronics.Computer
So, you could turn on "Amazon" logging and all Amazon stuff log (without having to explicitly configure each and every "child" TraceSource) and Database stuff would not. Or, you could turn Amazon on and Amazon.Electronics off and only the Amazon.Books (and children) would log.
Finally, if you do go with NLog or log4net, it is worth mentioning that NLog has just made a new release, NLog 2.0, (in beta).