Quartz.Net,使用Log4Net和Common.Logging进行日志记录会引发"未知日志级别"

时间:2015-10-09 00:06:36

标签: ninject log4net quartz.net common.logging

我有一个Azure云服务,它使用Quartz.Net(2.3.2)来运行计划任务。我的主要日志引擎是Log4Net(2.0.3),我使用Common.Logging.Log4Net1213(3.0.0)来桥接Common.Logging和Log4Net。我正在使用自己的" NinjectJobFactory"创建所有作业及其依赖项(它实现IJobFactory)。我的计划启动代码如下所示:

  _scheduler = factory.GetScheduler();
  _scheduler.JobFactory = new NinjectJobFactory(_kernel);
  _scheduler.Start();

一切都适用于正常的日常日志记录(Quartz启动和关闭,NServiceBus启动,任务启动,作业内的异常处理等)。我遇到的问题是上面任何一行中都有一个致命异常会阻止Quartz启动。 (通常,这是因为我未能正确地包含或配置其中一个作业需要的依赖项)。在这种情况下,我没有记录真正的问题,而是在Log4NetLogger.cs中得到一个异常,抱怨未知的日志记录级别,并且从不浮出或记录底层异常。我必须打破捕获的异常才能看到底层异常。有人可以建议修复吗?提前致谢!

堆栈跟踪如下所示:

  

Microsoft.WindowsAzure.ServiceRuntime严重:1:未处理   异常:System.ArgumentOutOfRangeException:未知的日志级别   参数名称:logLevel实际值为Error。在   Common.Logging.Log4Net.Log4NetLogger.GetLevel(LogLevel logLevel)in   C:_oss \共记录\ SRC \ Common.Logging.Log4Net129 \记录\ log4net的\ Log4NetLogger.cs:线   180.在Common.Logging.Log4Net.Log4NetLogger.WriteInternal(LogLevel   logLevel,Object message,Exception exception)in   C:_oss \共记录\ SRC \ Common.Logging.Log4Net129 \记录\ log4net的\ Log4NetLogger.cs:线   140.在Common.Logging.Factory.AbstractLogger.Error(对象消息,   例外情况)   C:_oss \共记录\ SRC \ Common.Logging.Portable \记录\厂\ AbstractLogger.cs:线   806在Quartz.Simpl.SimpleThreadPool.WorkerThread.Run()中   c:\ Program Files   (86)\詹金斯\工作空间\ Quartz.NET \ SRC \石英\ SIMPL \ SimpleThreadPool.cs:线   492在   System.Threading.ExecutionContext.RunInternal(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态,布尔值   preserveSyncCtx)at   System.Threading.ExecutionContext.Run(执行上下文   executionContext,ContextCallback回调,对象状态)at   System.Threading.ThreadHelper.ThreadStart()

app.config中的common.logging配置为:

<common>
    <logging>
      <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net1213">
        <arg key="configType" value="FILE" />
        <arg key="configFile" value="log4net.config" />
      </factoryAdapter>
    </logging>
  </common>

最后,我的log4net.config是:

<log4net>
  <appender name="ErrorAppender" type="log4net.Appender.BufferingForwardingAppender">
    <bufferSize value="1" />
    <lossy value="true" />
    <evaluator type="log4net.Core.LevelEvaluator">
      <threshold value="INFO" />
    </evaluator>
    <appender-ref ref="TraceAppender" />
  </appender>
  <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
    <threshold value="INFO" />
    <filter type="log4net.Filter.LoggerMatchFilter">
      <loggerToMatch value="NServiceBus.Azure.Transports.WindowsAzureServiceBus.AzureServiceBusQueueCreator" />
      <acceptOnMatch value="false" />
    </filter>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%message%newline" />
    </layout>
  </appender>
  <root>
    <level value="ALL" />
    <appender-ref ref="ErrorAppender" />
  </root>
</log4net>

2 个答案:

答案 0 :(得分:2)

这可能听起来很傻,但我遇到了完全相同的问题,我通过确保common.logging,common.logging.core和common.logging.log4net1213的版本都是相同的版本来克服它(3.3 0.1)。显然,三个库之间存在版本依赖关系,如果一个与另一个不同版本使用,则会导致这种情况。

