冠军

导航

OpenTelemetry.NET API

OpenTelemetry.NET API

Status and Releases

Tracing Metrics Logging
1.0 Alpha Beta

安装

dotnet add package OpenTelemetry.Api

说明

应用程序的开发者和库的作者使用 OpenTelemetry API 来测量其应用程序。API 仅仅关注对于测量应用程序/库的必须的抽象。对于特殊的要求,例如 telemetry 如何导出到特定的 telemetry 后端,如何采样 telemetry 等等。API 由 Tracing API、Logging API、Metric API、Context 和 Propagation API ,以及一套语义约定所组成。

Tracing API

Tracing API 允许你生成 Span,它表示 Trace 的单个操作。Span 可以嵌套成为 Span 树。每个 Trace 包含一个根 Span,它专门描述整个的操作,一个或者多个的子 Span 对应子操作。

Logging API

OpenTelemetry.NET 并没有对日志引入自己的 API。相反,它提供了对众所周知的 Microsoft.Extensions.Logging API 的集成。

Metrics API

Metrics API 允许用户捕获计算机程序在运行时的测量。Metrics API 被设计为处理原始的测量,通常是这些测量的持续统计。

Baggage API

Baggage API 允许用户添加上下文信息到 metric、trace 以及 log 中。Baggage 可以使用 Propagator 来从进程暴露。OpenTelemetry SDK 提供了 BaggageProgagator ,并默认启用。

// Use GetBaggage to get all the key/value pairs present in Baggage
foreach (var item in Baggage.GetBaggage())
{
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}

// Use SetBaggage method to add a key/value pair in Baggage
Baggage.SetBaggage("AppName", "MyApp");
Baggage.SetBaggage("Region", "West US");

// Use RemoveBaggage method to remove a key/value pair in Baggage
Baggage.RemoveBaggage("AppName");

// Use ClearBaggage method to remove all the key/value pairs in Baggage
Baggage.ClearBaggage();

建议的添加 Baggate 方式是使用 Baggate.SetBaggate() API。OpenTelemetry 用户不应该使用 Activity.AddBaggate() 方法

OpenTelemetry.NET Tracing API 入门

很久以来,.NET 运行时提供了 Activity 类,它的用意是跟踪和表示与 OpenTelemetry Span 等价的意图。OpenTelemetry.NET 重用已有的 Activity 并用于表示 Telemetry 中的 Span。这意味着,用户可以仅仅使用 .NET 运行时,就可以测量其应用程序,并记录 OpenTelemetry 兼容的 Trace。

Activity 和相关类来自 System.Diagnostics.DiagnosticSource NuGet 包。该包的 5.0.0 版本包含了改进的 Activity 类,使得它更加接近 OpenTelemetry API 规范。

即使 Activity 使能了 OpenTelemetry 支持的所有场景,已经熟悉 OpenTelemetry 术语的用户可能发现它很容易使用该术语操作。例如,StartSpan 可能就是 StartActivity。为了帮助这种转换,OpenTelemetry.API 包提供了垫片类来封装 .NET 的 Activity 类。

垫片类仅仅存在于 API 中。.NET 的 OpenTelemetry SDK 将仅仅使用 Activity 。而不管在测量中使用的是垫片类,还是 Activity 类。最终的结果将是相同的。在 Processor 和 Exporter 中得到相同的数据。

建议的测量方式是使用 .NET Activity API。用户仅仅要求依赖于 DiagnosticSource。添加对于 OpenTelemetry.APi 仅仅对于如下场景是必须的:

  1. 你希望使用匹配 OpenTelemetry 规范的术语。垫片对于此类用户是有帮助的。如果你想比较其差异,请参考
  2. 你的库与其它库或者组件进行通讯,并期望访问 Propagator,以注入并抽取上下文数据。有些最通用的库要求这样,例如 HttpClient、ASP.NET、ASP.NET Core。该仓储已经提供了对于这些常用库的指导。如果你的库不是基于这些库构建,并期望借助于 propagator,请参考 Context propagation 一节。
  3. 你希望借助于 Baggage API

