Введение в Serilog: что это и зачем нужно
Serilog — это мощная, гибкая и современная библиотека для структурированного логирования в экосистеме .NET (C#, F#, VB.NET). В отличие от классических фреймворков логирования (например, NLog или log4net), которые работают с плоскими текстовыми сообщениями, Serilog изначально спроектирован для работы со структурированными данными.
Зачем нужен Serilog?
- Структурированное логирование: Вы логируете не просто строку, а объекты с именованными свойствами. Это позволяет эффективно фильтровать, искать и анализировать логи в системах вроде Elasticsearch, Seq, Datadog.
- Гибкость (Sinks): Serilog использует концепцию "приемников" (sinks). Вы можете отправлять логи в консоль, файл, базу данных, облачные сервисы (Azure, AWS), Elasticsearch, Telegram, Slack и сотни других мест — просто подключив нужный пакет.
- Производительность: Serilog оптимизирован для высоконагруженных приложений. Он использует отложенное форматирование строк (message templates), чтобы избежать лишних аллокаций памяти, если уровень логирования не активен.
- Простота настройки: Конфигурация через код или JSON-файл. Минимальный код для начала работы — всего пара строк.
- Диагностика: Позволяет легко добавлять контекстную информацию (например, ID пользователя, номер заказа, имя метода) в каждый лог.
Установка Serilog
Serilog распространяется через NuGet — менеджер пакетов для .NET. Установка производится через консоль диспетчера пакетов (Package Manager Console) или .NET CLI.
Установка через .NET CLI (рекомендуется):
dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Settings.Configuration
dotnet add package Serilog.AspNetCore
Установка через Package Manager Console (Visual Studio):
Install-Package Serilog
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File
Install-Package Serilog.Settings.Configuration
Install-Package Serilog.AspNetCore
Пояснение к пакетам:
- Serilog — ядро библиотеки.
- Serilog.Sinks.Console — приемник для вывода в консоль.
- Serilog.Sinks.File — приемник для записи в файлы.
- Serilog.Settings.Configuration — позволяет читать настройки из
appsettings.json. - Serilog.AspNetCore — интеграция с ASP.NET Core (добавляет HTTP-контекст в логи).
Примечание для читателей PythonLib: В Python аналогом установки через pip является pip install serilog (но Serilog — это .NET библиотека, для Python есть свои инструменты, например, structlog).
Быстрый старт: первый лог за 30 секунд
Создайте консольное приложение .NET и добавьте следующий код в Program.cs:
using Serilog;
// 1. Настройка Serilog
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("logs/myapp.log", rollingInterval: RollingInterval.Day)
.CreateLogger();
try
{
Log.Information("Приложение запущено успешно.");
int userId = 42;
string userName = "Alice";
Log.Information("Пользователь {UserId} с именем {UserName} выполнил вход.", userId, userName);
// Пример с ошибкой
try
{
throw new InvalidOperationException("Неверная операция");
}
catch (Exception ex)
{
Log.Error(ex, "Произошла ошибка при выполнении операции для пользователя {UserId}", userId);
}
Log.Warning("Это предупреждение. Уровень: {Level}", "Warning");
}
finally
{
// 2. Важно: закрыть логгер перед выходом из приложения
Log.CloseAndFlush();
}
Что произойдет?
- В консоли вы увидите цветные сообщения с временными метками.
- В папке
logsпоявится файлmyapp20250326.log(дата будет меняться каждый день). - Сообщения будут содержать структурированные данные:
{UserId: 42},{UserName: "Alice"}.
Основные методы и функции Serilog
Ниже приведены ключевые методы Serilog, которые вы будете использовать ежедневно. Все они являются методами статического класса Log или экземпляра ILogger.
1. Log.Information
Что делает: Записывает лог-сообщение с уровнем Information. Используется для логирования нормального хода работы приложения (запуск, завершение, успешные операции).
Параметры:
messageTemplate(string) — шаблон сообщения. Может содержать плейсхолдеры{PropertyName}.propertyValues(params object[]) — значения для плейсхолдеров.
Рабочий пример:
int orderId = 1001;
decimal amount = 250.50m;
Log.Information("Заказ #{OrderId} создан на сумму {Amount:C}.", orderId, amount);
// Вывод: Заказ #1001 создан на сумму 250,50 ₽.
2. Log.Debug
Что делает: Записывает лог с уровнем Debug. Используется для детальной отладочной информации, которая обычно не нужна в production, но полезна при разработке.
Параметры: Аналогичны Information.
Рабочий пример:
var data = new { Id = 5, Name = "Test" };
Log.Debug("Отладка: метод CalculatePrice вызван с данными {@Data}", data);
// {@Data} — сериализует объект как структуру.
3. Log.Warning
Что делает: Записывает лог с уровнем Warning. Используется для нештатных ситуаций, которые не являются ошибками, но требуют внимания (например, превышение лимита, устаревший API).
Параметры: Аналогичны Information.
Рабочий пример:
int attempts = 5;
Log.Warning("Пользователь {UserId} превысил лимит попыток входа. Попыток: {Attempts}", userId, attempts);
4. Log.Error
Что делает: Записывает лог с уровнем Error. Используется для логирования исключений и ошибок, которые нарушают работу приложения.
Параметры:
exception(Exception) — объект исключения (может быть null).messageTemplate(string) — шаблон сообщения.propertyValues(params object[]) — значения для плейсхолдеров.
Рабочий пример:
try
{
// какой-то код
}
catch (SqlException ex)
{
Log.Error(ex, "Ошибка базы данных при обработке заказа {OrderId}", orderId);
}
5. Log.Fatal
Что делает: Записывает лог с уровнем Fatal. Используется для критических ошибок, после которых приложение не может продолжать работу (например, потеря соединения с БД, нехватка памяти).
Параметры: Аналогичны Error.
Рабочий пример:
Log.Fatal("Критическая ошибка: не удалось инициализировать конфигурацию. Приложение будет остановлено.");
6. Log.Verbose
Что делает: Записывает лог с уровнем Verbose. Самый низкий уровень. Используется для очень подробной диагностики, которая обычно отключена в production.
Параметры: Аналогичны Information.
Рабочий пример:
Log.Verbose("Вход в цикл обработки. Текущая итерация: {Iteration}", i);
7. Log.ForContext
Что делает: Создает новый логгер с дополнительным контекстным свойством. Это свойство будет добавлено ко всем последующим сообщениям, записанным через этот логгер. Очень полезно для добавления идентификатора запроса, пользователя или имени класса.
Параметры:
propertyName(string) — имя свойства.value(object) — значение свойства.
Рабочий пример:
var contextLogger = Log.ForContext("RequestId", Guid.NewGuid());
contextLogger.Information("Обработка запроса начата.");
// В логе появится поле RequestId: "..."
8. Log.Logger (свойство)
Что делает: Статическое свойство, которое содержит текущий экземпляр логгера. Позволяет переключать логгер во время выполнения приложения или использовать его для глобального доступа.
Параметры: Нет (свойство).
Рабочий пример:
// Перенастройка логгера во время выполнения
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Warning()
.WriteTo.File("critical.log")
.CreateLogger();
Log.Information("Это сообщение не будет записано (уровень Information ниже Warning).");
Log.Warning("А это сообщение будет записано в critical.log.");
9. Log.CloseAndFlush
Что делает: Закрывает логгер и сбрасывает все буферизированные сообщения. ОБЯЗАТЕЛЬНО вызывать этот метод перед завершением приложения, иначе последние логи могут быть потеряны.
Параметры: Нет.
Рабочий пример:
try
{
// работа приложения
}
finally
{
Log.CloseAndFlush();
}
10. LoggerConfiguration.WriteTo.Console
Что делает: Метод конфигурации, который добавляет приемник (sink) для вывода логов в консоль.
Параметры:
restrictedToMinimumLevel(LogEventLevel, опционально) — минимальный уровень логирования для этого приемника.outputTemplate(string, опционально) — шаблон форматирования вывода.
Рабочий пример:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(
restrictedToMinimumLevel: LogEventLevel.Information,
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
)
.CreateLogger();
11. LoggerConfiguration.WriteTo.File
Что делает: Метод конфигурации, который добавляет приемник для записи логов в файл.
Параметры:
path(string) — путь к файлу.rollingInterval(RollingInterval, опционально) — интервал ротации файлов (Day, Hour, Minute, Infinite).retainedFileCountLimit(int?, опционально) — максимальное количество хранимых файлов.
Также в библиотеке
Кэширование в Kotlin: Redis, Caffeine и другие решения
WebSocket библиотеки Kotlin для создания реального времени в веб-приложениях
Кэширование в C++: Redis, Memcached и встроенные решения
Event Bus и паттерн Observer в Swift: реализация и примеры
Работа с XML в TypeScript: библиотеки, парсинг и создание XML-документов