以下是您的异常所源自的函数的反编译代码。它来自Common.Logging.Log4Net1213 v3.3.1。此代码的早期版本并未完全考虑Common.Logging.LogLevel.Warn,因此异常落在switch语句的底部:

 public static Level GetLevel(Common.Logging.LogLevel logLevel)
    {
      switch (logLevel)
      {
        case Common.Logging.LogLevel.All:
          return Level.All;
        case Common.Logging.LogLevel.Trace:
          return Level.Trace;
        case Common.Logging.LogLevel.Debug:
          return Level.Debug;
        case Common.Logging.LogLevel.Info:
          return Level.Info;
        case Common.Logging.LogLevel.Warn:
          return Level.Warn;
        case Common.Logging.LogLevel.Error:
          return Level.Error;
        case Common.Logging.LogLevel.Fatal:
          return Level.Fatal;
        default:
          throw new ArgumentOutOfRangeException("logLevel", (object) logLevel, "unknown log level");
      }
    }

就我而言,common.logging.log4net1213是其他版本的一个版本(v3.3.0),因此我将库更新为与其他两个库相同的版本,并且问题已经消失。

祝你好运!

答案 1 :(得分:0)

你能告诉我们你的日志配置吗?

我的Servicebus / log4net / quartz实现成功记录了石英启动问题。这是我使用的启动代码;不确定它是否有帮助,因为没有看到你的代码。

NSB版本4.6.2

public class MyServer : ServiceControl
{
    private readonly ILog logger;
    private ISchedulerFactory schedulerFactory;
    private IScheduler scheduler;

    public static IBus Bus = null;

    public MyServer()
    {
        logger = LogManager.GetLogger(GetType());                       
    }


    public virtual void Initialize()
    {
        try
        {                           
            log4net.GlobalContext.Properties["Job"] = "Quartz";

            Configure.Serialization.Xml();
            Configure.Transactions.Enable();
            SetLoggingLibrary.Log4Net();

            Bus = Configure.With().DefaultBuilder().UnicastBus().SendOnly();

            schedulerFactory = CreateSchedulerFactory();
            scheduler = GetScheduler();
        }
        catch (Exception e)
        {
            logger.Error("Server initialization failed:" + e.Message, e);
            throw;
        }
    } 
}

public class Configuration
{
    private static readonly NameValueCollection configuration;

    static Configuration()
    {
        configuration = (NameValueCollection)ConfigurationManager.GetSection("quartz");
    }


    static public string GetQuartzConfigFileName()
    {
        return configuration["quartz.plugin.xml.fileNames"] as String;
    }
}

我的app配置看起来像这样

<configuration>
  <configSections>
    <section name="quartz" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    <sectionGroup name="common">
      <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
    </sectionGroup>
    </configSections>
  <common>
   <logging>
      <factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4net1211">
        <arg key="configType" value="INLINE" />
      </factoryAdapter>
    </logging>
  </common>
  <log4net debug="false">
    <appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
      <mapping>
        <level value="FATAL" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="ERROR" />
        <foreColor value="Red, HighIntensity" />
      </mapping>
      <mapping>
        <level value="WARN" />
        <foreColor value="Yellow" />
      </mapping>
      <mapping>
        <level value="INFO" />
        <foreColor value="Green" />
      </mapping>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>

    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="GrafOI.Scheduler.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="10000KB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>

    <!-- quartz clutters the logs so turn it off unless an error occurs -->
    <logger name="Quartz">
      <level value="ERROR" />
    </logger>

    <root>
      <level value="DEBUG" />
      <appender-ref ref="AdoNetAppender" />
      <appender-ref ref="EventLogAppender" />
      <appender-ref ref="ColoredConsoleAppender" />
      <appender-ref ref="RollingFileAppender" />
    </root>
  </log4net>
  <quartz>
    <add key="quartz.scheduler.instanceName" value="GrafOI Scheduler" />
    <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
    <add key="quartz.threadPool.threadCount" value="2" />
    <add key="quartz.threadPool.threadPriority" value="Normal" />
    <add key="quartz.jobStore.misfireThreshold" value="60000" />
    <add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
    <add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz" />
    <add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
    <add key="quartz.jobStore.dataSource" value="myDS" />
    <add key="quartz.dataSource.myDS.connectionString" value="server=.;database=GrafOI;Integrated Security=true;" />
    <add key="quartz.dataSource.myDS.provider" value="SqlServer-20" />
    <add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" />
    <add key="quartz.plugin.xml.fileNames" value="~/GrafOI.Scheduler.Jobs.xml" />
    <add key="quartz.jobStore.useProperties" value="true" />

  </quartz>
  <appSettings>

  </appSettings>

</configuration>

也许有些东西可以帮助