使用 .NET Activity API 测量库/应用程序

基本使用

如在入门部分所述,在 OpenTelemetry.NET 中的测量 API 使用 .NET 中的 Activity API。

  1. 为你的应用程序安装 System.Diagnostics.DiagnosticSouce 5.0.1 及以上 Package

    <ItemGroup>
      <PackageReference
        Include="System.Diagnostics.DiagnosticSource"
        Version="5.0.1"
      />
    </ItemGroup>
    
  2. 创建一个 ``ActivitySource。提供处理测量相关的名称和版本。ActivitySource` 实例通常仅仅创建一个,并在整个应用程序/库中重用。

    static ActivitySource activitySource = new ActivitySource(
        "companyname.product.instrumentationlibrary",
        "semver1.0.0");
    

    上面的代码要求导入 System.Diagnostics 命名空间。

  3. 使用 ActivitySource 实例来创建 Activity 实例,用来表示单个的 Trace 。提供的参数是活动的 DisplayName

    var activity = activitySource.StartActivity("ActivityName");
    

    如果对于该 Activity 没有监听器,上面的活动将为 null。当最终的应用程序没有启用 OpenTelemetry 的时候就会发生。或者 OpenTelemetry 的采样器不采样此 Actitity 的时候。确保后继的使用该 activity 的操作进行 null 检查

  4. 使用 OpenTelemetry 语义约定填充 activity。非常建议检查 activity.IsAllDataRequested,在填充任何没有快速可用的数据之前。IsAllDataRequested 类似于 Span.IsRecording ,当采样器决定不采样该 activity 的时候,将返回 false。这可以用来忽略任何昂贵的提取标志的操作

    activity?.SetTag("http.method", "GET");
    if (activity != null && activity.IsAllDataRequested == true)
    {
        activity.SetTag("http.url", "http://www.mywebsite.com");
    }
    

    建议的方式是使用 Activity 类的 SetTag 来设置 span 属性。OpenTelemetry 用户不应该使用其它方法,比如 AddTag(),SetCustomProperty 等等

  5. 执行应用逻辑

  6. 在业务逻辑完成之后,停止 activity。

    activity?.Stop();
    

    另外,由于 Activity 已经实现了 IDisposable 接口,可以使用 using 块来确保 activity 在回收之前停止,如下所示

    using (var activity = activitySource.StartActivity("ActivityName")
    {
        activity?.SetTag("http.method", "GET");
    } // Activity gets stopped automatically at end of this block during dispose.
    

以上展示了使用 Activity 进行测量的基本用法。

Activity 创建的选项

以上的基本使用介绍了使用 StartActivity 来开始一个 Activity。启动的 Activity 自动变成 Current 活动。重要的是要注意,如果没有监听器作用于该 Activity 的话, StartActivity 返回 null。当应用程序没有启用 OpenTelemetry,或者当 OpenTelemetry 的采样器不采样此 Activity 的话。

StartActivity 有多个重载来控制 activity 的创建

  1. ActivityKind

    Activity 有一个称为 ActivityKind 的属性,表示 OpenTelemetry 的 SpanKind。默认值为 Internal。StartActivity 允许传递 ActivityKind

    var activity = activitySource.StartActivity("ActivityName", ActivityKind.Server);
    
  2. Parent,使用 ActivityContext

    ActivityContext 表示 OpenTelemetry 的 SpanContext。当启动一个新的 Activity 的时候,当前活动的 Activity 自动获取它,作为新创建的 Activity 的父节点。StartActivity 支持传递显式的 ActivityContext 来覆盖此行为。

    var parentContext = new ActivityContext(
        ActivityTraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c"),
        ActivitySpanId.CreateFromString("b7ad6b7169203331"),
        ActivityTraceFlags.None);
    
    var activity = activitySource.StartActivity(
        "ActivityName",
        ActivityKind.Server,
        parentContext);
    

    ActivityContext 支持 W3C Trace-Context 规范,还可以使用符合 W3C Trace-Context 规范的单个字符串来提供父 Span 的上下文。如下所示

    var activity = activitySource.StartActivity(
        "ActivityName",
        ActivityKind.Server,
        "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01");
    
  3. 初始标志

    Activity 中的 Tag 表示 OpenTelemetry 中的 Span 属性。前面的示例展示了使用 Activity 的 SetTag() 来添加标志。还可以在创建 Activity 的时候提供初始化标志。如下所示。提供的标志可以被采样器所访问,而使用 SetTag() 方法添加的对于采样器不可用。

    var initialTags = new ActivityTagsCollection();
    
    initialTags["com.mycompany.product.mytag1"] = "tagValue1";
    initialTags["com.mycompany.product.mytag2"] = "tagValue2";
    
    var activity = activitySource.StartActivity(
        "ActivityName",
        ActivityKind.Server,
        "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01",
        initialTags);
    

    上面的代码需要引入命名空间 System.Collections.Generic。

  4. Activity Links

    除了父子关联,activity 之间还可以使用 ActivityLink 来连接,它表示 OpenTelemetry 的 Link。连接的 Activity 必须在创建时提供,如下所示

    var activityLinks = new List<ActivityLink>();
    
    var linkedContext1 = new ActivityContext(
        ActivityTraceId.CreateFromString("0af7651916cd43dd8448eb211c80319c"),
        ActivitySpanId.CreateFromString("b7ad6b7169203331"),
        ActivityTraceFlags.None);
    
    var linkedContext2 = new ActivityContext(
        ActivityTraceId.CreateFromString("4bf92f3577b34da6a3ce929d0e0e4736"),
        ActivitySpanId.CreateFromString("00f067aa0ba902b7"),
        ActivityTraceFlags.Recorded);
    
    activityLinks.Add(new ActivityLink(linkedContext1));
    activityLinks.Add(new ActivityLink(linkedContext2));
    
    var activity = activitySource.StartActivity(
        "ActivityWithLinks",
        ActivityKind.Server,
        default(ActivityContext),
        initialTags,
        activityLinks);
    

    注意,上面创建的 Activity 使用了 default(ActivityContext) 父节点,这使得它隐式成为 Activity.Current 的子节点。如果没有 Current 的话,就是一个孤儿节点。

添加 event

可以使用 AddEvent() 方法来为 Activity 添加事件

activity?.AddEvent(new ActivityEvent("sample activity event."));

除了提供 name,timestamp 之外,可以使用 ActivityEvent 来添加属性。

设置状态

OpenTelemetry 定义了称为 Status 关联到 Activity。在 .NET 中,没有 Status 类,请注意 Status 是使用如下的 tag 来设置到 Activity 的。

otel.status_code 是用来存储状态码 StatusCodeTagotel.status_description 是用来存储可选的描述信息 DescriptionTag

例如

activity?.SetTag("otel.status_code", "ERROR");
activity?.SetTag("otel.status_description", "error status description");

StatusCode 的值必须为字符串 UNSETOK 或者 ERROR 之一,它相关与 StatusCode 枚举的值

  • Unset
  • Ok
  • Error

如果使用 OpenTelemetry API 的垫片,那么你可以借助于 Activity 方法的扩展 SetStatus()。

使用 OpenTelemetry.API 垫片

如入门部分所述,除非你希望使用 OpenTelemetry 术语,例如 Tracer,才建议使用垫片。

请参考如下代码使用 垫片。

参考

Instrumenting a .NET web API using OpenTelemetry, Tempo, and Grafana Cloud | Grafana Labs

https://opentelemetry.lightstep.com/csharp/

posted on 2023-03-17 20:55  冠军  阅读(97)  评论(0编辑  收藏  举报