NLog - gro1vy/DeliverServiceAPI GitHub Wiki

Для удобства логгирования некоторой информации в процессе работы приложения asp.net в проект был добавлен NLog, благодаря которому происходит запись логгов в БД, где удобно фильтровать нужные логги. Здесь более чем подробно рассматривается, как подключить данный логгер к приложению asp.net и как его конфигурировать.

Что такое Nlog?

NLog (NLog - это аббревиатура от "Nigel's Logger") - это популярная библиотека для логирования событий в приложениях .NET. Он предоставляет мощные и гибкие средства для записи различных событий, таких как отладочные сообщения, ошибки, информационные сообщения и другие, в различные цели, такие как файлы, базы данных, консоль, и другие. NLog предоставляет возможность настраивать и кастомизировать запись логов с помощью XML-конфигурации или кода.

Используя NLog в приложении, мы можем регистрировать типы логгов, приведенные ниже. Числа у каждого типа означаю их уровень, соответственно Trace самый высокий и несет наиболее подробную информацию.

  • Trace - Подробный логг
  • Debug - Информация об отладке
  • Info - Информационное сообщение
  • Warning - Предупреждающие сообщения
  • Error - Сообщения об ошибках
  • Fatal - Серьезные ошибки, на которые нужно обратить внимание

У NLog есть следующие типы цели (Target) записи:

  • Files - Мы можем записывать наши логги в файл.
  • Database - Также может работать с БД, используя NLog.
  • Console - Отображает логга в консольном приложении на C #.
  • Email - Мы можем отправить наш логг по электронной почте.

Как подключить Nlog?

Для начала нужно установить с помощью NuGet необходимые пакеты, представленные на картинке. NLog.Databse нужен для записи логгов в базу данных, поэтому если нужно писать только файл или консоль, этот пакет не нужно устанавливать.

image

Далее нужно настроить конфигурацию NLog. Для этого в корне проекта добавляем Файл веб-конфигурации.

image

И вставить в него следующий код конфига, в котором уже прописано, что логги будет писаться в базу данных и текстовый файл.

<?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"
      autoReload="true"
      internalLogLevel="Info"
      internalLogFile="${basedir}/logs/NLog.log">

  <extensions>
    <add assembly="NLog.Web.AspNetCore" />
  </extensions>
  
  <variable name="logDirectory" value="logs/${shortdate}" />
  
  <targets>
    <!-- Target for writing to a file -->
    <target name="fileTarget" xsi:type="File" fileName="${logDirectory}/app.log" />

    <!-- Target for writing to a database -->
    <target name="databaseTarget" xsi:type="Database"  dbProvider="Npgsql.NpgsqlConnection, Npgsql">
      <connectionString>Server=localhost;Port=5432;Database=LogsDB;User Id=postgres;Password=root</connectionString>
      <commandText>
        INSERT INTO public.logtable (MachineName, LogDate, Level, Message, Logger, Callsite, Exception)
        VALUES (@MachineName, @LogDate, @Level, @Message, @Logger, @Callsite, @Exception)
      </commandText>

      <parameter name="@MachineName" layout="${machinename}" />
      <parameter name="@LogDate" layout="${longdate}" />
      <parameter name="@Level" layout="${level:uppercase=true}" />
      <parameter name="@Message" layout="${message}" />
      <parameter name="@Logger" layout="${logger}" />
      <parameter name="@Callsite" layout="${callsite}" />
      <parameter name="@Exception" layout="${exception:format=Message,StackTrace}" />
    </target>
  </targets>

  <rules>
    <logger name="*" minlevel="Warn" writeTo="databaseTarget" />

    <logger name="*" minlevel="Warn" writeTo="fileTarget" />
  </rules>
</nlog>

Разберем этот конфиг подробнее. В строках internalLogLevel="Info" internalLogFile="${basedir}/logs/NLog.log" указано, куда будут писаться логги самого NLog, и то, что эти логги будут не ниже уровня Info (про уровни было сказано выше).

Далее строка создает переменную в которой храниться какое-то значение, в данном случае это путь к логгам.

В идет перечисление с помощью всех целей, в которые будут писаться логги. В указывается название, которое характеризует эту цель, один из типов, описанных выше, цели записи и в зависимости от типа дополнительный атрибут. Если типом является файл, то в атрибуте указывается путь к нему, если консоль, то - формат данных, а если база данных, то провайдер и строка подключения (в примере она вынесена во внутрь ). Для базы данных также необходимо добавить в команду для вставки данных о логге в таблицу, а также с помощью перечислить переменные, в которые будут записаны необходимые данные и которые будет использованы в команде для вставке данных. Стоит отметить, что перед тем как подключаться к БД и вставлять данные таблиц, нужно соответственно их создать. Для примера выше, команда ниже создает таблицу для логгов.

CREATE TABLE public.logtable (
  ID SERIAL PRIMARY KEY,
  MachineName VARCHAR(50),
  LogDate TEXT,
  Level VARCHAR(10),
  Message TEXT,
  Logger VARCHAR(255),
  Callsite TEXT,
  Exception TEXT
);

И наконец в с помощью происходит настройка того, какие типы логгов попадут в какую цель.

И в конце, чтобы начать писать логги, нужно в том классе, где это будет происходить с помощью Dependency Injection нужно получить ILogger, у которого в '<>' указан класс, получающий его. Ниже представлен пример с использованием логгера в middleware, для глобальной обработки исключений.

public class ExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlingMiddleware> _logger;

    public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, ex.Message);
            throw;
        }
    } 
}
⚠️ **GitHub.com Fallback** ⚠️