Пример. Использование OpenTelemetry с OTLP и автономной Aspire панелью мониторинга

Эта статья является одним из ряда примеров для иллюстрации наблюдаемости .NET с помощью OpenTelemetry.

Помимо стандартной части Aspire, Aspire панель мониторинга доступна как автономный контейнер Docker, который предоставляет конечную точку OTLP, в которую можно отправлять данные телеметрии. Панель мониторинга визуализирует журналы, метрики и трассировки. Использование панели мониторинга таким образом не зависит от Aspire и визуализирует данные телеметрии из любого приложения, отправляющего данные телеметрии для визуализации через OTLP. Он работает одинаково хорошо для приложений, написанных на Java, GoLang или Python, если они могут отправлять данные телеметрии в конечную точку OTLP.

Aspire Использование панели мониторинга требует меньше конфигурации и настройки, чем использование таких решений с открытым кодом, как Prometheus, Grafana и Jaeger. Но в отличие от этих средств Aspire панель мониторинга предназначена как средство визуализации разработчика, а не для производственного мониторинга.

1. Создание проекта

Создайте простой проект веб-API с помощью шаблона ASP.NET Core Empty в Visual Studio или следующей команды .NET CLI:

dotnet new web

2. Добавление метрик и определений действий

Следующий код определяет новую метрику (greetings.count) для количества вызовов API и нового источника действия (Otel.Example).

// Custom metrics for the application
var greeterMeter = new Meter("OTel.Example", "1.0.0");
var countGreetings = greeterMeter.CreateCounter<int>("greetings.count", description: "Counts the number of greetings");

// Custom ActivitySource for the application
var greeterActivitySource = new ActivitySource("OTel.Example");

3. Создание конечной точки API

Вставка следующего кода между builder.Build(); и app.Run()

app.MapGet("/", SendGreeting);

Вставьте следующую функцию в нижней части файла:

async Task<string> SendGreeting(ILogger<Program> logger)
{
    // Create a new Activity scoped to the method
    using var activity = greeterActivitySource.StartActivity("GreeterActivity");

    // Log a message
    logger.LogInformation("Sending greeting");

    // Increment the custom counter
    countGreetings.Add(1);

    // Add a tag to the Activity
    activity?.SetTag("greeting", "Hello World!");

    return "Hello World!";
}

Примечание.

Определение конечной точки не использует ничего конкретного для OpenTelemetry. Он использует API .NET для наблюдения.

4. Ссылка на пакеты OpenTelemetry

Используйте диспетчер пакетов NuGet или командную строку, чтобы добавить следующие пакеты NuGet:

  <ItemGroup>
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.9.0" />
  </ItemGroup>

Примечание.

Используйте последние версии, так как API OTel постоянно развиваются.

5. Настройте OpenTelemetry с помощью правильных поставщиков

Вставьте следующий код перед builder.Build();:

// Setup logging to be exported via OpenTelemetry
builder.Logging.AddOpenTelemetry(logging =>
{
    logging.IncludeFormattedMessage = true;
    logging.IncludeScopes = true;
});

var otel = builder.Services.AddOpenTelemetry();

// Add Metrics for ASP.NET Core and our custom metrics and export via OTLP
otel.WithMetrics(metrics =>
{
    // Metrics provider from OpenTelemetry
    metrics.AddAspNetCoreInstrumentation();
    //Our custom metrics
    metrics.AddMeter(greeterMeter.Name);
    // Metrics provides by ASP.NET Core in .NET 8
    metrics.AddMeter("Microsoft.AspNetCore.Hosting");
    metrics.AddMeter("Microsoft.AspNetCore.Server.Kestrel");
});

// Add Tracing for ASP.NET Core and our custom ActivitySource and export via OTLP
otel.WithTracing(tracing =>
{
    tracing.AddAspNetCoreInstrumentation();
    tracing.AddHttpClientInstrumentation();
    tracing.AddSource(greeterActivitySource.Name);
});

// Export OpenTelemetry data via OTLP, using env vars for the configuration
var OtlpEndpoint = builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"];
if (OtlpEndpoint != null)
{
    otel.UseOtlpExporter();
}

Этот код настраивает OpenTelemetry для различных источников телеметрии.

  • Он добавляет поставщика OTel в ILogger для сбора логов.
  • Он настраивает метрики, регистрируя поставщиков инструментирования и счетчики для ASP.NET и наш пользовательский счетчик.
  • Он настраивает трассировку, регистрируя поставщиков инструментирования и наш пользовательский источник активности (ActivitySource).

Затем он регистрирует экспортер OTLP с помощью env vars для его конфигурации.

6. Настройка переменных среды OTLP

Экспортер OTLP можно настроить с помощью API в коде, но чаще всего его можно настроить с помощью переменных среды. Добавьте следующее в AppSettings.Development.json

"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
"OTEL_SERVICE_NAME": "OTLP-Example"

