NLog - записать запись журнала в другой файл - PullRequest
0 голосов
/ 11 апреля 2020

Я еще не нашел решение проблемы. В некоторых случаях в моем приложении возникают ошибки, которые я должен записать в отдельный файл журнала. Проблема с некоторыми из этих ошибок состоит в том, что они состоят из большого количества данных, и я хотел бы иметь записи журнала в отдельных файлах, чтобы проанализировать их позже. В настоящее время я просто записываю сообщение в глобальный файл журнала, копирую и вставляю начальный и конечный теги (XML, JSON) записей журнала вручную в другой файл, сохраняю его и открываю в JSON / * 1011. * -viewer. Я думаю, что лучше всего было бы иметь каталог с уникальными именами файлов для записи для каждой записи журнала и иметь обратную ссылку на глобальный файл журнала с этим именем файла в качестве записи журнала. Но это только мое скромное мнение, может быть, есть лучшее решение для этого. У вас есть один? :)

В настоящее время я использую NLog, но я также могу изменить изображение на Serilog, если это невозможно с NLog. Я также хотел бы сказать, что не должно быть другого способа записи сообщения в коде, чем этот:

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

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

    }

Поскольку конфигурация ведения журнала связана с тем, как это записывается в файлы, база данных и так далее c .

Спасибо.

Ответы [ 3 ]

1 голос
/ 11 апреля 2020

Если действительно важно сгенерировать только один 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 для записи в оба файла.

1 голос
/ 11 апреля 2020

Вот возможный подход с использованием Serilog, используя приемники Файл и Карта :

  • Запись регулярных сообщений журнала в файл с именем Application.log ( т. е. все, что не имеет больших данных в сообщении журнала)
  • Запись больших сообщений данных в отдельные файлы с именем Data_{uniqueId}.log
  • Используйте свойство с именем LargeDataId, чтобы сохранить уникальный идентификатор для файл, в котором будут храниться большие данные, а также использовать это свойство, чтобы определить, является ли сообщение обычным сообщением журнала или нет (т. е. если существует свойство 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();
1 голос
/ 11 апреля 2020

Простое решение состоит в том, чтобы просто сделать это (Гарантирует, что вывод 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} гарантирует новый file:

<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

Вы также можете использовать LogEvent-контекст в макетах NLog, а FileTarget Filename - это макет NLog. Таким образом, один и тот же файл-цель может записывать в разные имена файлов на основе LogEvent-context.

...