Подвійний експорт метрик .NET через OTLP та Prometheus

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

З огляду на те, що OpenTelemetry став дипломованим проєктом CNCF, багато компаній все частіше прагнуть перейти на OpenTelemetry, щоб додати до своєї архітектури спостереження більше сигналів окрім метрик. Логи та трасування є популярними доповненнями для отримання глибшого розуміння поведінки застосунків. Профілювання також починає ставати популярним четвертим сигналом телеметрії для ще глибшого аналізу.

Це може створити перешкоду для міграції — як ми можемо перенести наші застосунки з однієї системи в іншу для обробки метрик, не проводячи одноразового переходу? Щоб зменшити ризики будь-якої міграції, краще застосовувати інкрементний підхід, за якого метрики експортуються в обидві системи протягом певного періоду, щоб можна було порівняти та перевірити стани «до» та «після» і переконатися, що в жодній із систем не відбувається втрати видимості виробничих процесів для спостереження за метриками або управління сповіщеннями.

Використання експортера OpenTelemetry Prometheus для .NET

Останній реліз експортера OpenTelemetry Prometheus для .NET дозволяє застосувати саме такий підхід до ваших виробничих метрик. Ви можете використовувати клас .NET Meter у коді вашого застосунку та фреймворку, щоб збирати метрики й експортувати їх як у Prometheus, так і через інший експортер, наприклад експортер OTLP, який надає NuGet-пакунок OpenTelemetry.Exporter.OpenTelemetryProtocol.

Експортер Prometheus — це фактично клієнтська бібліотека Prometheus, написана поверх OpenTelemetry SDK, яка надає HTTP-точку доступу для збору метрик (scrape) у вашому застосунку, щоб сервер Prometheus міг регулярно збирати метрики з вашого застосунку. Експортер реалізує специфікацію Prometheus OpenTelemetry (матрицю) та всі документовані текстові формати представлення (окрім OpenMetrics 2.0, який усе ще експериментальний), щоб забезпечити сумісність з OpenMetrics.

flowchart LR
    subgraph APP["Застосунок"]
        AC["Код застосунку"]
        SDK["OpenTelemetry SDK"]
        PE["Експортер Prometheus"]
        OE["Експортер OTLP (Клієнт)"]
        EP["GET /metrics HTTP-точка доступу (Сервер)"]

        AC -->|"Генерує метрики"| SDK
        SDK -->|"Надає метрики"| PE
        PE -->|"Надає метрики у форматі text/plain"| EP
        SDK -->|"Надає метрики"| OE
    end

    P["Prometheus (Клієнт)"]
    OTB["OpenTelemetry Backend (Сервер)"]

    P -->|"HTTP GET /metrics (запитscrape)"| EP
    EP -->|"Відповідь з метриками (текстовий формат)"| P

    OE -->|"Запит експорту OTLP"| OTB
    OTB -->|"Відповідь/підтвердження OTLP"| OE

Використовуючи лише клас Meter разом з інструментами Counter<T>, Gauge<T> та Histogram<T> у коді вашого .NET-застосунку, метрики можна збирати без потреби використовувати одночасно .NET OpenTelemetry SDK та окремий клієнт Prometheus.

public class BlogPostComments
{
    private readonly Meter _meter;
    private readonly Counter<long> _likes;

    public BlogPostComments(IMeterFactory meterFactory)
    {
        _meter = meterFactory.Create("OpenTelemetry.Blog");
        _likes = _meter.CreateCounter<long>("blog_post_likes");
    }

    public void BlogPostLiked(long id) =>
        _likes.Add(1, new KeyValuePair<string, object?>("post_id", id));
}

Далі потрібно зовсім небагато коду, щоб налаштувати OpenTelemetry SDK на експорт ваших метрик як у Prometheus, так і через OTLP до бекенду, що підтримує OpenTelemetry, додавши до проєкту NuGet-пакунок OpenTelemetry.Exporter.Prometheus.AspNetCore.

