Мониторинг и логирование C# приложений: от хаоса к порядку

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему ваше C# приложение кричит, а вы не слышите?

Представьте: вы запускаете новую версию микросервиса на C# в полночь. Всё работает идеально... первые 10 минут. А потом — бац! — пользователи жалуются на тормоза, а вы сидите перед лог-файлом размером 2 ГБ и пытаетесь найти иголку в стоге сена. Знакомо? Если нет — вы либо гений, либо никогда не занимались мониторингом по-настоящему.

В этой статье мы разберём, как превратить хаос логов в стройную систему. Вы узнаете, как настроить логирование C#, чтобы не сойти с ума при деплое, и как построить мониторинг приложений, который реально помогает, а не просто рисует красивые графики.

С чего начать: философия правильного логирования

Многие разработчики думают: «Поставлю Console.WriteLine — и норм». Спойлер: нет, не норм. Настоящее логирование в C# — это structured logging (структурированное логирование). Вместо строк вида:

Log.Info("User " + userId + " bought item " + itemId);

Вы пишете:

Log.Information("User {UserId} bought item {ItemId}", userId, itemId);

Разница колоссальная. Во втором случае вы можете фильтровать логи по UserId, строить дашборды и быстро находить проблемы. Это основа диагностики ошибок C# в production.

Выбираем библиотеку: Serilog vs NLog vs log4net

На рынке .NET есть три главных игрока. Давайте сравним их по критериям, важным для реального проекта:

  • Serilog — фаворит современного .NET. Идеален для structured logging, легко настраивается, поддерживает sinks (вывод в файл, базу, Elasticsearch). Рекомендую для новых проектов.
  • NLog — ветеран с гибкой конфигурацией через XML/JSON. Отлично подходит для легаси-систем, где уже используется.
  • log4net — старичок, который лучше не трогать без крайней нужды. Поддержка хромает, structured logging — через костыли.

Для трассировки .NET в современных приложениях Serilog — выбор №1. Давайте настроим его за 5 минут.

Настройка Serilog в C#: пошаговый гайд

Установите пакеты через NuGet:

dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
dotnet add package Serilog.Sinks.Seq

Теперь — минимальная конфигурация в Program.cs для ASP.NET Core:

using Serilog;

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.Console()
    .WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day)
    .WriteTo.Seq("http://localhost:5341") // для продвинутого мониторинга
    .CreateLogger();

try
{
    Log.Information("Starting web application");
    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseSerilog(); // интеграция с хостом
    // ... остальная настройка
    var app = builder.Build();
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}

Обратите внимание на rollingInterval — логи будут ротироваться каждый день, а не расти до бесконечности. Это основа асинхронного логирования в production.

Структурированные логи: как извлекать максимум пользы

Допустим, у нас есть метод обработки заказа. Без структурирования вы бы написали:

logger.LogInformation("Processing order {OrderId} for user {UserId}", order.Id, user.Id);

С Serilog это превращается в JSON-объект, который можно парсить. А если добавить контекст через ILogger<T>:

public class OrderService
{
    private readonly ILogger<OrderService> _logger;

    public OrderService(ILogger<OrderService> logger)
    {
        _logger = logger;
    }

    public async Task ProcessOrder(Order order)
    {
        using (_logger.BeginScope(new Dictionary<string, object>
        {
            ["OrderId"] = order.Id,
            ["UserId"] = order.UserId
        }))
        {
            _logger.LogInformation("Processing order");
            // бизнес-логика
            _logger.LogInformation("Order processed successfully");
        }
    }
}

Теперь все логи внутри scope автоматически содержат OrderId и UserId. Это невероятно упрощает мониторинг приложений при поиске конкретной транзакции.

Мониторинг в реальном времени: Application Insights и Grafana

Логи — это хорошо, но видеть их в реальном времени — ещё лучше. Для C# приложений есть два популярных пути:

  • Azure Application Insights — облачное решение от Microsoft. Встраивается за 2 минуты, показывает метрики, трейсы, исключения. Идеально для Azure-проектов.
  • Seq + Grafana — self-hosted вариант. Seq принимает structured logs, Grafana рисует дашборды. Подходит для on-premise.

Подключим Application Insights к ASP.NET Core:

dotnet add package Microsoft.ApplicationInsights.AspNetCore

В Program.cs:

builder.Services.AddApplicationInsightsTelemetry();

И добавьте строку подключения в appsettings.json:

{
  "ApplicationInsights": {
    "ConnectionString": "InstrumentationKey=ваш-ключ"
  }
}

Готово! Теперь каждое исключение, каждый медленный запрос автоматически отправляются в портал Azure. Вы можете настроить алерты на падение производительности — это спасёт вас ночью.

Health Checks: чтобы мониторинг был полезным

Просто логировать мало — нужно проверять, что сервис жив. Добавьте Health Checks в ASP.NET Core:

builder.Services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>()
    .AddUrlGroup(new Uri("https://external-api.com"), "External API");

app.MapHealthChecks("/health");

Теперь ваш эндпоинт /health возвращает статус 200, если всё ОК, и 503, если проблемы. Подключите к этому Uptime Kuma или аналоги — и вы узнаете о падении раньше пользователей.

Лучшие практики: как не утонуть в логах

Опытные разработчики C# знают: количество логов — не равно качеству. Вот 5 правил, которые превратят ваш мониторинг C# приложений в искусство:

  • Не логируйте в цикле. Если у вас 10 000 итераций — не пишите лог на каждую. Используйте счётчики или пишите summary после цикла.
  • Используйте уровни логирования. Verbose — для отладки, Information — для биз

Блоги

Рекомендаций по книгам