I have been told to add “logging” to my code using log4net, the problem is no one can travel in time and see what real world problems the logging will need to be used to solve.<
Logging is not an easy task, but my experience is that all logs should be searchable for responsible parties. An useful target for errors are email directly (and in some cases sms). But in the end all logging data should be searchable in a database with a sesible user interface.
When the email is received to a specific account, this can be processed and put in the database directly. There are som categories and handling rules below:
The content of the debugging can be written to the database in different way, but we need to concider performance. Large amount of data should not be written to database in "production mode". This should be done in daily/weekly bases. The best way is to produce a local file (such as XML or plain text) and put this file into the database during maintenance hours (at night). It should be possible to start/stop a debug session and only write the debug information to the database when the debug session is completed.
The debug component could be implemented as a WCF and log2net and directy access to the database and/or a local file store that is put into the database on regular basis.
One thing is clear...ALL errors/exception should be logged somewhere. Nothing is more irritating than lost error messages :)
Happy debugging!
Log events to event viewer.
Use wisely INFO DEBUG WARNING and ERROR.
when developing show everything (use the console on the server side- see below) on production , log only errors (configurable)
I create a logger in the begging of each class giving it the typeof(myClass) but that's optional...
I'm hosting the WCF in DEV as a console app - so watching the server log is easy also in the console, but once it becomes a service, you have to use event viewer....
ah - and it is very fast if you compare it to WCF "calling times" (calling from client to server) so it doesn't really effect your times, unless you has something the logs like crazy (nHibernate for example) )
What kinds of logging should one add to an application that would be useful later?
If you throw exceptions from your own exception classes, or even better, all your exception classes derive from a base class, add ERROR level logging in the (base) exception constructor; saves you having to remember on each catch/throw. Useful if you have a large code base.
For CLR or 3rd party exceptions, log Exception.ToString() not just the message, otherwise you miss the full stack trace (assuming programmers are not swallowing exceptions or re-throwing sans inner exception)
Focus on DEBUG detail in areas where you either know or suspect you will have issues (just ask QA or Tech Support where to look;-)
If you follow the robustness principle, then you may want INFO or WARN logging when you ignore or change inputs, or expected behaviour. This could be useful if your WCF service starts receiving unexpected (but parseable) input.
To ensure your application performs well, don't ship/install it with DEBUG level logging enabled by default, ERROR or WARN is probably the way to go.
I disagree with the last part of the accepted answer, because log4net has awesome filtering capabilities; on the condition that your programmers understand that logging comes at a cost (as per CK's answer) and they (and QA and Tech Support) know about the filters, and that configuring everything at DEBUG is a bad idea. If you are logging at DEBUG level a large object graph, xml document, db result, et cetera, wrap it in some code that reduces the expense:
if (log.IsDebugEnabled)
{
log.DebugFormat("Loaded in {0} ms {1}", timer.ElapsedMilliseconds, dataSet.GetXml());
}
I would suggest you follow the recommended static logger-per-class approach, simply because it should make logging more useful when you have to actually use it and narrow down on a problem using filters, e.g. LoggerMatchFilter.
If you follow this approach and are willing take a (fairly small) performance hit, here's one way which uses a stack trace to create ILog objects for any class and ensure the config file is wired up to monitor for changes:
public static class LogFactory
{
/// <summary>
/// Create log whose name is the calling methods class name.
/// </summary>
/// <remarks>
/// <para>
/// Configures the log repository if it hasn't been configured before.
/// </para>
/// <para>
/// Creates a debug log message right after getting the logger, this follows
/// the log4net recommendation to log first message as early as possible.
/// </para>
/// </remarks>
/// <returns>Log ready for work.</returns>
public static log4net.ILog Create()
{
var method = new StackTrace().GetFrame(1).GetMethod();
var log = log4net.LogManager.GetLogger(method.DeclaringType);
if (log4net.LogManager.GetRepository().Configured == false)
{
try
{
new FileIOPermission(FileIOPermissionAccess.Read,
AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)
.Demand();
var configFile = new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
log4net.Config.XmlConfigurator.ConfigureAndWatch(configFile);
log.DebugFormat("Log4net configured and watching {0}", configFile.FullName);
}
catch (System.Security.SecurityException e)
{
log.DebugFormat("Unable to watch config file due to security permissions. {0}", e.ToString());
}
}
log.DebugFormat("Logging {0}", log.Logger.Name);
return log;
}
}