Logging with Castle.Facilities.Logging and log4net

前端 未结 6 1662
轻奢々
轻奢々 2020-12-06 11:49

I\'m trying to get log4net integration for Castle Windsor working. I wrote my class with an public property of type ILogger and took the configuration in my app

相关标签:
6条回答
  • 2020-12-06 12:17

    I was missing the following NuGet package.

    Castle.Windsor-log4net

    Install-Package Castle.Windsor-log4net
    

    Fixed it.

    0 讨论(0)
  • 2020-12-06 12:23

    Note that you can use the following in recent Castle versions:

    container.AddFacility<LoggingFacility>(f => f.UseLog4Net().WithAppConfig());
    

    This will use Log4net for logging and search for the log4net config section in the application configuration file.

    0 讨论(0)
  • 2020-12-06 12:29

    Following recent Castle conventions (correct me if wrong), I have solved it this way:

    using Castle.Facilities.Logging;
    using Castle.MicroKernel.Registration;
    using Castle.MicroKernel.SubSystems.Configuration;
    using Castle.Windsor;
    
    namespace EVRM.Aspects.Container.Installers
    {
       public class LoggingInstaller : IWindsorInstaller
        {
           public void Install(IWindsorContainer container, IConfigurationStore store)
           {
               container.AddFacility<LoggingFacility>(f => f.UseLog4Net(System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile));
           }
        }
    }
    

    I have simply adapted the method provided here: http://docs.castleproject.org/Windsor.Windsor-Tutorial-Part-Five-Adding-logging-support.ashx

    and used the overload of UseLog4Net() that accepts an configuration file parameter.

    0 讨论(0)
  • 2020-12-06 12:31

    Move your log4net configuration to a separate file log4net.config, then refer that file from the facility configuration:

    <facility id="loggingfacility" configfile="log4net.config" loggingapi="log4net" type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"/>
    

    If you want to have your log4net configuration in a section of your app.config:

    public class MyLog4NetFactory: Log4netFactory {
        public MyLog4NetFactory() {
            XmlConfigurator.Configure();
        }
    
        public override ILogger Create(String name) {
            ILog log = LogManager.GetLogger(name);
            return new Log4netLogger(log.Logger, this);
        }
    
        public override ILogger Create(String name, LoggerLevel level) {
            throw new NotSupportedException("Logger levels cannot be set at runtime. Please review your configuration file.");
        }
    }
    

    then register the facility as:

    <facility 
      id="loggingfacility" 
      loggingapi="custom" 
      customLoggerFactory="[fully qualified type name of MyLog4NetFactory]" 
      type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"/>
    
    0 讨论(0)
  • 2020-12-06 12:31

    This is the entire configuration for the sample given here Home » MicroKernel/Windsor » Getting Started » Part 1 - The basics

    <configuration>
      <configSections>
        <section
            name="castle"
            type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
      </configSections>
      
    
      <castle>
        <facilities>
        <facility
             id="logging"
             type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"
             loggingApi="log4net"
             configFile="D:\\Backup-E\\My Work\\.NET\\CastleWindsorPOC\\CastleWindosorApp\\CastleWindosorApp\\Log4Net.xml" />
        </facilities>
        <components>
          <component
              id="httpservicewatcher"
              type="CastleWindosorApp.HttpServiceWatcher, CastleWindosorApp" >
            <parameters>
              <notifiers>
                <array>
                  <item>${email.notifier}</item>
                  <item>${alarm.notifier}</item>
                </array>
              </notifiers>
              <Url>test url</Url>
              <!--<Logger>${logger.component}</Logger>-->
            </parameters>
          </component>
          
          <component
              id="email.notifier"
              service="CastleWindosorApp.IFailureNotifier, CastleWindosorApp"
              type="CastleWindosorApp.EmailFailureNotifier, CastleWindosorApp" />
    
          <component
              id="alarm.notifier"
              service="CastleWindosorApp.IFailureNotifier, CastleWindosorApp"
              type="CastleWindosorApp.AlarmFailureNotifier, CastleWindosorApp" />
         <!--<component
              id="logger.component"
              service="Castle.Core.Logging.ILogger, Castle.Core"
              type="Castle.Services.Logging.Log4netIntegration.Log4netLogger, Castle.Services.Logging.Log4netIntegration" />-->
          <component
              id="form.component"
              type="CastleWindosorApp.Form1, CastleWindosorApp" />
     
    
        </components>
    
      </castle>
    

    The mistake I did was (as you can see the sections commented in the config file), tried to assign the Logger property once again in my class by registering the component in castle. this is not required as Castle does this automatically for you.

    Cheers Badal

    0 讨论(0)
  • 2020-12-06 12:37

    You can use App.config for your log4net configuration without creating a custom logging factory. Simply provide the App.config file as an argument to the LoggingFacility constructor:

    container
        .AddFacility("logging",
            new LoggingFacility(LoggerImplementation.Log4net,
                System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)
            )
    

    Unlike Mauricio Scheffer's answer, the default factory does ConfigureAndWatch. This works just fine for me with the App.config file, though I'm not running on IIS or anything else that restricts permissions.

    I'm doing this in code because you can't reliably use the Windsor Xml configuration to load log4net configuration from App.config. This is because the location of App.config can be modified when creating a new AppDomain.

    Using my solution means the log file configuration will be compiled into your code. But you can mitigate this by using a Windsor Installer to configure logging, and specify the installer (or installer assembly) from the App.config file:

    public class LoggingInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container
                .AddFacility("logging",
                    new LoggingFacility(LoggerImplementation.Log4net,
                        System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)
                    );
        }
    }
    

    ...

    <castle>
        <installers>
            <install assembly="MyAssemblyName" />
        </installers>
    </castle>
    

    If in the future (maybe in your test cases) you have to load the logging configuration from a different file, and can't or don't want to recompile, simply change the Xml to point to Windsor Installers in a different assembly:

    <castle>
        <installers>
            <install assembly="SomeOtherAssemblyName" />
        </installers>
    </castle>
    
    0 讨论(0)
提交回复
热议问题