nlog自定义目标不在.net core 2.0之后记录

问题描述 投票:1回答:1

在将我们的项目提升到.NET Standard 2.0之后,我们遇到了Nlog的问题。似乎自定义targes Write()-method不会触发。

你们中的任何人都有同样的问题或想法如何解决问题?

注册自定义目标:

GlobalDiagnosticsContext.Set("configDir", Directory.GetCurrentDirectory());
ConfigurationItemFactory.Default.Targets.RegisterDefinition("DatabaseLog", typeof(MultiTenantDataBaseLogTarget));

var connectionString = Common.Lib.AppSettingsReader.GetConnectionString("DefaultConnection");

if (string.IsNullOrEmpty(connectionString)) // to support the .NET Framework Service DataProvider connectionString = ConfigurationManager.ConnectionStrings["localRuleContext"].ConnectionString;
LogManager.Configuration.Variables["connectionString"] = connectionString;

自定义目标:

using NLog;
using NLog.Common;
using NLog.Targets;

namespace OurNamespace.Logging
{
    [Target("DatabaseLog")]
    public class MultiTenantDataBaseLogTarget : DatabaseTarget
    {
        protected override void Write(AsyncLogEventInfo logEvent)
        {
            CommandText = $@"
                    insert into {logEvent.LogEvent.Properties["SchemaName"]}.ProtocolLogs (
                        Timestamp, LogLevel, MessageKey, Message, Parameters, [User], ApplicationName, Action, ObjectId, ObjectName
                    ) values (
                        @Timestamp, @LogLevel, @MessageKey, @Message, @Parameters, @User, @ApplicationName, @Action, @ObjectId, @ObjectName
                    );";

            base.Write(logEvent);
        }

        protected override void Write(LogEventInfo logEvent)
        {
            CommandText = $@"
                    insert into {logEvent.Properties["SchemaName"]}.ProtocolLogs (
                        Timestamp, LogLevel, MessageKey, Message, Parameters, [User], ApplicationName, Action, ObjectId, ObjectName
                    ) values (
                        @Timestamp, @LogLevel, @MessageKey, @Message, @Parameters, @User, @ApplicationName, @Action, @ObjectId, @ObjectName
                    );";

            base.Write(logEvent);
        }
    }
}

nlog.config

<?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"
      throwExceptions="true"
      autoReload="true"
      internalLogLevel="Trace"
      internalLogFile=".\Logs\internal-nlog.txt">

  <extensions>
    <add assembly="NLog.Targets.ElasticSearch"/>
    <add assembly="NLog.Web.AspNetCore"/>
  </extensions>

  <targets>
    <target name="DatabaseLog" xsi:type="Database" >
      <connectionString>${var:connectionstring}</connectionString>

      <commandText>
        insert into Schema.ProtocolLogs (
Timestamp, [LogLevel], MessageKey, Message, Parameters, [User], ApplicationName, Action, ObjectId
        ) values (
@Timestamp, @LogLevel, @MessageKey, @Message, @Parameters, @User, @ApplicationName, @Action, @ObjectId);
      </commandText>

      <parameter name="@Timestamp" layout="${event-properties:Timestamp:format=yyyy-MM-dd HH\:mm\:ss.fff}" />
      <parameter name="@LogLevel" layout="${event-properties:LogLevel}" />
      <parameter name="@MessageKey" layout="${event-properties:MessageKey}" />
      <parameter name="@Message" layout="${message}" />
      <parameter name="@Parameters" layout="${event-properties:Parameters}" />
      <parameter name="@User" layout="${event-properties:User}" />
      <parameter name="@ApplicationName" layout="${event-properties:ApplicationName}" />
      <parameter name="@Action" layout="${event-properties:Action}" />
      <parameter name="@ObjectId" layout="${event-properties:ObjectId}" />
      <parameter name="@ObjectName" layout="${event-properties:ObjectName}" />

    </target>

  </targets>

  <rules>
    <logger name="DatabaseLog" minlevel="Trace" writeTo="DatabaseLog" />
  </rules>
</nlog>

这就是我们进行日志调用的方式:

var theEvent = new LogEventInfo(nLogLevel, logFilterName, message);
theEvent.Properties["SchemaName"] = _schemaTarget;
// more properties added...
var logger = LogManager.GetLogger("DatabaseLog");
logger.Log(theEvent)

使用Framework 4.5,这段代码可以正常运行。现在看起来,logger.Log(theEvent)只是直接写入数据库跳过我们的自定义方法。

c# nlog .net-standard-2.0
1个回答
1
投票

首先,您将自定义目标注册为type="DatabaseLog"

ConfigurationItemFactory.Default.Targets.RegisterDefinition("DatabaseLog", typeof(MultiTenantDataBaseLogTarget));

但是,然后配置标准目标type="Database"

<target name="DatabaseLog" xsi:type="Database">

但不是使用自定义目标,我建议你只需将<commandText>更改为:

<target name="DatabaseLog" xsi:type="Database">
   <connectionString>${var:connectionstring}</connectionString>

   <commandText>
        insert into ${event-properties:item=SchemaName}.ProtocolLogs (
Timestamp, [LogLevel], MessageKey, Message, Parameters, [User], ApplicationName, Action, ObjectId
        ) values (
@Timestamp, @LogLevel, @MessageKey, @Message, @Parameters, @User, @ApplicationName, @Action, @ObjectId);
   </commandText>
</target>

请注意,我刚刚插入了${event-properties:item=SchemaName},因此NLog将自动呈现CommandText,以便您可以完全删除MultiTenantDataBaseLogTarget(提高性能并允许您使用NLog AsyncWrapper)。

请注意,如果您需要默认的SchemaName,则可以考虑使用${whenEmpty}。另见:https://github.com/NLog/NLog/wiki/WhenEmpty-Layout-Renderer

© www.soinside.com 2019 - 2024. All rights reserved.