如何在运行时拦截和替换Quartz.NET的默认日志记录?

时间:2015-02-22 12:09:51

标签: log4net quartz.net

为了消除人为错误并避免维护谁知道多少App.config个文件,我决定在运行时设置所有Quartz.NET作业的Log4Net配置,完全在码。不允许App.config个文件。我已经成功地获得了一个独立的控制台应用程序来执行此操作,如here所示。

然而,在调度程序本身中它是一个不同的故事。由于某种原因,它没有使用我指定的配置:

Dim oProperties As New NameValueCollection

' ... Set Quartz.NET properties here

BasicConfigurator.Configure(New Logger.DbAppender)

With New StdSchedulerFactory(oProperties)
  Manager.Scheduler = .GetScheduler
End With

我将它作为TopShelf服务运行,我希望Scheduler的日志与每个IJob的目标相同。在这里,Quartz.NET顽固地继续将其输出发送到TopShelf的调试控制台窗口(STDOUT)。

此构造在控制台应用程序中工作(上面链接);为什么不在这里工作?

2 个答案:

答案 0 :(得分:1)

好的,明白了。 (这次是真实的。)

澄清:当在TopShelf / Quartz.NET组合下运行时,在.config中发生在没有Common.Logging文件的情况下对日志记录的抑制。由于某种原因,它始终拒绝识别运行时加载的Appender,即使服务中的第一行代码配置日志记录也是如此。仍然是一个谜,但并不重要。 (至少不适合我,这个最新的发现 - YMMV。)

唯一被抑制的日志记录是在Common.Logging库本身的构建和拆除之后;服务本身发生的所有事情仍然会被记录下来。

我能够使用下面的代码使其工作(当然,结合上面链接的代码)。

正如我所说,YMMV。

[服务]

Public Module Main
  Sub Main()
    Try
      BasicConfigurator.Configure(New Logger.DbAppender("ConnectionString"))
      Logger = LogManager.GetLogger(GetType(Main))

      Environment.ExitCode = HostFactory.Run(Sub(Configurator)
                                               Configurator.Service(Of Manager)(Sub(Service)
                                                                                  Service.ConstructUsing(Function(Factory) As ServiceControl
                                                                                                           Return New Manager
                                                                                                         End Function)

                                                                                  Service.WhenStarted(Function(Manager, HostControl) As Boolean
                                                                                                        Return Manager.StartService(HostControl)
                                                                                                      End Function)

                                                                                  Service.WhenStopped(Function(Manager, HostControl) As Boolean
                                                                                                        Return Manager.StopService(HostControl)
                                                                                                      End Function)
                                                                                End Sub)

                                               Configurator.SetDescription(ServiceInfo.Description)
                                               Configurator.SetServiceName(ServiceInfo.Product)
                                               Configurator.SetDisplayName(ServiceInfo.Title)
                                               Configurator.StartAutomatically()
                                               Configurator.RunAsLocalSystem()
                                             End Sub)

    Catch ex As Exception
      EventLog.WriteEntry(ServiceInfo.Product, ex.Message, EventLogEntryType.Error, 1, 1, ex.ToBytes)

    End Try
  End Sub



  Public Property Logger As ILog
End Module

[DbAppender](更新w / add'l构造函数,接受连接字符串)

Public Class DbAppender
  Inherits AdoNetAppender

  Public Sub New()
    Me.New(String.Empty)
  End Sub



  Public Sub New(ConnectionString As String)
    If Trim(ConnectionString) <> String.Empty Then
      MyBase.ConnectionString = ConnectionString
    End If

    MyBase.CommandText = Me.CommandText
    MyBase.BufferSize = 1

    Me.Parameters.ForEach(Sub(Parameter As DbParameter)
                            MyBase.AddParameter(Parameter)
                          End Sub)

    Me.ActivateOptions()
  End Sub



  Protected Overrides Function CreateConnection(ConnectionType As Type, ConnectionString As String) As IDbConnection
    Return MyBase.CreateConnection(GetType(System.Data.SqlClient.SqlConnection), MyBase.ConnectionString)
  End Function



  Private Overloads ReadOnly Property CommandText As String
    Get
      Dim _
        sColumns,
        sValues As String

      sColumns = Join(Me.Parameters.Select(Function(P As DbParameter) P.DbColumn).ToArray, ",")
      sValues = Join(Me.Parameters.Select(Function(P As DbParameter) P.ParameterName).ToArray, ",")

      Return COMMAND_TEXT.ToFormat(sColumns, sValues)
    End Get
  End Property



  Private ReadOnly Property Parameters As List(Of DbParameter)
    Get
      Parameters = New List(Of DbParameter)
      Parameters.Add(Me.Date)
      Parameters.Add(Me.Thread)
      Parameters.Add(Me.Level)
      Parameters.Add(Me.Source)
      Parameters.Add(Me.Message)
      Parameters.Add(Me.Exception)
    End Get
  End Property



  Private ReadOnly Property [Date] As DbParameter
    Get
      Return New DbParameter("Date", New DbPatternLayout(PATTERN_DATE), DbType.Date, 0)
    End Get
  End Property



  Private ReadOnly Property Thread As DbParameter
    Get
      Return New DbParameter("Thread", New DbPatternLayout(PATTERN_THREAD), DbType.String, 255)
    End Get
  End Property



  Private ReadOnly Property Level As DbParameter
    Get
      Return New DbParameter("Level", New DbPatternLayout(PATTERN_LEVEL), DbType.String, 50)
    End Get
  End Property



  Private ReadOnly Property Source As DbParameter
    Get
      Return New DbParameter("Source", New DbPatternLayout(PATTERN_SOURCE), DbType.String, 255)
    End Get
  End Property



  Private ReadOnly Property Message As DbParameter
    Get
      Return New DbParameter("Message", New DbPatternLayout(PATTERN_MESSAGE), DbType.String, 4000)
    End Get
  End Property



  Private ReadOnly Property Exception As DbParameter
    Get
      Return New DbParameter("Exception", New DbExceptionLayout)
    End Get
  End Property



  Private Const PATTERN_MESSAGE As String = "%message"
  Private Const PATTERN_THREAD As String = "%thread"
  Private Const PATTERN_SOURCE As String = "%logger.%M()"
  Private Const PATTERN_LEVEL As String = "%level"
  Private Const PATTERN_DATE As String = "%date{yyyy-MM-dd HH:mm:ss.fff}"
  Private Const COMMAND_TEXT As String = "INSERT INTO Log ({0}) VALUES ({1})"
  '======================================================================================
  ' Available patterns:
  ' http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html
  '======================================================================================
End Class

答案 1 :(得分:0)

好的,明白了。 (这没用多久!)

出于某种原因,如果缺少必要的App.config条目,TopShelf / Quartz.NET组合会坚持抑制日志输出。

在这种情况下,由于它是我们处理的中央调度程序,而不是过多的工作,我会咬紧牙关并继续使用App.config文件对于这一个。

所以根本问题仍未解决;这只是暂时的解决方法。如果您知道答案,我仍然很高兴收到您的回复。感谢。