Можно добавить дополнительные переменные среды для экспортера OTLP .NET или распространенных переменных OTel, например OTEL_RESOURCE_ATTRIBUTES для определения атрибутов ресурсов.

Примечание.

Распространенная ошибка заключается в том, чтобы перепутать AppSettings.json и AppSettings.Development.json. Если он присутствует, он будет использоваться при использовании F5 из Visual Studio, а все параметры в AppSettings.json будут игнорироваться.

7. Запуск Aspire контейнера панели мониторинга

Используется docker для скачивания и запуска контейнера панели мониторинга.

docker run --rm -it `
-p 18888:18888 `
-p 4317:18889 `
--name aspire-dashboard `
mcr.microsoft.com/dotnet/aspire-dashboard:latest

Данные, отображаемые на панели мониторинга, могут быть конфиденциальными. По умолчанию панель мониторинга защищена с помощью аутентификации, требующей для входа токен. Токен отображается в результатах вывода при запуске контейнера.

Aspire Панель управления

Скопируйте отображаемый URL-адрес, замените 0.0.0.0 на localhost, например, http://localhost:18888/login?t=123456780abcdef123456780, и откройте его в браузере. Можно также вставить ключ после /login?t=, когда отображается диалоговое окно входа. Маркер изменяется при каждом запуске контейнера.

8. Запуск проекта

Запустите проект и получите доступ к API с помощью браузера или curl.

curl -k http://localhost:7275

Каждый раз, когда вы запрашиваете страницу, он увеличивает количество приветствий, которые были сделаны.

Выходные данные журнала 8.1

Операторы ведения журнала из кода выводятся с использованием ILogger. По умолчанию поставщик консоли включён, чтобы выходные данные направлялись в консоль.

Существует несколько вариантов выгрузки журналов из .NET:

  • stdout и stderr перенаправляются контейнерными системами, такими как Kubernetes, в файлы журнала.
  • Использование библиотек ведения журнала, которые интегрируются с ILogger. К этим библиотекам относятся Serilog и NLog.
  • Использование поставщиков ведения журналов для OTel, таких как OTLP. Раздел логирования в коде из шага 5 добавляет поставщика OTel.

Журналы отображаются на панели мониторинга как структурированные журналы. Все свойства, заданные в сообщении журнала, извлекаются в виде полей в записи журнала.

Журналы в автономной панели мониторинга

8.2 Просмотр метрик

На Aspire панели мониторинга отображаются метрики для каждого ресурса (ресурс — это термин OTel для обозначения источников телеметрии, таких как процессы). При выборе ресурса панель мониторинга перечисляет каждую метрику, отправленную в конечную точку OTLP ресурсом. Список метрик является динамическим и обновляется по мере получения новых метрик.

Метрики на автономной панели мониторинга

Представление метрик зависит от типа используемой метрики:

  • Счетчики отображаются напрямую.
  • Гистограммы, отслеживающие значение каждого запроса, например интервал времени или байты, отправленные на запрос, собираются в ряд сегментов. Панель мониторинга графирует процентили P50, P90 и P99. Результаты гистограммы могут включать образцы, которые являются отдельными точками данных вместе с trace или spanId для этого запроса. Они отображаются как точки на графе. При выборе одной из трассировок вы перейдёте к соответствующей трассе, чтобы увидеть, что произошло и привело к этому значению. Это полезно для диагностики выбросов.
  • Метрики могут включать измерения, которые являются парами "ключ-значение", связанными с отдельными значениями. Значения агрегируются по измерениям. С помощью выпадающих списков в представлении можно фильтровать результаты, чтобы просматривать определенные измерения, такие как только GET запросы или только запросы для определенного URL-маршрута в ASP.NET.

8.3 Просмотр трассировки

В окне трассировки отображается список следов. Каждая трассировка — это набор действий, которые имеют один и тот же идентификатор трассировки. Работа отслеживается с помощью диапазонов, представляющих единицу работы. Обработка запроса ASP.NET создает диапазон. Выполнение запроса HttpClient — это интервал. Отслеживая родительский диапазон, можно визуализировать иерархию диапазонов. Собирая диапазоны из каждого ресурса (процесса), вы можете отслеживать работу, которая происходит в ряде служб. HTTP-запросы имеют заголовок, который используется для передачи traceId и родительского spanId в следующую службу. Каждый ресурс должен собирать данные телеметрии и отправлять их одному сборщику. Затем он будет агрегировать и представлять иерархию диапазонов.

Трассы на автономной панели мониторинга

На панели мониторинга отображается список трассировок с сводными сведениями. При каждом просмотре диапазона с новым идентификатором traceId они получают строку в таблице. Щелкнув на кнопку "Показать", отображаются все диапазоны в трассировке.

Диапазоны на автономной панели мониторинга

При выборе диапазона отображаются его сведения, включая все свойства диапазона, например greeting тег, заданный на шаге 3.