JavaRush /Курси /C# SELF /Розподілене трасування та телеметрія

Розподілене трасування та телеметрія

C# SELF
Рівень 64 , Лекція 4
Відкрита

1. Вступ

У сучасному світі сервіс-орієнтованої архітектури (SOA), мікросервісів та хмарних рішень один користувацький запит може «пролетіти» через десятки різних сервісів, перш ніж він поверне результат. Кожен вузол цього «маршруту» веде власні журнали, але як зрозуміти, що помилка або затримка в одному місці справді повʼязана з цим конкретним запитом?

Розподілене трасування — це як система відстеження посилки в логістиці: ви бачите, через які пункти пройшла ваша посилка, де вона затрималася і де стався форс-мажор. У світі програмування — це можливість відстежити «подорож» одного запиту всіма сервісами, зрозуміти, скільки часу він провів на кожному етапі та де виникла помилка чи затримка.

Навіщо потрібне трасування?

  • Локалізація помилок: Якщо щось пішло не так, ви одразу бачите, де саме: у якому сервісі, на якому етапі й навіть який саме метод було викликано.
  • Пошук «вузьких місць»: Трасування покаже, де ваші сервіси уповільнюються і на якому етапі втрачається найбільше часу.
  • Аналітика користувацьких сценаріїв: Можна зрозуміти, як клієнти насправді користуються вашими сервісами, і куди в першу чергу варто вкладатися в оптимізацію.

Як це працює?

Кожен запит отримує унікальний ідентифікатор траси (TraceId), який «подорожує» разом із ним усім стеком сервісів: від фронтенда до бекенда, від API до бази даних і назад. На кожному етапі створюються «спани» (spans), що фіксують час виконання операції й додаткові події. У підсумку ви отримуєте дерево (граф) операцій з їхньою тривалістю та звʼязками між ними.

Ключові сутності та терміни розподіленого трасування

Термін Опис
Траса (Trace) Логічний шлях одного запиту крізь багато сервісів. Унікальна за TraceId.
Спан (Span) Операція або підоперація в межах траси. У кожного спана свій унікальний ідентифікатор.
TraceId Унікальний ідентифікатор всієї траси (усього запиту).
SpanId Унікальний ідентифікатор поточного спана (операції).
Parent SpanId Ідентифікатор батьківського спана (якщо цей спан — частина іншої операції).
Attributes Набір користувацьких метаданих для спана: імʼя методу, параметри, статус тощо.
Events/Logs Важливі події, повʼязані зі спаном (наприклад, помилка, завершення).
Context Propagation Передача інформації про трасу між сервісами та потоками.

2. OpenTelemetry: відкритий стандарт для спостережуваності

Коротко про OpenTelemetry

OpenTelemetry — відкритий стандарт і набір інструментів для збирання телеметрії (трасування, метрики, логи) з різноманітних застосунків. Його підтримує Cloud Native Computing Foundation (CNCF), і він став де-факто стандартом у світі хмарних та розподілених застосунків.

OpenTelemetry (скорочено OTel) вміє:

  • Автоматично збирати й надсилати траси, метрики та логи;
  • Працювати з основними мовами програмування, включно з C#, Java, Python та іншими;
  • Передавати дані до систем спостережуваності — Jaeger, Zipkin, Azure Monitor, Grafana тощо;
  • Розширюватися завдяки плагінам і налаштовуватися під будь-який стек.

Чому саме OpenTelemetry?

  • Незалежність від постачальника: OTel — стандарт, а не продукт конкретної компанії.
  • Сумісність: Підтримує основні формати трасування, легко інтегрується з APM-системами.
  • Автоматизація: Велику частину роботи (наприклад, трасування HTTP-запитів) OTel може виконувати самостійно, з мінімальними налаштуваннями.
  • Масштабованість: OTel добре працює як у невеликих, так і в дуже великих системах.

Архітектура OpenTelemetry: спрощено

Щоб не заплутатися в рівнях, спробуймо візуалізувати типовий потік даних трасування в OTel.

flowchart LR
    subgraph Застосунок
        A[OpenTelemetry SDK]
    end
    A -->|Траси, метрики, логи| B[OpenTelemetry Collector]
    B -->|Експорт до| C[Jaeger/Zipkin/Grafana/Azure/Application Insights та ін.]
  1. OpenTelemetry SDK: Вбудовується безпосередньо у ваш застосунок (наприклад, через NuGet-пакети для .NET).
  2. OTel Collector: Окремий сервіс-концентратор (часто розгортається як Docker-контейнер), який приймає дані трасування від усіх ваших застосунків і експортує їх туди, куди ви вкажете.
  3. Фронтенд спостереження: Система, де ви бачите наочні графіки, дерева, фільтруєте й аналізуєте траси.

3. Швидкий старт із трасуванням у C#/.NET

Додаймо базове розподілене трасування до нашого навчального застосунку. Основні кроки доволі прості.

Ставимо NuGet-пакети

dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Exporter.Console

OpenTelemetry — базова реалізація SDK;
OpenTelemetry.Exporter.Console — експорт трас у консоль (можна замінити на Jaeger, Zipkin тощо).

Мінімальне налаштування трасування

