NLog 自定义 FileTarget

NLog custom FileTarget

我为 Sentinel 定制了 NLogViewerTarget (NLogViewerEx),如下所示:

现在我也想为我的 FileTarget 设置格式化的消息,但是当我应用它时,它不再工作(记录)了。

<targets async="true">
    <target
      xsi:type="FileTargetEx"
      name="file"
      layout="${longdate} - ${level:uppercase=true}: ${message}${onexception:${newline}exception\: ${exception:format=tostring}}"
      filename="${specialfolder:folder=commonapplicationdata}/company gmbh/${appname}/logs/${appname}.log"
      keepfileopen="false"
      archivefilename="${specialfolder:folder=commonapplicationdata}/company gmbh/${appname}/logs/${appname}_archive.{##}.zip"
      archivenumbering="dateandsequence"
      archiveevery="day"
      maxarchivefiles="50"
      archivedateformat="yyyy-mm-dd"
      archiveoldfileonstartup="true"
      createdirs="true"
      enablearchivefilecompression="true"
      encoding="utf-8"
      header="############################################## ${appname} log ##############################################"
      archiveabovesize="10485760"/>


    <target xsi:type="NLogViewerEx"
              name="sentinel"
              address="udp://127.0.0.1:9999"/>
  </targets>

我也尝试过自定义 FileTarget,但这也行不通。有人知道如何应用它吗?

[Target("FileTargetEx")]
internal class FileTargetEx : FileTarget
{
    private readonly Log4JXmlEventLayoutEx _Layout = new Log4JXmlEventLayoutEx();

    public override Layout Layout { get { return _Layout; } set { } }
}

我给了 File Target xsi:type FileTargetExxsi:type NLogViewerEx,但没有成功。如果我这样做,Sentinel 和 File 将不再记录!

调试

启用内部调试日志后,我得到以下日志:

