JavaRush /Курсы /C# SELF /Структурированное логирование и

Структурированное логирование и Serilog

C# SELF
64 уровень , 1 лекция
Открыта

1. Введение

Если обычное текстовое логирование — это ваш дневник с заметками "Я сегодня поел", то структурированное логирование превращает каждую запись в карточку с полями: {Дата: ..., Событие: "Поел", Калории: 500, Блюдо: "Жареное мясо"}. Это значит, что вы можете потом не только почитать дневник, но и построить график по калориям за месяц, отфильтровать события по блюду и узнать, когда вы ели слишком поздно.

Почему простого текста мало?

С простым текстом всё просто... до поры до времени. Попробуйте собрать статистику по ошибкам в логах, объёмам продаж в интернет-магазине, цепочку действий одного пользователя по его ID (например, 42), если все данные — это простыни текста. Структурированное логирование позволяет прикрутить анализ и даже ИИ к логам. С ним можно искать аномалии, строить дашборды и реагировать на проблемы автоматически.

Преимущества

  • Позволяет логировать не только сообщения, но и связанные с ними данные (поля/свойства).
  • Логи можно анализировать автоматически: считать, фильтровать, строить отчёты.
  • Используются стандартизированные форматы, такие как JSON, которые легко парсить машинами.

Serilog: что это и почему он?

Serilog (официальный сайт: serilog.net, документация: github.com/serilog/serilog/wiki) — популярная библиотека для структурированного логирования в .NET. Она прекрасно интегрируется с Microsoft.Extensions.Logging, поддерживает вывод в десятки разных систем (файл, консоль, Seq, ElasticSearch, Grafana, Azure и т.д.), минимально влияет на производительность и проста в настройке.

Чем Serilog отличается от «просто логирования»?

  • Структура: логи — это объекты с полями, по которым можно фильтровать (например, все ошибки пользователя с ID 42).
  • Форматы: умеет писать не только текст, но и JSON, XML, что удобно для дальнейшей обработки.
  • Гибкость: множество готовых пакетов‑синков для отправки логов куда угодно.

Структура записи лога с Serilog

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

{
  "Timestamp": "2024-06-22T10:23:45.123Z",
  "Level": "Information",
  "MessageTemplate": "Пользователь {UserId} вошёл в систему",
  "Properties": {
    "UserId": 42,
    "IpAddress": "127.0.0.1"
  }
}

Здесь даже не самый продвинутый анализ поймёт: речь про пользователя №42 и его IP-адрес.

2. Установка и базовая настройка Serilog в C# проекте

Шаг 1. Установка NuGet‑пакетов

В Rider/Visual Studio через NuGet Package Manager установите:

  • Serilog
  • Serilog.Sinks.Console (вывод в консоль)
  • Serilog.Extensions.Logging (для интеграции с Microsoft.Extensions.Logging)

Через командную строку:

dotnet add package Serilog
dotnet add package Serilog.Sinks.Console

Шаг 2. Минимальная настройка

Добавим конфигурацию в Program.cs и запишем первый лог.

using System;
using Serilog;

namespace MySuperApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1. Базовая настройка Serilog: вывод в консоль
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.Console()
                .CreateLogger();

            // 2. Пример структурированного логирования
            int userId = 42;
            string ip = "127.0.0.1";
            Log.Information("Пользователь {UserId} вошёл в систему с IP {IpAddress}", userId, ip);

            Log.CloseAndFlush();
        }
    }
}

В консоли увидим примерно такое:

[10:30:16 INF] Пользователь 42 вошёл в систему с IP 127.0.0.1

Далее легко направить вывод в JSON-файл, Seq или другую систему.

3. Форматирование логов: Message Template

В Serilog вместо конкатенации строк используется синтаксис шаблонов:

Log.Information("Операция {Operation} над файлом {FileName}", "удаление", "test.txt");

Это не просто красивая запись — это структурированное логирование: в запись попадут поля Operation и FileName, доступные для фильтрации и агрегации.

Чем отличается от string.Format?

string.Format("Операция {0} над файлом {1}", operation, fileName) просто склеивает строку с плейсхолдерами {0}, {1}. Serilog же делает отдельные поля, с которыми потом можно работать аналитически.

Гибкая настройка: уровни, фильтры, разные «синки»

Serilog может писать логи одновременно в несколько мест.

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Console()
    .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

Теперь логи пишутся и в консоль, и в файл с ежедневной ротацией.

4. Пример

Допустим, мы делаем консольное приложение‑«блокнот», позволяющее создавать записи пользователя. Добавим структурированное логирование действий.

using System;
using Serilog;

