Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why have named logger in Log4Net?

I have been investigating ways to inject the Log4Net ILog into classes using Castle Windsor. In most examples, I see where Castle Windsor can provide a "facilitator" that provides property injection, and injects the ILogger (not ILog). I have found only one example where contructor injection is used, and the facilitator method is not used (see Castle Windsor dependency injection: Use the caller type as a parameter)

In all these examples, it seems Log4Net wants to have a named logger. Most examples refer to the Log4Net static method LogManager.GetLogger(class name here). This makes it a challenge to define the dependancies for CastleWindsor without using reflection, or the facilitator method (can facilitator method be used with ctor injection???). When looking at the question by Ilya Kogan (URL above...), I guess I don't understand why I need, or even want a named logger. Can't I use a logger by the same name everywhere?

For example, can't I just register the logger with hardcoded name of XXX? (It seems to work fine, and in the end, I just want to log - I don't care which logger logged it...) Is there a scope issue? Is there a memory leak issue? Why can't/shouldn't the logger be a singleton?

public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
                Component.For<log4net.ILog>().UsingFactoryMethod(() => log4net.LogManager.GetLogger("xxx"))
                );
        }

UPDATE:

Upon some research, a hardcoded named logger can be used - such as XXX in my example above, but if the configuration of the logger outputs the logger name to the logfile and if the logger name is dynamically assigned to the same name as the method or class, you automagically get reference to where the logging originated from. Context within the log file can be very helpful.

When specifically addressing ctor injection, there seems to be 5 possible options...

  • Use a singleton and not use named loggers (thus not reported in log file)
  • Use reflection with ctor injection (as seen in Ilya Kogan's example)
  • Use property injection (via facilitators)
  • Use post-sharp AOP IL Injection for logging
  • Use CTOR injection (via facilitators)
like image 571
barrypicker Avatar asked Nov 14 '12 22:11

barrypicker


People also ask

What is difference between log4j and log4net?

The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets. log4net is a port of the excellent Apache log4j™ framework to the Microsoft® . NET runtime. We have kept the framework similar in spirit to the original log4j while taking advantage of new features in the .

Where are log4net logs stored?

You can configure the log4net. config file to create log files. The file is located in the webroot\App_data directory of the installation. The different log files are described in Services logs.

Is log4net dependent on log4j?

Log4net is a logging utility for . NET applications. It's based on log4j, which is for Java applications. Log4net is highly configurable, so you can use it in many scenarios.


2 Answers

Good questions.

In short, log4net wants named loggers because then the names are used for filtering the log output (see the log4net documentation for details). Type name is just a convenient convention as it provides you that extra bit of context and coupled with correct use of namespaces allows you do things like say "log all NHibernate messages to a separate file"

That's also why commonly, if you're not using container for that, you have a single, static logger property/field in your classes.

The ILogger you're referring to is the abstraction in Castle over logging, one of which can be for log4net.

While the LoggingFacility provides out of the box support for providing dependencies on ILogger it is by no means forcing you to do this.

Your ILog registration should be rewritten as follows (I'm writing this from memory so details may be slightly different):

Component.For<log4net.ILog>()
    .UsingFactoryMethod((k, c) => log4net.LogManager.GetLogger(c.RequestedType))
    .LifestyleTransient()

c.RequestedType will give you the type for which you're satisfying the dependency and making it transient will avoid the issue that all types would reuse the single instance of logger named after whatever the first type to request the dependency was.

like image 182
Krzysztof Kozmic Avatar answered Sep 23 '22 02:09

Krzysztof Kozmic


The recommended way to DI an Log4Net Log using Castle Windsor is to use Facilities. One has already been created for Log4Net and its use is demonstrated in this tutorial.

like image 34
Adam Goss Avatar answered Sep 21 '22 02:09

Adam Goss