最近在写一个稍微复杂的 dotnet core web api 程序,里面有个比较耗时的任务,包含很多次循环和 DB 请求,就在想有没有办法优化一下。

想要优化,要先能看“看”到,因为逻辑很复杂,只通过看代码不能完全发现,就想着用 OpenTelemetry 配合 Jaeger 可以比较直观的看到整个调用信息。效果还不错。

"Jaeger UI"

具体的用法还是现查官方文档

大概的步骤如下:

  1. 引用 Nuget 包

    Nuget 包主要分为两类:Instrumentation 和 Exporter,比如下面我用到的

    <PackageReference Include="OpenTelemetry" Version="1.7.0" />
    <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.7.0" />
    <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.7.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.7.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="1.0.0-beta.9" />
    • Instrumentation 用于生成 Tracing 数据:比如我想 Tracing Http 请求和 DB 请求,就加对应的 Instrumentation 就行。

    • Exporter 就是导出器,Tracing 数据输出到哪里去:默认是 Console 可以方便的 Debug;另外一个就是输出到 Jagger 的。

  2. 启用

    因为我只在 LocalHost 做观察,所以多加了 Environment 判断。

    public class Startup
    {
    public Startup(IConfiguration configuration, IWebHostEnvironment env)
    {
    Configuration = configuration;
    Environment = env;
    }

    public IConfiguration Configuration { get; }
    public IWebHostEnvironment Environment { get; }

    public void ConfigureServices(IServiceCollection services)
    {
    // ...
    if (Environment.IsDevelopment())
    {
    services.AddOpenTelemetry()
    .WithTracing(builder =>
    {
    // 设置 tracing tag.service_name
    builder.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(Environment.ApplicationName));

    builder.AddAspNetCoreInstrumentation();
    builder.AddEntityFrameworkCoreInstrumentation();
    builder.AddOtlpExporter(options =>
    {
    options.Endpoint = new Uri(Configuration["OTLP_ENDPOINT_URL"]);
    });
    //builder.AddConsoleExporter();
    });
    }
    }

    // appsettings.Development.json 添加收集器的 endpoint 地址:
    // "OTLP_ENDPOINT_URL": "http://localhost:4317/",
  3. 验证效果

    启动 Jaeger:jaeger-all-in-one.exe --collector.otlp.enabled

    UI:localhost:16686/