Логирование: ILogger, уровни, structured logging, Serilog
↑ 3.1 Хост, конфигурация и middleware pipeline · ← Предыдущая · → Следующая
Зачем это на собесе
Логи — основа диагностики в проде. Спрашивают про уровни, structured logging и почему нельзя интерполировать строки.
Объяснение
ILogger<T> — абстракция логирования; провайдеры (Console, Serilog, OpenTelemetry) подключаются отдельно.
| Уровень | Назначение |
|---|---|
| Trace / Debug | детали отладки, выключены в проде |
| Information | значимые события работы |
| Warning | нештатная, но обработанная ситуация |
| Error | ошибка операции |
| Critical | сбой приложения |
// Structured logging: шаблон + параметры, а не интерполяция
logger.LogInformation("Order {OrderId} paid by {UserId} in {ElapsedMs} ms", order.Id, userId, ms);
// Исключение передаём отдельным параметром
logger.LogError(ex, "Failed to process order {OrderId}", order.Id);Шаблон сохраняется как имя события, а параметры становятся полями — в Loki/Elasticsearch можно фильтровать по OrderId.
Source generator
public static partial class Log
{
[LoggerMessage(EventId = 1001, Level = LogLevel.Information, Message = "Order {OrderId} paid")]
public static partial void OrderPaid(this ILogger logger, Guid orderId);
}Нет аллокаций на boxing и парсинг шаблона; удобно для горячих путей.
Serilog
builder.Host.UseSerilog((ctx, lc) => lc
.ReadFrom.Configuration(ctx.Configuration)
.Enrich.FromLogContext()
.WriteTo.Console(new CompactJsonFormatter()));Scopes и LogContext добавляют correlation id и tenant во все записи запроса.
Нюансы и подводные камни
$"..."в сообщении убивает structured logging и создаёт строку даже при выключенном уровне.- Не логируйте пароли, токены, персональные данные и тела запросов целиком.
- Для тяжёлых аргументов проверяйте
logger.IsEnabled(LogLevel.Debug). - Логируйте исключение один раз на границе, а не в каждом слое (иначе дубли).
- Уровни по категориям задаются в
Logging:LogLevel;Microsoft.AspNetCoreобычноWarning.
Практика
- Настройте вывод в JSON и добавьте
CorrelationIdчерез scope. - Перепишите три горячих лога на
LoggerMessage. - Отправьте логи в Seq/Loki и найдите запрос по
OrderId.
Вопросы с ответами
Что такое structured logging?
Логирование с сохранением шаблона и параметров как отдельных полей, что позволяет искать и агрегировать по значениям.
Почему не стоит использовать интерполяцию строк в логах?
Теряется структура, строка формируется всегда и создаёт аллокации; шаблон с параметрами быстрее и удобнее для поиска.
Как связать логи одного запроса?
Correlation/trace id в scope или через
Activity/OpenTelemetry, добавляемый в каждую запись.