August 19, 2021

分散トレース用のDotNetアプリケーションインストルメンテーション

分散トレース用のDotNetアプリケーションインストルメンテーション

このガイドを使用して、OpenTelemetry Protocol(OTLP)仕様を使用してトレースを発行するDotNet(.Net)アプリケーションを作成します。 必要なのは、.NET Framework4.6.2以降または.NETCore 2.1以降と、.NetFrameworkでのアプリケーション開発の基本的な理解だけです。

新しいプロジェクトを初期化する

まず、新しいコンソールアプリケーションを作成し、次のパッケージを追加してOpenTelemetryを有効にします。 これらは、IDEを使用するか、以下のようなコマンドラインでインストールできます。


dotnet new console --output getting-started
// Add dotnet packagesdotnet add package Opentelemetrydotnet add package Opentelemetry.Exporter.OpentelemetryProtocol

リソース検出器を作成する

リソースは、テレメトリ信号を生成したオブジェクトを記述します。 基本的に、これはサービスまたはアプリケーションの名前である必要があります。 OpenTelemetryは、サービス実行環境を説明するための標準を定義しています。 ホスト名、hostType(クラウド、コンテナー、サーバーレス)、名前空間、cloud-resource-idなど。

この例では、アプリケーションのいくつかのenvvar設定を使用してリソースを定義しています。

 var resourceList = new List<KeyValuePair<string, object>>();
 resourceList.Add(newKeyValuePair<string,object>
("service.namespace","US-West-1"));
 resourceList.Add(new KeyValuePair<string, object>("host.name",
"prodsvc.us-west-1.example.com"));
 resourceList.Add(new KeyValuePair<string, object>("host.type",
"system"));

TracerProviderを構築します 

sdk / traceパッケージには、OpenTelemetry分散トレースのサポートが含まれています。 TracerProviderは、OpenTelemetryAPIのエントリポイントです。

ここで、CreateTracerProviderBuilderは、新しく構成されたTracerProviderを返します。

 TracerProviderBuilder tracerProvider =
Sdk.CreateTracerProviderBuilder();

リソースビルダーを構成する 

ResourceBuilderのAddServiceメソッドを使用して、次の属性をResourceに追加できます。

  1. 文字列serviceName
  2. 文字列serviceNamespace
  3. 文字列serviceVersion
  4. bool autoGeneratedServiceInstanceId→falseの場合、XNUMX番目のパラメーターを設定する必要があります
  5. 文字列serviceInstanceId

次のドキュメントは、リソースの標準属性を定義しています。 リソースビルダーの仕様.

 string serviceName = "product-service";
 string instanceId = "product-service-instance-id";
 tracerProvider.AddAspNetCoreInstrumentation();
 tracerProvider.SetResourceBuilder(ResourceBuilder.CreateDefault()
      .AddService(serviceName, null, null, false,
$"{instanceId}").AddAttributes(resourceList));
 tracerProvider.SetSampler(new AlwaysOnSampler());
 tracerProvider.AddSource("TestActivitySource");

Init TraceExporter

OtlpExporterOptionsプロパティを使用してOtlpExporterを構成できます。

  • 終点: エクスポータがトレースまたはメトリックを送信するターゲット。 エンドポイントは、スキーム(HTTPまたはHTTPS)とホストを備えた有効なURIである必要があり、ポートとパスを含めることができます。
  • ヘッダー: 接続用のオプションのヘッダー。
  • TimeoutMilliseconds: バックエンドがバッチを処理するための最大待機時間。
  • ExportProcessorType:エクスポータがバッチまたはシンプルエクスポートプロセッサを使用する必要があるかどうか。
  • BatchExportProcessorOptions: バッチエクスポータの構成オプション。 ExportProcessorTypeがBatchに設定されている場合にのみ使用されます。

OTLPエクスポーターを使用してコレクターにトレースを送信するには、OTLP_ENDPOINT環境変数を設定する必要があります。 

var otlpEndpoint =Environment.GetEnvironmentVariable("OTLP_ENDPOINT")
??"http://localhost:55680";
 tracerProvider.AddOtlpExporter(opt => opt.Endpoint = 
new Uri(otlpEndpoint)).Build();

トレーサーを作成する 

OpenTelemetry.API Shimの使用は、ActivitySourceやActivityの代わりにTracerやSpanなどのOpenTelemetryの用語を使用する場合にのみ推奨されます。

次の例では、OpenTelemetry.APIShimを使用してスパンを生成しています。

       var tracer = TracerProvider.Default.GetTracer("TestActivitySource");

スパンを作成し、スパン属性を定義する

スパンは、操作のXNUMX回の実行です。 これは、スパンタグと呼ばれることもある一連の属性によって識別されます。 アプリケーションの所有者は、スパンに必要な情報を取得できる属性を自由に選択できます。 スパンごとのスパン属性の数に制限はありません。 

この例では、サンプルアプリケーションのXNUMXスパン属性を定義しています。

using (var parentSpan = tracer.StartActiveSpan("parent span"))
       {
           parentSpan.SetAttribute("priority", "business.priority");
           parentSpan.SetAttribute("prodEnv", true);
           parentSpan.UpdateName("parent span new name");
  }

スパンへのイベント/ログの追加

