.NET CORE 接入 OpenTelemetry 收集指标、链路跟踪数据

376

1. OpenTelemetry简介

OpenTelemetry(简称 OTel)是一个开源的云原生观测框架,由 Cloud Native Computing Foundation(CNCF)维护。它的目标是提供一套标准化的工具、API 和 SDK,帮助开发者收集、生成和管理应用程序的遥测数据(如指标、日志、分布式追踪等),从而实现对系统运行状态的全面观测。

2. OpenTelemetry 能做什么?

统一观测数据标准:

标准化了指标(Metrics)、日志(Logs)和分布式追踪(Traces)的格式(如 OTLP 协议),解决多工具数据格式不兼容的问题。

分布式追踪(Distributed Tracing):

跟踪请求在微服务架构中的完整流转路径,记录每个服务的耗时、状态和依赖关系。

帮助定位性能瓶颈(例如:哪个服务导致请求延迟?)。

指标(Metrics)收集:

自动采集系统性能指标(如 CPU 使用率、请求吞吐量、错误率等),也支持自定义业务指标。

与 Prometheus、Grafana 等监控工具无缝集成。

日志(Logs)集成:

将日志与追踪和指标关联,提供更完整的上下文(例如:某条错误日志对应的请求链路)。

灵活的导出与集成:

支持将数据导出到多种后端系统(如 Jaeger、Zipkin、Prometheus、Elasticsearch、Datadog 等),无需修改代码即可切换观测平台。

自动代码插桩(Auto-Instrumentation):

对常见框架(如 HTTP 服务、数据库驱动)自动注入观测代码,减少手动插桩的工作量。

3. OpenTelemetry Clinet 接入

创建项目并引用相关OpenTelemetry包,使用正确的提供程序配置 OpenTelemetry

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.11.2" />
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.2" />
    <PackageReference Include="OpenTelemetry.Exporter.Prometheus.AspNetCore" Version="1.11.2-beta.1" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.1" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.1" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.11.1" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1" />
  </ItemGroup>
  
</Project>

配置 OpenTelemetry 用于向 OpenTelemetry 服务端发送Tracing、Metrics、Logging 数据

using OpenTelemetry.Instrumentation.AspNetCore;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Otlp.AspNetCore;

var appBuilder = WebApplication.CreateBuilder(args);

// 创建一个服务来公开ActivitySource,并创建用于手动检测的Metric Instruments
appBuilder.Services.AddSingleton<Instrumentation>();

// 清除WebApplication主机使用的默认日志记录提供程序
appBuilder.Logging.ClearProviders();

// 使用自动启动配置OpenTetry日志记录、指标和跟踪
// 从OpenTetry添加OpenTetry扩展。扩展。群众或部队的集合
appBuilder.Services.AddOpenTelemetry()
    .ConfigureResource(r => r
        .AddService(
            serviceName: appBuilder.Configuration.GetValue("ServiceName", defaultValue: "otel-test")!,
            serviceVersion: typeof(Program).Assembly.GetName().Version?.ToString() ?? "unknown",
            serviceInstanceId: Environment.MachineName))
    .WithTracing(builder =>
    {
        // Tracing

        // 确保TracerProvider订阅了任何自定义ActivitySource。
        builder
            .AddSource(Instrumentation.ActivitySourceName)
            .SetSampler(new AlwaysOnSampler())
            .AddHttpClientInstrumentation()
            .AddAspNetCoreInstrumentation();

        // 对AspNetCore检测选项使用IConfiguration绑定。
        appBuilder.Services.Configure<AspNetCoreTraceInstrumentationOptions>(appBuilder.Configuration.GetSection("AspNetCoreInstrumentation"));
        builder.AddOtlpExporter(otlpOptions =>
        {
            // 直接将IConfiguration用于Otlp导出器端点选项
            otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint", defaultValue: "http://localhost:4317"));
        });
    })
    .WithMetrics(builder =>
    {
        // Metrics

        // 确保MeterProvider订阅任何自定义指标。
        builder
            .AddMeter(Instrumentation.MeterName)
            .SetExemplarFilter(ExemplarFilterType.TraceBased)
            .AddRuntimeInstrumentation()
            .AddHttpClientInstrumentation()
            .AddAspNetCoreInstrumentation();

        builder.AddOtlpExporter(otlpOptions =>
        {
            // 直接将IConfiguration用于Otlp导出器端点选项。
            otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint", defaultValue: "http://localhost:4317")!);
        });
    })
    .WithLogging(builder =>
    {
        // Logging

        builder.AddConsoleExporter();
        builder.AddOtlpExporter(otlpOptions =>
        {
            // 直接将IConfiguration用于Otlp导出器端点选项。
            otlpOptions.Endpoint = new Uri(appBuilder.Configuration.GetValue("Otlp:Endpoint", defaultValue: "http://localhost:4317"));
        });
    });

appBuilder.Services.AddControllers();

appBuilder.Services.AddEndpointsApiExplorer();

appBuilder.Services.AddSwaggerGen();

var app = appBuilder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

OpenTelemetry .NET Client , 详细介绍如何接入并举例进行参考

https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/examples

4. 官方资料

https://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/observability-prgrja-examplehttps://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/metricshttps://learn.microsoft.com/zh-cn/aspnet/core/grpc/diagnostics?view=aspnetcore-9.0

5. OpenTelemetry Collector 使用和安装

OpenTelemetry Collector 接收跟踪、指标和日志,处理遥测数据,并将其导出到使用其组件的各种可观察性后端,如:Jaeger

https://opentelemetry.io/zh/docs/collector/installation/https://opentelemetry.io/zh/docs/collector/configuration/

OpenTelemetry Collector 配置问卷参考:

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318
processors:
  batch:

exporters:
  otlp/jaeger:
    endpoint: 10.0.12.10:4317
    tls:
      insecure: true
  prometheus:
    endpoint: 0.0.0.0:8889

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: []
      exporters: [otlp/jaeger]
    metrics:
      receivers: [otlp]
      processors: []
      exporters: [prometheus]

exporters.prometheus.endpoint=0.0.0.0:8889,对应prometheus采集地址=http://服务器节点:8889/metare;

exporters.otlp/jaeger.endpoint=10.0.12.10:4317,对映Jaeger 链路数据采集器地址

6. prometheus安装和使用

https://prometheus.io/docs/prometheus/latest/installation/

配置文件参考

global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"

scrape_configs:
  # prometheus
  - job_name: prometheus
    static_configs:
      - targets: ['10.0.12.10:9090']
  # prometheus-mysqld-exporter
  - job_name: mysql
    metrics_path: /probe
    params:
      auth_module: [client]
    static_configs:
      - targets:
        # All mysql hostnames or unix sockets to monitor.
        - 10.0.12.10:3306
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        # The mysqld_exporter host:port
        replacement: 10.0.12.10:9104
  # opentelemetry-metrics
  - job_name: opentelemetry
    metrics_path: /metrics
    static_configs:
      - targets: 
        - 10.0.12.10:8889

2025-03-17-ottujjth.png

7. Jaeger安装和使用

OpenTelemetry Collector 接收跟踪的数据会被 OpenTelemetry Collector 发送至 jaeger ,用于在jaeger 展示链路数据

https://www.jaegertracing.io/docs/2.4/getting-started/

2025-03-17-vmlwjtjj.png

8. Grafana安装和使用

运行 Grafana Docker 镜像

https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/

2025-03-17-poycifmm.png