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, що зручно для подальшої обробки.
  • Гнучкість: чимало готових sinkʼів для надсилання логів куди завгодно.

Структура запису лога з 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 же створює окремі поля, з якими потім можна працювати аналітично.

Гнучке налаштування: рівні, фільтри, різні «sinkʼи»

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ʼів — кінцевих точок, куди надсилаються логи.

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
{
    // якийсь код
}
catch (Exception ex)
{
    Log.Error(ex, "Сталася помилка під час виконання запиту");
}

Зловживання конфігурацією: не перетворюйте конфігурацію на звалище — додавайте лише потрібні sinkʼи та рівні.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