スパンは、スパンの実行中に発生したいくつかの実行ログ/イベントで強化できます。 この情報は、常にそれぞれのスパンに関連付けられたコンテキストログを提供するのに役立ちます。

 var childSpan = tracer.StartSpan("child span");
 childSpan.AddEvent("Authentication").SetAttribute("Username",
"value").SetAttribute("Id", 101);
 childSpan.SetStatus(OpenTelemetry.Trace.Status.Ok);
 childSpan.End();

それをまとめる

using System;
using System.Collections.Generic;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
 
public class Program
{
   public static void Main()
   {
       // Only Required when using insecure (http) endpoint
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.
   Http2UnencryptedSupport", true);
 
      var resourceList = new List<KeyValuePair<string, object>>();
      resourceList.Add(new KeyValuePair<string, object>("service.namespace",
         "US-West-1"));
      resourceList.Add(new KeyValuePair<string, object>("host.name",
   "prodsvc.us-west-1.example.com"));
      resourceList.Add(new KeyValuePair<string, object>("host.type",
   "system"));
 
      TracerProviderBuilder tracerProvider =Sdk.CreateTracerProviderBuilder(); 
 
      string serviceName = "product-service";
      string instanceId = "product-service-instance-id";
      tracerProvider.AddAspNetCoreInstrumentation();
      tracerProvider.SetResourceBuilder(ResourceBuilder.CreateDefault()
      .AddService(serviceName, null, null, false,
 	$"{instanceId}").AddAttributes(resourceList));
      tracerProvider.SetSampler(new AlwaysOnSampler());
      tracerProvider.AddSource("TestActivitySource");
 
      var otlpEndpoint = Environment.GetEnvironmentVariable("OTLP_ENDPOINT")
 	?? "http://localhost:55680";
      tracerProvider.AddOtlpExporter(opt => opt.Endpoint = new
 	Uri(otlpEndpoint)).Build();
      var tracer = TracerProvider.Default.GetTracer("TestActivitySource");
 
      using (var parentSpan = tracer.StartActiveSpan("parent span"))
      {
           parentSpan.SetAttribute("priority", "business.priority");
           parentSpan.SetAttribute("prodEnv", true);
           parentSpan.UpdateName("parent span new name");
 
           var childSpan = tracer.StartSpan("child span");
           childSpan.AddEvent("Authentication").SetAttribute("Username",
 	   "value").SetAttribute("Id", 101);
           childSpan.SetStatus(OpenTelemetry.Trace.Status.Ok);
           childSpan.End();
       }
   }
}

アプリケーションを実行する 

最後に、このインストルメント化されたアプリケーションを実行して、LogicMonitorプラットフォームでトレースを取得します。

dotnet run
LogicMonitorプラットフォームに表示されるトレース
LogicMonitorプラットフォーム内で強調表示されたサービス名とリソース属性

構築されたトレース

Resource labels:
     -> service.namespace: STRING(US-West-1)
     -> host.name: STRING(prodsvc.us-west-1.example.com)
     -> host.type: STRING(system)
     -> service.name: STRING(product-service)
     -> service.instance.id: STRING(product-service-instance-id)
InstrumentationLibrarySpans #0
InstrumentationLibrary TestActivitySource 
Span #0
    Trace ID       : 7b7d18466ee42b45b797a30fbc55f09e
    Parent ID      : 204b306e1ba7124d
    ID             : 8fd6f7414b2a4a4a
    Name           : child span
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2021-07-26 18:33:25.300514 +0530 IST
    End time       : 2021-07-26 18:33:25.302944 +0530 IST
    Status code    : STATUS_CODE_OK
    Status message : 
Attributes:
     -> UserName: STRING(value)
     -> Id: INT(101)
Events:
SpanEvent #0
     -> Name: sample event
     -> Timestamp: 1627304605301466000
     -> DroppedAttributesCount: 0
Span #1
    Trace ID       : 7b7d18466ee42b45b797a30fbc55f09e
    Parent ID      : 
    ID             : 204b306e1ba7124d
    Name           : parent span new name
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2021-07-26 18:33:25.29771 +0530 IST
    End time       : 2021-07-26 18:33:25.334138 +0530 IST
    Status code    : STATUS_CODE_UNSET
    Status message : 
Attributes:
     -> priority: STRING(business.priority)
     -> prodEnv: BOOL(true)

結論

おめでとうございます。OpenTelemetryProtocol(OTLP)仕様を使用してトレースを発行する.Netアプリケーションを作成しました。 OTLP仕様を使用してビジネスアプリケーションのインストルメント化を開始するときは、このコードを参照として自由に使用してください。 LogicMonitor APM仕様は、ベンダーロックインなしで100%OTLPに準拠しています。 LogicMonitorプラットフォームでトラブルシューティングするための複数のサービスのトレースを受信して​​視覚化するには、無料の試用アカウントにサインアップしてください 詳細を見る。 複数の言語にわたるOpenTelemetry標準を使用した分散トレースのアプリケーションインストルメンテーション手順をカバーするブログをチェックしてください。

アディチャ・バイラブカー

アディチャ・バイラブカー

アソシエイトソフトウェアエンジニア

AdityaBhairavkarはLogicMonitorの従業員です。