namespace NotesApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Information()
                .WriteTo.Console()
                .WriteTo.File("notes-log.json", rollingInterval: RollingInterval.Day, 
                              formatter: new Serilog.Formatting.Json.JsonFormatter())
                .CreateLogger();

            Console.WriteLine("Введите имя пользователя:");
            string userName = Console.ReadLine();

            Log.Information("Пользователь {UserName} запустил приложение NotesApp", userName);

            while (true)
            {
                Console.WriteLine("Введите текст записи (или напишите 'выход'):");
                string note = Console.ReadLine();

                if (note == "выход")
                {
                    Log.Information("Пользователь {UserName} завершил работу", userName);
                    break;
                }

                Log.Information("Пользователь {UserName} создал заметку: {NoteText}", userName, note);
            }

            Log.CloseAndFlush();
        }
    }
}

Комментарий:
Лог фиксирует, кто запускает программу, что вводит и когда завершает работу. В файле notes-log.json каждая запись — это JSON-объект, который легко анализировать.

5. Полезные нюансы

Лучшие практики структурированного логирования

  • Не злоупотребляйте уровнями Debug/Trace в продакшне — используйте Information и Warning разумно.
  • Используйте именованные параметры в шаблонах вместо конкатенации строк.
  • Никогда не логируйте чувствительные данные (пароли, токены, ключи).
  • Логируйте важные бизнес‑события, а не только ошибки и исключения.
  • Настройте ротацию и очистку логов, чтобы не закончалось место на диске.

Визуализация и анализ: Seq, Kibana, Application Insights

Serilog поддерживает множество синков — конечных точек, куда отправляются логи.

Sink Краткое описание Где используется
Console Прямо в консоль Разработка, тесты
File В локальный или сетевой файл Маленькие проекты, dev
Seq Веб‑интерфейс с фильтрацией и дашбордами Enterprise, аналитика
ElasticSearch Мощная система хранения и анализа Большие компании
Azure Application Insights Облачный мониторинг и телеметрия Azure‑нагруженные сервисы

Seq (datalust.co/seq) — очень популярное решение для разработки и внутреннего использования: удобная фильтрация, поиск по полям и быстрое развёртывание.

Таблички и визуализация

Ниже — краткая таблица того, что можно логировать структурированно:

Что логируем Как выглядит в Serilog Пример значения
ID пользователя
{UserId}
123
Действие
{Action}
"Удаление"
Ошибка
Log.Error(ex, "Ошибка в {Module}")
"Модуль регистрации"
Время операции {Elapsed:0.000} сек 1.234
Имя файла
{FileName}
"report.pdf"

Интересные фишки и дополнительные возможности Serilog

  • Enrichers: добавляют к каждому логу свойства (например, .Enrich.WithMachineName()).
  • Связанные логи: добавляйте RequestId для корреляции цепочки событий.
  • Конфигурация через appsettings.json: удобно для продакшна.
{
  "Serilog": {
    "MinimumLevel": "Debug",
    "WriteTo": [
      { "Name": "Console" },
      { "Name": "File", "Args": { "path": "log.txt" } }
    ]
  }
}

Advanced sinks: можно отправлять логи в Slack, Telegram, по почте (но осторожно, чтобы не получить тысячу писем на каждую ошибку).

6. Практическая часть: интеграция с Microsoft.Extensions.Logging

В .NET часто используют стандартный интерфейс ILogger, чтобы не привязываться к конкретной библиотеке. Serilog можно подключить как провайдер.

Шаг 1. Установка пакета

dotnet add package Serilog.Extensions.Logging

Шаг 2. Конфигурирование

using Microsoft.Extensions.Logging;
using Serilog;

// ...

// Конфигурировать Serilog, как обычно:
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateLogger();

// Теперь используем Microsoft.Extensions.Logging
var loggerFactory = LoggerFactory.Create(builder =>
{
    builder.AddSerilog();
});

ILogger<Program> logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Тестовое сообщение: {TestValue}", 123);

// Не забываем закрыть:
Log.CloseAndFlush();

Комментарий:
Теперь весь ваш код на ILogger<T> независим от провайдера — при желании можно перейти на NLog или Log4Net.

7. Типичные ошибки при работе с Serilog

Перегрузка логов: если писать всё подряд, полезную информацию будет сложно найти.

Логирование исключений как текста: используйте перегрузку с исключением — так в лог попадёт структура ошибки.

try
{
    // some code
}
catch (Exception ex)
{
    Log.Error(ex, "Произошла ошибка при выполнении запроса");
}

Злоупотребление конфигом: не превращайте конфигурацию в свалку — добавляйте только нужные синки и уровни.

2
Задача
C# SELF, 64 уровень, 1 лекция
Недоступна
Базовое структурированное логирование с Serilog
Базовое структурированное логирование с Serilog
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