using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;

using var meterProvider = Sdk.CreateMeterProviderBuilder()
    .SetResourceBuilder(CreateResourceBuilder())
    .AddMeter("OpenTelemetry.Blog")
    .AddOtlpExporter()
    .AddPrometheusExporter()
    .Build();

Ваш застосунок також має надавати HTTP-точки доступу для збору метрик, які Prometheus використовуватиме для збору метрик з вашого застосунку. Це можна зробити, додавши метод розширення UseOpenTelemetryPrometheusScrapingEndpoint до вашого IApplicationBuilder у методі Configure вашого класу Startup.

Наприклад:

var builder = WebApplication.CreateBuilder(args);

// Налаштуйте сервіси тут

var app = builder.Build();

// Налаштуйте інший проміжне програмне забезпечення тут

app.MapPrometheusScrapingEndpoint();

app.Run();

Використання API Meter для експорту метрик робить код вашого застосунку більш переносним і незалежним від специфічних для Prometheus API. Це дозволяє прибрати залежності від клієнтських бібліотек Prometheus з коду вашого застосунку. Окрім того, що ваш код готовий до використання в екосистемі OpenTelemetry, це також відкриває можливість використовувати інші інструменти екосистеми .NET, як-от dotnet-counters, для перегляду метрик.

Якщо ваш застосунок наразі використовує лише нативний клієнт Prometheus, наприклад prometheus-net, вам спершу доведеться поступово мігрувати на використання API Meter. Скільки часу займе ця міграція, залежить від складності вашої наявної інструментації Prometheus та ресурсів, доступних вам для внесення відповідних змін.

Деякі труднощі, з якими ви можете зіткнутися під час цієї міграції, можуть включати такі функції Prometheus, які не мають прямих аналогів в API Meter і тому не підтримуються:

  • тип даних summary у Prometheus;
  • нативні гістограми.

Надсилання метрик до Prometheus через OTLP

Альтернативно, якщо у вас є лише сервер Prometheus і немає бекенду, сумісного з OTLP, і ви хочете лише експортувати метрики, сам Prometheus має опційну підтримку приймання метрик, надісланих до нього через OTLP.

Спершу переконайтеся, що ви запускаєте Prometheus із прапорцем командного рядка --web.enable-otlp-receiver.

Потім налаштуйте експортер OTLP так само, як у фрагменті коду вище, але в цьому випадку вам не потрібно буде також використовувати експортер Prometheus. Зверніть також увагу, що експортер OTLP вказує базовий шлях для OTLP-точки доступу метрик і використовує HTTP/protobuf як протокол для експортера OTLP.

using OpenTelemetry;
using OpenTelemetry.Exporter;
using OpenTelemetry.Metrics;

using var meterProvider = Sdk.CreateMeterProviderBuilder()
    .SetResourceBuilder(CreateResourceBuilder())
    .AddMeter("OpenTelemetry.Blog")
    .AddOtlpExporter((options, _) =>
    {
        options.Endpoint = new Uri("http://prometheus:9090/api/v1/otlp/v1/metrics");
        options.Protocol = OtlpExportProtocol.HttpProtobuf;
    })
    .Build();

Цей підхід дозволяє надсилати метрики до Prometheus за допомогою OpenTelemetry .NET SDK через OTLP, не покладаючись на клієнтську бібліотеку Prometheus у коді вашого застосунку.

Повний приклад цього підходу ви можете знайти у зразку Getting Started with Prometheus and Grafana у репозиторії OpenTelemetry .NET.

Підсумок

З мінімальними накладними витратами під час виконання застосунок може як надсилати метрики через OTLP, так і дозволяти збирати метрики Prometheus, що дає змогу використовувати обидві системи паралельно, доки ви не вирішите повністю перейти на бекенд, сумісний з OpenTelemetry, для ваших метрик.

Востаннє змінено September 23, 2026: [uk] Blog Dual dotNet metrics export (725e43a3)