0

我还没有找到解决问题的方法。在某些情况下,我的应用程序中有错误,我必须将其记录到单独的日志文件中。其中一些错误的问题在于它们包含大量数据,我希望将日志条目放在单独的文件中以便稍后分析它们。目前我只是将消息记录到全局日志文件中,然后手动将日志条目的开始和结束标签(XML、JSON)复制并粘贴到另一个文件中,保存并在 JSON/XML 查看器中打开它。我认为最好的方法是为每个日志条目编写一个具有唯一文件名的目录,并使用此文件名作为日志条目对全局日志文件进行反向引用。但这只是我的拙见,也许有更好的解决方案。你有一个?:)

目前我正在使用 NLog,但如果 NLog 无法实现,我也可以将图像更改为 Serilog。我还要说,在代码中记录消息的方式不应该是这样的:

    public class TestClass
    {
        private static readonly Logger Log = LogManager.GetCurrentClassLogger();

        private void Work()
        {
            var json/xml = ...
            Log.Error(json/xml);
        }

    }

因为它关注日志配置如何将其写入文件、数据库等。

谢谢。

4

3 回答 3

1

如果只生成一个 LogEvent 真的很重要,那么您可以这样做:

public class TestClass
{
    private static readonly Logger Log = LogManager.GetCurrentClassLogger();

    private void Work()
    {
        var json/xml = ...
        Log.WithProperty("Blob", json/xml).Error("Hello World);;
    }

}

然后在你的 NLog.config 中执行此操作:

<targets>
    <target name="logfile" xsi:type="File" fileName="file.txt" layout="${message}${when:when=length('${event-properties:Blob}') > 0:inner= BlobGuid-${guid:GeneratedFromLogEvent=true}}"/>
    <target name="blobfile" xsi:type="File" fileName="Blob.${shortdate}.${guid:GeneratedFromLogEvent=true}.txt" layout="${event-properties:Blob}" />
</targets>

<rules>
    <logger name="BlobLog" minlevel="Trace" writeTo="blobfile">
       <filters defaultAction='Ignore'>
          <when condition="length('${event-properties:Blob}') > 0" action="Log" />
       </filters>
    </logger>
    <logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>

这将重用相同的 LogEvent 来写入两个文件。

于 2020-04-11T09:16:05.413 回答
1

简单的解决方案就是这样做(确保 Blob 输出突然不会在不需要的地方传播):

public class TestClass
{
    private static readonly Logger Log = LogManager.GetCurrentClassLogger();
    private static readonly Logger BlobLog = LogManager.GetLogger("BlobLog");

    private void Work()
    {
        var correlationId = Guid.NewGuid().ToString();
        Log.WithProperty("BlobGuid", correlationId).Error("Hello");
        var json/xml = ...
        BlobLog.WithProperty("BlobGuid", correlationId).Error(json/xml);
    }

}

然后在你的 NLog.config 中执行此操作,${event-properties:BlobGuid}确保新文件:

<targets>
    <target name="logfile" xsi:type="File" fileName="file.txt" layout="${longdate}|${level}|${logger}|${message} BlobGuid=${event-properties:BlobGuid}" />
    <target name="blobfile" xsi:type="File" fileName="blob.${shordate}.${event-properties:BlobGuid}.txt" layout="${message}" />
</targets>

<rules>
    <logger name="BlobLog" minlevel="Trace" writeTo="blobfile" final="true" />
    <logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>

有很多方法可以将上下文添加到 LogEvent。另请参阅https://github.com/NLog/NLog/wiki/Context

LogEvent 上下文可用于日志记录规则过滤。另请参阅https://github.com/nlog/NLog/wiki/Filtering-log-messages

你也可以在 NLog Layouts 中使用 LogEvent-context,FileTarget Filename 是一个 NLog Layout。所以同一个文件目标可以根据 LogEvent 上下文写入不同的文件名。

于 2020-04-11T08:44:00.923 回答
1

这是一种使用 Serilog 的可能方法,利用接收器FileMap

  • 将常规日志消息写入名为的文件Application.log(即日志消息中没有大数据的任何内容)
  • 将大数据消息写入名为Data_{uniqueId}.log
  • 使用一个名为的属性LargeDataId来存储将存储大数据的文件的唯一 ID,并使用此属性来确定消息是否是常规日志消息(即,如果LargeDataId存在属性,则它会在个人文件,否则它是一条常规消息并转到Application.log

public class TestClass
{
    private readonly ILogger _logger = Log.ForContext<TestClass>();

    public void Work()
    {
        var jobId = Guid.NewGuid();

        // Writes to Application.log
        _logger.Error("Error executing job {JobId}", jobId);

        var jsonOrXml = "...";

        // Writes to Data_{uniqueId}.log
        _logger.Error("{LargeDataId}{LargeData}", jobId, jsonOrXml);
    }
}

您的 Serilog 日志记录管道配置如下所示:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Logger(c =>
        c.Filter.ByExcluding(e => e.Properties.ContainsKey("LargeData"))
            .WriteTo.File("Application.log"))
    .WriteTo.Map("LargeDataId", (id, wt) =>
            wt.File($"Data_{id}.txt", outputTemplate: "{LargeData}"),
                sinkMapCountLimit: 0)
    .CreateLogger();
于 2020-04-11T19:24:03.937 回答