简体   繁体   中英

log4Net dilemma

I have a C# solution containing multiple C# projects. I am planning to add logging in it. This logging should be available in all the projects and preferably use log4Net with rolling file logs.

With the above said premise, I could think of two ways to do that.

  1. Initialize logger in entry point (Program class) of the solution & Get the logger instance & use it as a member variable for every class that needs logging.

  2. Add another project, Utilities & define a Logging class with static logging methods. This class should be initialized in entry point (Program class) of the solution.

What could be the best possible solution?

I have a similar situation. What we've done is use 1 app config for all the projects and use links to reference it.

In the app.config for your app you set the log4net config Section

  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>

And later set the Appender:

<log4net>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
...

And in each class you want to log you put a line similar to this:

private static readonly ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

Then each class grabs the same logger (singleton). Would that work for you?

In my projects, I wrote a wrapper around LOG4NET to (theoretically) exchange it with other logging frameworks like NLOG without breaking my code.

My own logging class is accessible through a static singleton. It does initialization in this singleton.

(BTW: I published the source code over at the Code Project some time ago, maybe it gives you some inspiration)

If you're thinking about initializing something at the entry point every single time, then you're writing yourself a case for dependency injection. Using a DI library (like Unity, Castle, or whatever flavor you personally like), you could do either constructor injection or property injection to get your logger class (or Log4Net) initialized automatically.

Additionally, you can use the DI kernel to make it a singleton, so that you only have one instance of it active.

Building off of Queso's answer, we had .dll's that were imported with reflection at runtime. In order to get them to use Log4Net we created a log4net.config file with all the appropriate config sections. We also used the same line of code to intialize the log in each class that Queso references. The seperate config allowed us to use it throughout the entire app domain.

EDIT we also had to make a modifcation to the appsettings file to allow for this.

http://haacked.com/archive/2005/03/07/ConfiguringLog4NetForWebApplications.aspx

Option 1 is the way to go.

If you use static methods you loose the ability to use hierarchical loggers. This feature allows you to configure your log output differently for individual classes or even for entire sub systems eg YourNameSpace.Security . This tutorial elaborates on this topic (also the other chapters are a good read).

Building a wrapper is certainly not a bad idea, but it is not strictly necessary. It does allow for a few things though: change log framework, use DI, add additional log levels (eg log.Verbose()) or different overloads for logging...

Btw. I would initialize the loggers like this:

ILog log = LogManager.GetLogger(typeof(YourClass));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM