翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
OpenTelemetry Go への移行
次のコード例を使用して、X-Ray から移行するときに OpenTelemetry SDK を使用して Go アプリケーションを手動で計測します。
SDK を使用した手動計測
- Tracing setup with X-Ray SDK
-
X-Ray SDK for Go を使用する場合、コードを実装する前にサービスプラグインまたはローカルサンプリングルールを設定する必要があります。
func init() { if os.Getenv("ENVIRONMENT") == "production" { ec2.Init() } xray.Configure(xray.Config{ DaemonAddr: "127.0.0.1:2000", ServiceVersion: "1.2.3", }) }
- Set up tracing with OpenTelemetry SDK
-
TracerProvider をインスタンス化し、グローバルトレーサープロバイダーとして登録して、OpenTelemetry SDK を設定します。以下のコンポーネントを設定することをお勧めします。
-
OTLP トレースエクスポーター – CloudWatch エージェントまたは OpenTelemetry Collector へのトレースのエクスポートに必要です
-
X-Ray Propagator – X-Ray と統合された AWS サービスにトレースコンテキストを伝達するために必要です
-
X-Ray リモートサンプラー – X-Ray サンプリングルールを使用したリクエストのサンプリングに必要です
-
リソースディテクター – アプリケーションを実行しているホストのメタデータを検出するには
import ( "go.opentelemetry.io/contrib/detectors/aws/ec2" "go.opentelemetry.io/contrib/propagators/aws/xray" "go.opentelemetry.io/contrib/samplers/aws/xray" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/sdk/trace" ) func setupTracing() error { ctx := context.Background() exporterEndpoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") if exporterEndpoint == "" { exporterEndpoint = "localhost:4317" } traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), otlptracegrpc.WithEndpoint(exporterEndpoint)) if err != nil { return fmt.Errorf("failed to create OTLP trace exporter: %v", err) } remoteSampler, err := xray.NewRemoteSampler(ctx, "my-service-name", "ec2") if err != nil { return fmt.Errorf("failed to create X-Ray Remote Sampler: %v", err) } ec2Resource, err := ec2.NewResourceDetector().Detect(ctx) if err != nil { return fmt.Errorf("failed to detect EC2 resource: %v", err) } tp := trace.NewTracerProvider( trace.WithSampler(remoteSampler), trace.WithBatcher(traceExporter), trace.WithResource(ec2Resource), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(xray.Propagator{}) return nil }
-
受信リクエストのトレース (HTTP ハンドラー計測)
- With X-Ray SDK
-
X-Ray を使用して HTTP ハンドラーを計測するために、X-Ray ハンドラーメソッドを使用して NewFixedSegmentNamer を使用してセグメントを生成しました。
func main() { http.Handle("/", xray.Handler(xray.NewFixedSegmentNamer("myApp"), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello!")) }))) http.ListenAndServe(":8000", nil) }
- With OpenTelemetry SDK
OpenTelemetry を使用して HTTP ハンドラーを計測するには、OpenTelemetry の newHandler メソッドを使用して元のハンドラーコードをラップします。
import ( "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) helloHandler := func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() span := trace.SpanFromContext(ctx) span.SetAttributes(attribute.Bool("isHelloHandlerSpan", true), attribute.String("attrKey", "attrValue")) _, _ = io.WriteString(w, "Hello World!\n") } otelHandler := otelhttp.NewHandler(http.HandlerFunc(helloHandler), "Hello") http.Handle("/hello", otelHandler) err = http.ListenAndServe(":8080", nil) if err != nil { log.Fatal(err) }
AWS SDK for Go v2 の計測
- With X-Ray SDK
-
AWS SDK からの送信 AWS リクエストを計測するために、クライアントは次のように計測されました。
// Create a segment ctx, root := xray.BeginSegment(context.TODO(), "AWSSDKV2_Dynamodb") defer root.Close(nil) cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-west-2")) if err != nil { log.Fatalf("unable to load SDK config, %v", err) } // Instrumenting AWS SDK v2 awsv2.AWSV2Instrumentor(&cfg.APIOptions) // Using the Config value, create the DynamoDB client svc := dynamodb.NewFromConfig(cfg) // Build the request with its input parameters _, err = svc.ListTables(ctx, &dynamodb.ListTablesInput{ Limit: aws.Int32(5), }) if err != nil { log.Fatalf("failed to list tables, %v", err) }
- With OpenTelemetry SDK
-
ダウンストリーム AWS SDK 呼び出しのトレースサポートは、OpenTelemetry の AWS SDK for Go v2 Instrumentation によって提供されます。S3 クライアント呼び出しをトレースする例を次に示します。
import ( ... "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "go.opentelemetry.io/otel" oteltrace "go.opentelemetry.io/otel/trace" awsConfig "github.com/aws/aws-sdk-go-v2/config" "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws" ) ... // init aws config cfg, err := awsConfig.LoadDefaultConfig(ctx) if err != nil { panic("configuration error, " + err.Error()) } // instrument all aws clients otelaws.AppendMiddlewares(&.APIOptions) // Call to S3 s3Client := s3.NewFromConfig(cfg) input := &s3.ListBucketsInput{} result, err := s3Client.ListBuckets(ctx, input) if err != nil { fmt.Printf("Got an error retrieving buckets, %v", err) return }
送信 HTTP 呼び出しの計測
- With X-Ray SDK
-
X-Ray を使用して送信 HTTP 呼び出しを計測するために、xray.Client を使用して提供された HTTP クライアントのコピーを作成しました。
myClient := xray.Client(http-client) resp, err := ctxhttp.Get(ctx, xray.Client(nil), url)
- With OpenTelemetry SDK
-
OpenTelemetry を使用して HTTP クライアントを計測するには、OpenTelemetry の otelhttp.NewTransport メソッドを使用して http.DefaultTransport をラップします。
import ( "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) // Create an instrumented HTTP client. httpClient := &http.Client{ Transport: otelhttp.NewTransport( http.DefaultTransport, ), } req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.github.com/repos/aws-observability/aws-otel-go/releases/latest", nil) if err != nil { fmt.Printf("failed to create http request, %v\n", err) } res, err := httpClient.Do(req) if err != nil { fmt.Printf("failed to make http request, %v\n", err) } // Request body must be closed defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { fmt.Printf("failed to close http response body, %v\n", err) } }(res.Body)
他のライブラリの計測サポート
OpenTelemetry Go でサポートされているライブラリインストルメンテーションの完全なリストは、インストルメンテーションパッケージ
または、OpenTelemetry レジストリを検索して、OpenTelemetry が Registry
トレースデータを手動で作成する
- With X-Ray SDK
-
X-Ray SDK では、X-Ray セグメントとサブセグメントを手動で作成するにはBeginSegment メソッドと BeginSubsegment メソッドが必要でした。 BeginSubsegment
// Start a segment ctx, seg := xray.BeginSegment(context.Background(), "service-name") // Start a subsegment subCtx, subSeg := xray.BeginSubsegment(ctx, "subsegment-name") // Add metadata or annotation here if necessary xray.AddAnnotation(subCtx, "annotationKey", "annotationValue") xray.AddMetadata(subCtx, "metadataKey", "metadataValue") subSeg.Close(nil) // Close the segment seg.Close(nil)
- With OpenTelemetry SDK
カスタムスパンを使用して、計測ライブラリによってキャプチャされない内部アクティビティのパフォーマンスをモニタリングします。この種のスパン Server のみが X-Ray セグメントに変換され、他のすべてのスパンは X-Ray サブセグメントに変換されることに注意してください。
まず、
otel.Tracer
メソッドで取得できるスパンを生成する Tracer を作成する必要があります。これにより、トレースセットアップの例でグローバルに登録された TracerProvider の Tracer インスタンスが提供されます。必要に応じていくつでも Tracer インスタンスを作成できますが、アプリケーション全体に 1 つの Tracer を持つことが一般的です。tracer := otel.Tracer("application-tracer")
import ( ... oteltrace "go.opentelemetry.io/otel/trace" ) ... var attributes = []attribute.KeyValue{ attribute.KeyValue{Key: "metadataKey", Value: attribute.StringValue("metadataValue")}, attribute.KeyValue{Key: "annotationKey", Value: attribute.StringValue("annotationValue")}, attribute.KeyValue{Key: "aws.xray.annotations", Value: attribute.StringSliceValue([]string{"annotationKey"})}, } ctx := context.Background() parentSpanContext, parentSpan := tracer.Start(ctx, "ParentSpan", oteltrace.WithSpanKind(oteltrace.SpanKindServer), oteltrace.WithAttributes(attributes...)) _, childSpan := tracer.Start(parentSpanContext, "ChildSpan", oteltrace.WithSpanKind(oteltrace.SpanKindInternal)) // ... childSpan.End() parentSpan.End()
OpenTelemetry SDK を使用してトレースに注釈とメタデータを追加する
上記の例では、
WithAttributes
メソッドを使用して各スパンに属性を追加します。デフォルトでは、すべてのスパン属性は X-Ray raw データ内のメタデータに変換されることに注意してください。属性がメタデータではなく注釈に変換されるようにするには、属性のリストにaws.xray.annotations
属性のキーを追加します。詳細については、「カスタマイズされた X-Ray 注釈を有効にする」を参照してください。
Lambda 手動計測
- With X-Ray SDK
-
X-Ray SDK では、Lambda でアクティブトレースを有効にした後、X-Ray SDK を使用するために必要な追加の設定はありませんでした。Lambda は Lambda ハンドラー呼び出しを表すセグメントを作成し、追加の設定なしで X-Ray SDK を使用してサブセグメントを作成しました。
- With OpenTelemetry SDK
-
次の Lambda 関数コード (計測なし) は、Amazon S3 ListBuckets 呼び出しと送信 HTTP リクエストを行います。
package main import ( "context" "encoding/json" "fmt" "io" "net/http" "os" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" ) func lambdaHandler(ctx context.Context) (interface{}, error) { // Initialize AWS config. cfg, err := awsconfig.LoadDefaultConfig(ctx) if err != nil { panic("configuration error, " + err.Error()) } s3Client := s3.NewFromConfig(cfg) // Create an HTTP client. httpClient := &http.Client{ Transport: http.DefaultTransport, } input := &s3.ListBucketsInput{} result, err := s3Client.ListBuckets(ctx, input) if err != nil { fmt.Printf("Got an error retrieving buckets, %v", err) } fmt.Println("Buckets:") for _, bucket := range result.Buckets { fmt.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday")) } fmt.Println("End Buckets.") req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.github.com/repos/aws-observability/aws-otel-go/releases/latest", nil) if err != nil { fmt.Printf("failed to create http request, %v\n", err) } res, err := httpClient.Do(req) if err != nil { fmt.Printf("failed to make http request, %v\n", err) } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { fmt.Printf("failed to close http response body, %v\n", err) } }(res.Body) var data map[string]interface{} err = json.NewDecoder(res.Body).Decode(&data) if err != nil { fmt.Printf("failed to read http response body, %v\n", err) } fmt.Printf("Latest ADOT Go Release is '%s'\n", data["name"]) return events.APIGatewayProxyResponse{ StatusCode: http.StatusOK, Body: os.Getenv("_X_AMZN_TRACE_ID"), }, nil } func main() { lambda.Start(lambdaHandler) }
Lambda ハンドラーと Amazon S3 クライアントを手動で計測するには、次の手順を実行します。
-
main() で、TracerProvider (tp) をインスタンス化し、グローバルトレーサープロバイダーとして登録します。TracerProvider は、以下を使用して設定することをお勧めします。
-
Lambda の UDP X-Ray エンドポイントにトレースを送信するための X-Ray UDP スパンエクスポーターを備えたシンプルなスパンプロセッサ
-
service.name を Lambda 関数名に設定したリソース
-
-
の使用を
lambda.Start(lambdaHandler)
に変更しますlambda.Start(otellambda.InstrumentHandler(lambdaHandler, xrayconfig.WithRecommendedOptions(tp)...))
。 -
の OpenTelemetry ミドルウェアを Amazon S3 クライアント設定に追加OpenTelemetry SDK 計測を使用して Amazon S3 クライアント
aws-sdk-go-v2
を計測します。 OpenTemetry AWS -
OpenTelemetry の
otelhttp.NewTransport
メソッドを使用して をラップすることで、http クライアントを計測しますhttp.DefaultTransport
。
次のコードは、変更後に Lambda 関数がどのように表示されるかの例です。自動的に提供されるスパンに加えて、追加のカスタムスパンを手動で作成できます。
package main import ( "context" "encoding/json" "fmt" "io" "net/http" "os" "github.com/aws-observability/aws-otel-go/exporters/xrayudp" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda/xrayconfig" "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/contrib/propagators/aws/xray" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.26.0" ) func lambdaHandler(ctx context.Context) (interface{}, error) { // Initialize AWS config. cfg, err := awsconfig.LoadDefaultConfig(ctx) if err != nil { panic("configuration error, " + err.Error()) } // Instrument all AWS clients. otelaws.AppendMiddlewares(&cfg.APIOptions) // Create an instrumented S3 client from the config. s3Client := s3.NewFromConfig(cfg) // Create an instrumented HTTP client. httpClient := &http.Client{ Transport: otelhttp.NewTransport( http.DefaultTransport, ), } // return func(ctx context.Context) (interface{}, error) { input := &s3.ListBucketsInput{} result, err := s3Client.ListBuckets(ctx, input) if err != nil { fmt.Printf("Got an error retrieving buckets, %v", err) } fmt.Println("Buckets:") for _, bucket := range result.Buckets { fmt.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday")) } fmt.Println("End Buckets.") req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.github.com/repos/aws-observability/aws-otel-go/releases/latest", nil) if err != nil { fmt.Printf("failed to create http request, %v\n", err) } res, err := httpClient.Do(req) if err != nil { fmt.Printf("failed to make http request, %v\n", err) } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { fmt.Printf("failed to close http response body, %v\n", err) } }(res.Body) var data map[string]interface{} err = json.NewDecoder(res.Body).Decode(&data) if err != nil { fmt.Printf("failed to read http response body, %v\n", err) } fmt.Printf("Latest ADOT Go Release is '%s'\n", data["name"]) return events.APIGatewayProxyResponse{ StatusCode: http.StatusOK, Body: os.Getenv("_X_AMZN_TRACE_ID"), }, nil } func main() { ctx := context.Background() detector := lambdadetector.NewResourceDetector() lambdaResource, err := detector.Detect(context.Background()) if err != nil { fmt.Printf("failed to detect lambda resources: %v\n", err) } var attributes = []attribute.KeyValue{ attribute.KeyValue{Key: semconv.ServiceNameKey, Value: attribute.StringValue(os.Getenv("AWS_LAMBDA_FUNCTION_NAME"))}, } customResource := resource.NewWithAttributes(semconv.SchemaURL, attributes...) mergedResource, _ := resource.Merge(lambdaResource, customResource) xrayUdpExporter, _ := xrayudp.NewSpanExporter(ctx) tp := trace.NewTracerProvider( trace.WithSpanProcessor(trace.NewSimpleSpanProcessor(xrayUdpExporter)), trace.WithResource(mergedResource), ) defer func(ctx context.Context) { err := tp.Shutdown(ctx) if err != nil { fmt.Printf("error shutting down tracer provider: %v", err) } }(ctx) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(xray.Propagator{}) lambda.Start(otellambda.InstrumentHandler(lambdaHandler, xrayconfig.WithRecommendedOptions(tp)...)) }
-
Lambda を呼び出すと、CloudWatch コンソールTrace Map
の に次のトレースが表示されます。
