castleproject/Windsor

Write in different files with Log4Net CastleWindsor for different CastleWindsor instances

smedotnet opened this issue · 3 comments

I don't know if it's the correct place to ask this question. But i have in my project two different instances of CastleWindsor. One for my web application and one for Hangfire (background job processing).

I'm using for these two instances, Log4Net as logger. But what is happenning is that the loggers write in the same file, so i would like to log in different files depending on the Castle Windsor instance. I don't know how to achieve that.

I'm registering my logger for both as such :

container.AddFacility((Action) (f => f.UseLog4Net()));

What i have tried so far :

  • Override the ILogger registration by doing this :
hangfireContainer.Register(Component.For<ILogger>()
    .UsingFactoryMethod((x) => x.Resolve<ILoggerFactory>().Create("HangfireLoggerAppender"))
    .Named("LoggerHangfire")
    .IsDefault()
    .LifestyleTransient()
);
// i have a appender named  "HangfireLoggerAppender" in my config file **Doesn't work** 

If you have any idea how can i achieve that, feel free to share !

I assume you've got 2 appenders in one log (i.e. the root log). Have you tried using 2 separate logs, e.g. <root /> and <logger name="hangfire" />.

You can then override the log name in Windsor:

container.AddFacility<LoggingFacility>(f => f.LogUsing<TLoggerFactory>()
    .WithConfig(configFile)
    .ToLog(logName)
);

See the log4net docs for more details:
https://logging.apache.org/log4net/release/manual/configuration.html

Since you are doing quite a bit of stuff with log4net, you are probably best served using the LoggingFacility method ConfiguredExternally which instructs Windsor not to load your log4net.config file and allows you to do that yourself before calling the facility.

I assume you've got 2 appenders in one log (i.e. the root log). Have you tried using 2 separate logs, e.g. <root /> and <logger name="hangfire" />.

You can then override the log name in Windsor:

container.AddFacility<LoggingFacility>(f => f.LogUsing<TLoggerFactory>()
    .WithConfig(configFile)
    .ToLog(logName)
);

See the log4net docs for more details:
https://logging.apache.org/log4net/release/manual/configuration.html

Since you are doing quite a bit of stuff with log4net, you are probably best served using the LoggingFacility method ConfiguredExternally which instructs Windsor not to load your log4net.config file and allows you to do that yourself before calling the facility.

Sorry, i should have posted more about that. Acutally i'm using two separate logs: and one for Hangfire using the hangfire appender :

<root>
      <level value="DEBUG" />
      <appender-ref ref="RollingFile" />
      <appender-ref ref="Console" />
    </root>
    <logger additivity="false" name="Hangfire">
      <level value="INFO" />
      <appender-ref ref="HangfireLoggerAppender" />
    </logger>

I have tried your code :

hangfireContainer.AddFacility<LoggingFacility>(f => f.LogUsing<ILoggerFactory>()
                .WithConfig("Web.config")
                .ToLog("Hangfire")
            );

but i got an exception Facility of type 'Castle.Facilities.Logging.LoggingFacility' has already been registered with the container. Only one facility of a given type can exist in the container.

But i suppose that's because i have already added that facility in my installers ? I should maybe refactor my installers to avoid this.
Thanks.

Correct, you can only register the facility once per container.

Also f.LogUsing<ILoggerFactory> is incorrect. I had TLoggerFactory as I just copied the method signature. We've deprecated UseLog4Net() as it just uses reflection to create Log4netFactory. It still works, but should instead use f.LogUsing<Log4netFactory>.