2017-12-13 09:32:52.6572 Info Loading assembly: HtCore
2017-12-13 09:32:52.6834 Debug ScanAssembly('NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c')
2017-12-13 09:32:52.7356 Debug Start auto loading, location: D:\Repositories\gitlab.company\dotNet\HtCore\HtCore\TestConsole\bin\Debug
2017-12-13 09:32:52.7356 Debug Auto loading done
2017-12-13 09:32:52.7496 Debug ScanAssembly('HtCore, Version=1.4.0.8, Culture=neutral, PublicKeyToken=null')
2017-12-13 09:32:52.7797 Debug Setting 'UppercaseLayoutRendererWrapper.uppercase' to 'true'
2017-12-13 09:32:52.7797 Debug Setting 'FileTargetEx.name' to 'file'
2017-12-13 09:32:52.7978 Debug Setting 'FileTargetEx.filename' to '${specialfolder:folder=commonapplicationdata}/company gmbh/Testconsole/logs/Testconsole.log'
2017-12-13 09:32:52.7978 Debug Setting 'SpecialFolderLayoutRenderer.folder' to 'commonapplicationdata'
2017-12-13 09:32:52.8108 Debug Setting 'FileTargetEx.keepfileopen' to 'false'
2017-12-13 09:32:52.8108 Debug Setting 'FileTargetEx.archivefilename' to '${specialfolder:folder=commonapplicationdata}/company gmbh/Testconsole/logs/Testconsole_archive.{##}.zip'
2017-12-13 09:32:52.8108 Debug Setting 'SpecialFolderLayoutRenderer.folder' to 'commonapplicationdata'
2017-12-13 09:32:52.8278 Debug Setting 'FileTargetEx.archivenumbering' to 'dateandsequence'
2017-12-13 09:32:52.8278 Debug Setting 'FileTargetEx.archiveevery' to 'day'
2017-12-13 09:32:52.8429 Debug Setting 'FileTargetEx.maxarchivefiles' to '50'
2017-12-13 09:32:52.8429 Debug Setting 'FileTargetEx.archivedateformat' to 'yyyy-mm-dd'
2017-12-13 09:32:52.8429 Debug Setting 'FileTargetEx.archiveoldfileonstartup' to 'true'
2017-12-13 09:32:52.8634 Debug Setting 'FileTargetEx.createdirs' to 'true'
2017-12-13 09:32:52.8634 Debug Setting 'FileTargetEx.enablearchivefilecompression' to 'true'
2017-12-13 09:32:52.8758 Debug Setting 'FileTargetEx.encoding' to 'utf-8'
2017-12-13 09:32:52.8758 Debug Setting 'FileTargetEx.header' to '############################################## Testconsole log ##############################################'
2017-12-13 09:32:52.8968 Warn Error when setting '############################################## ${appname} log ##############################################' on attibute 'header'
2017-12-13 09:32:52.9028 Error Parsing configuration from D:\Repositories\gitlab.company\dotNet\HtCore\HtCore\TestConsole\bin\Debug\NLog.config failed. Exception: NLog.NLogConfigurationException: Exception when parsing D:\Repositories\gitlab.company\dotNet\HtCore\HtCore\TestConsole\bin\Debug\NLog.config.  ---> NLog.NLogConfigurationException: Error when setting property 'Header' on FileTargetEx Target[file] ---> System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
   bei NLog.Targets.TargetWithLayoutHeaderAndFooter.set_Header(Layout value)
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei NLog.Internal.PropertyHelper.SetPropertyFromString(Object obj, String propertyName, String value, ConfigurationItemFactory configurationItemFactory)
   bei NLog.Config.XmlLoggingConfiguration.ConfigureObjectFromAttributes(Object targetObject, NLogXmlElement element, Boolean ignoreType)
   bei NLog.Config.XmlLoggingConfiguration.ParseTargetElement(Target target, NLogXmlElement targetElement, Dictionary`2 typeNameToDefaultTargetParameters)
   bei NLog.Config.XmlLoggingConfiguration.ParseTargetsElement(NLogXmlElement targetsElement)
   bei NLog.Config.XmlLoggingConfiguration.ParseNLogElement(NLogXmlElement nlogElement, String filePath, Boolean autoReloadDefault)
   bei NLog.Config.XmlLoggingConfiguration.ParseTopLevel(NLogXmlElement content, String filePath, Boolean autoReloadDefault)
   bei NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
   --- Ende der internen Ausnahmestapelüberwachung ---
2017-12-13 09:32:52.9028 Debug --- NLog configuration dump ---

Nlog.conf

<?xml version="1.0" encoding="utf-8" ?>
<nlog
  xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
  autoReload="true"
  internalLogFile="c:\log.txt" 
  internalLogLevel="Debug">
  <extensions>
    <add assembly="HtCore"/>
  </extensions>
  <variable name="appname" value="Testconsole" />

  <targets async="true">
    <target
      xsi:type="FileTargetEx"
      name="file"
      filename="${specialfolder:folder=commonapplicationdata}/company gmbh/${appname}/logs/${appname}.log"
      keepfileopen="false"
      archivefilename="${specialfolder:folder=commonapplicationdata}/company gmbh/${appname}/logs/${appname}_archive.{##}.zip"
      archivenumbering="dateandsequence"
      archiveevery="day"
      maxarchivefiles="50"
      archivedateformat="yyyy-mm-dd"
      archiveoldfileonstartup="true"
      createdirs="true"
      enablearchivefilecompression="true"
      encoding="utf-8"
      header="############################################## ${appname} log ##############################################"
      archiveabovesize="10485760"/>


    <target xsi:type="NLogViewerEx"
              name="sentinel"
              address="udp://127.0.0.1:9999"/>
  </targets>
  <rules>
    <logger name="*" writeTo="file" minlevel="Info"/>
    <logger name="*" writeTo="sentinel" minlevel="Info"/>
  </rules>
</nlog>

C#Class

[Target("FileTargetEx")]
internal class FileTargetEx : NLog.Targets.FileTarget
{
    private readonly FileLayout _Layout = new FileLayout();

    public override Layout Layout { get { return _Layout; } set { } }
}

internal class FileLayout : NLog.Layouts.SimpleLayout
{

}

我总是遇到同样的错误。如果我将 FileLayout 设置为 Layout 或我正在与 Sentinel.

一起使用的其他 Layout 并不重要

当取消注释 Layout override 时,它正在加载 NLog.conf..

工作解决方案

如果有更好的解决方案,请告诉我!

/// <summary>
/// is using the <see cref="FileLayoutEx"/> class.
/// </summary>
[Target("FileTargetEx")]
internal class FileTargetEx : FileTarget
{
    public override Layout Layout
    {
        get => _Layout;
        set
        {
            base.Layout = new FileLayoutEx((value as SimpleLayout).OriginalText);
            _Layout = new FileLayoutEx((value as SimpleLayout).OriginalText);
        }
    }
    private Layout _Layout;

    public FileTargetEx()
    {
        Footer = new FileLayoutEx();
        Header = new FileLayoutEx();
    }
}

/// <summary>
/// Provides a formated message (Exception included!).
/// </summary>
[Layout("FileLayoutEx")]
internal class FileLayoutEx : SimpleLayout
{
    public FileLayoutEx() { }

    public FileLayoutEx(string originalText) : base(originalText) { }

    protected override string GetFormattedMessage(LogEventInfo logEvent)
    {
        //Extension method is outsourced
        LogEventInfo updatedInfo = logEvent.GetFormattedMessage();
        return base.GetFormattedMessage(updatedInfo);
    }
}

NLog.conf 目标

<target
  xsi:type="FileTargetEx"
  name="file"
  filename="${specialfolder:folder=commonapplicationdata}/company gmbh/${appname}/logs/${appname}.log"
  keepfileopen="false"
  archivefilename="${specialfolder:folder=commonapplicationdata}/company gmbh/${appname}/logs/${appname}_archive.{##}.zip"
  archivenumbering="dateandsequence"
  archiveevery="day"
  maxarchivefiles="50"
  archivedateformat="yyyy-mm-dd"
  archiveoldfileonstartup="true"
  createdirs="true"
  enablearchivefilecompression="true"
  encoding="utf-8"
  header="############################################## ${appname} log ##############################################"
  layout="${longdate}|${level:uppercase=true}|${logger}|${message}"
  archiveabovesize="10485760"/>