AWS Distro for OpenTelemetry
OpenTelemetryは、オープンソースのプロジェクトで、
アプリケーション監視用の分散トレースとメトリックを収集するために、
ライブラリ・API・エージェントが提供されています。
AWS Distro for OpenTelemetryはOpenTelemetryをAWSで使うためのディストリビューションです。
OpenTelemetry自体については、freeCodeCamp.orgの動画が参考になるかと思います。
AWS Distro for OpenTelemetry Collector
OpenTelemetry Collectorについてはこちらが参考になります。
こちらのdocker版サンプルを実施します。
以下のソースコードをcheckoutし、exampleフォルダへ移動します。
% git clone https://github.com/aws-observability/aws-otel-collector.git
% cd aws-otel-collector/examples/docker/
以下コマンドで実行します。
% docker-compose up
OpenTelemetry Go SDK on Traces Instrumentation
以下を参考に実施します。
Global Tracerの設定
以下のサンプルアプリを使います。
OpenTelemetry Protocol (OTLP) Exporterの作成
OpenTelemetry Goではバックエンドにトレースを送信する場合には、Exporterが必要になるようです。
ここではADOT Collectorへ送信するため、以下のようにExporterを作成します。
// Create and start new OTLP trace exporter
traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint("0.0.0.0:4317"), otlptracegrpc.WithDialOption(grpc.WithBlock()))
if err != nil {
log.Fatalf("%s: %v", "failed to create new OTLP trace exporter", err)
}
Tracer Providerの作成
Traceの生成用に、Tracer Providerを作成します。
上記で作成したExporterと、ID generatorを設定します。
idg := xray.NewIDGenerator()
tp := trace.NewTracerProvider(
trace.WithSampler(trace.AlwaysSample()),
trace.WithBatcher(traceExporter)
trace.WithIDGenerator(idg),
)
アプリケーションの実装
エンドポイントが2つ用意されています。
/aws-sdk-call
と
r.HandleFunc("/aws-sdk-call", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
ctx := r.Context()
xrayTraceID := getXrayTraceID(trace.SpanFromContext(ctx))
json := simplejson.New()
json.Set("traceId", xrayTraceID)
payload, _ := json.MarshalJSON()
_, _ = w.Write(payload)
}))
/outgoing-http-call
こちらはhttpリクエストのタイミングと、その後のカスタム計装の2箇所でspanが作成されています。
r.HandleFunc("/outgoing-http-call", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
client := http.Client{Transport: otelhttp.NewTransport(http.DefaultTransport)}
ctx := r.Context()
xrayTraceID, _ := func(ctx context.Context) (string, error) {
req, _ := http.NewRequestWithContext(ctx, "GET", "https://aws.amazon.com", nil)
res, err := client.Do(req)
if err != nil {
handleErr(err, "HTTP call to aws.amazon.com failed")
}
_, _ = ioutil.ReadAll(res.Body)
_ = res.Body.Close()
return getXrayTraceID(trace.SpanFromContext(ctx)), err
}(ctx)
ctx, span := tracer.Start(
ctx,
"CollectorExporter-Example",
trace.WithAttributes(commonLabels...))
defer span.End()
json := simplejson.New()
json.Set("traceId", xrayTraceID)
payload, _ := json.MarshalJSON()
_, _ = w.Write(payload)
}))
以下のコマンドで実行します。
% go build -o sampleapp
% ./sampleapp
Aws-OTel-Collectorインスタンスの実行
先ほどのdocker版サンプルのシングルインスタンス版を使用します。
AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
を環境変数に設定した上で、以下を実行します。
% cd aws-otel-collector/examples/docker/
% docker run --rm -p 4317:4317 -p 55680:55680 -p 8889:8888 \
-e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" \
-e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" \
-e AWS_REGION=us-west-2 \
-v "${PWD}/examples/docker/config-test.yaml":/otel-local-config.yaml \
--name awscollector public.ecr.aws/aws-observability/aws-otel-collector:latest \
--config otel-local-config.yaml;
この状態で、localhost:8080/aws-sdk-call
にアクセスすると、X-Rayで以下トレースが確認できます。
また、localhost:8080/outgoing-http-call
にアクセスすると同じく以下が確認できます。
CollectorExporter-Example
の方のメタデータは以下になっていました。