У файлі Program.cs (для консольного застосунку):

using OpenTelemetry;
using OpenTelemetry.Trace;

class Program
{
    static void Main(string[] args)
    {
        // Налаштовуємо трасування
        using var tracerProvider = Sdk.CreateTracerProviderBuilder()
            .AddSource("DemoApp") // Вказуємо імʼя джерела
            .AddConsoleExporter() // Експортуємо траси в консоль
            .Build();

        var source = new System.Diagnostics.ActivitySource("DemoApp");

        // Починаємо нову трасу (кореневий спан)
        using (var activity = source.StartActivity("Головна операція"))
        {
            DoWork();
        }
    }

    static void DoWork()
    {
        // Трохи логіки застосунку...
        System.Threading.Thread.Sleep(300);
    }
}

Що тут відбувається?

  • Створюємо провайдер трасування, реєструємо джерело ("DemoApp") і додаємо консольний експортер AddConsoleExporter().
  • Запускаємо нову «активність» (span) через ActivitySource у корені програми.
  • Всередині виконуємо корисну роботу, яку хочемо відстежити.

Результат:

Activity.Id:          0b69e3e97ca5f14d
Activity.Operation:   Головна операція
Duration: 00:00:00.3001082
...

Автоматичне трасування HTTP та баз даних

OpenTelemetry підтримує інструментування — автоматичне трасування популярних бібліотек. Наприклад, виклики через HttpClient і запити до БД (ADO.NET) можна збирати без додаткового коду.

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
    .AddHttpClientInstrumentation() // HTTP-запити
    .AddSqlClientInstrumentation()  // SQL-запити (якщо використовуєте)
    .AddConsoleExporter()
    .Build();

Тепер усі ваші виклики через HttpClient і робота з SQL автоматично з’являтимуться у трасах.

4. Візуалізація трасування

Виведення у консоль — це лише перший крок. Для справжньої користі краще користуватися фронтендом із візуалізацією.

Jaeger

Jaeger — одна з найпопулярніших open-source систем для візуалізації трасувань.

  1. Розгортаєте Jaeger (наприклад, через Docker).
  2. Замість AddConsoleExporter() використовуєте:
    .AddJaegerExporter(options =>
    {
        options.AgentHost = "localhost";
        options.AgentPort = 6831;
    })
    
  3. Тепер усі траси відображатимуться в Jaeger UI — можна фільтрувати за TraceId, переглядати детальні часові діаграми.

Повна інструкція: OpenTelemetry Jaeger Exporter для .NET

5. Корисні нюанси

Порівняння підходів

Без OTel ви вручну копіюєте TraceId у журналах, сподіваєтеся не забути передати його далі та стикаєтеся зі складнощами під час аналізу інцидентів. З OTel увесь ланцюжок вибудовується автоматично й візуалізується одним кліком.

Підхід Трудовитрати Надійність Масштабованість Сумісність
Ручне журналювання TraceId Високі Низька Потребує постійної підтримки Лише ваші застосунки
OpenTelemetry Мінімальні (після впровадження) Гарантована Широка (будь-яка мова, стек) Сумісний із більшістю APM та систем журналювання

Приклад архітектури

[Веб-клієнт] --> [API-сервіс] --> [Сервіс-авторизації] --> [Сервіс-бази даних]

Коли користувач натискає кнопку, запит проходить через усі ці сервіси. За допомогою OTel ви зможете «протягнути ниточку» (TraceId) через кожен із них, автоматично об’єднуючи події в єдину трасу.

  • У кожному сервісі SDK OTel автоматично розпізнає TraceId з HTTP-заголовків і продовжує ланцюжок.
  • У результаті можна відкрити одну трасу та побачити, де було витрачено мілісекунди, що відбувалося та де сталася помилка.

Застосування в реальних проєктах і на співбесідах

  • Мікросервісні системи та розподілені застосунки (фінтех, маркетплейси, SaaS тощо).
  • DevOps/SRE: швидка локалізація проблем.
  • Покращення SLA і часу відгуку сервісів.
  • Профілювання та оптимізація.
  • На співбесідах — демонстрація зрілої інженерної практики.

6. Типові помилки та особливості реалізації

Забули передати TraceContext. Якщо між сервісами не передається TraceId (наприклад, забули передати потрібні HTTP-заголовки), траси будуть розірвані — виглядатимуть як ізольовані «точки», і вся перевага спостережуваності зникне.

Неінструментований код. Якщо ваша бібліотека або фреймворк не підтримує інструментування, деякі операції випадуть із траси (але завжди можна створити спани вручну через ActivitySource і StartActivity()).

Надлишок даних. Збирати траси для кожного запиту — ресурсомістко, особливо у великому бойовому середовищі. Зазвичай вмикають трасування лише для частини запитів (частота семплювання) або за тригером (помилки, повільні запити).

Продуктивність. Впровадження OTel мінімально впливає на продуктивність за умови асинхронного експорту, проте за дуже великого трафіку стежте за накладними витратами й регулюйте частоту семплювання.

1
Опитування
Логування, рівень 64, лекція 4
Недоступний
Логування
Logging, моніторинг і трасування
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