With traditional .NET applications, configuring log4net is relatively straightforward by simply changing the web.config and using xcopy deployment. In SharePoint, however, things become a little more complicated, and getting log4net working effectively takes a little more effort.
Firstly, it's not recommended that you modify the web.config manually or use xcopy deployments when working with SharePoint. This breaks the whole SharePoint model, and is likely to cause issues later on (for instance, when joining a new FTE server to the farm or extending an application). I'm a firm believer in repeatable builds and deploying everything via solutions and features, so this is not an option.
Secondly, not all code executes within the web application context. Take feature receivers and jobs, for example; depending on how they are invoked, these could run within the
stsadm process or within
OWSTimer. Setting up your
log4net settings in the web.config can therefore be somewhat futile for debugging these components.
The solution I recommend is to deploy log4net into the GAC, and log4net.config to the 12 hive (using WSPBuilder). It's then possible to pass the location of the config file to log4net on initialize by simply adding the following line to your AssemblyInfo.cs file.
[assembly: log4net.Config.XmlConfigurator(ConfigFile =
@"C:\Program Files\Common Files\Microsoft Shared\" +
@"Web Server Extensions\12\CONFIG\log4net.config", Watch = true)]
Note that although this requires hard-coding the location of your previously deployed config file, I feel that it's acceptable as the path never changes between SharePoint installations. I would deploy the log4net assembly and config within a globally scoped solution rather than packaging with your main application codebase. The reasons for this are discussed briefly in a previous article here, and will reduce risk with managing shared resources in the farm.
Often, you may wish to have different log4net configurations per environment. If this is the case, I recommend using a different technique for configuring the location of the log4net config file within your codebase. This allows you to inject some additional application logic to determine the location of your config file.
public static void InitializeLog4Net(string environment)
string configFile = string.Concat("log4net.",environment,".config");
FileInfo configFileInfo = new FileInfo(@"C:\Program Files\Common Files\" +
@"Microsoft Shared\Web Server Extensions\12\CONFIG\log4net\"+ configFile);
The beauty of this solution is that log4net settings may be managed across the entire farm centrally. It also doesn't matter how your code is executed or what process it's running in, all log messages will be processed according to your settings. Use filters to customize log messages for different applications from the one config file.
For debugging feature receivers and jobs, I highly recommend configuring the log4net
OutputDebugStringAppender and using the Sysinternals DebugView. This allows you to see your debug code in real-time, and can easily be switched on in various environments without the need for a debug build.
- 18th November, 2009: Initial post