Esegui la migrazione a OpenTelemetry Go - AWS X-Ray

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Esegui la migrazione a OpenTelemetry Go

Usa i seguenti esempi di codice per strumentare manualmente le tue applicazioni Go con l' OpenTelemetry SDK durante la migrazione da X-Ray.

Strumentazione manuale con l'SDK

Tracing setup with X-Ray SDK

Quando si utilizzava X-Ray SDK for Go, era necessario configurare i plug-in di servizio o le regole di campionamento locali prima di utilizzare la strumentazione del codice.

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

Configura l' OpenTelemetry SDK creando un'istanza e registrandolo come provider di tracciamento globale TracerProvider . Ti consigliamo di configurare i seguenti componenti:

  • OTLP Trace Exporter: necessario per esportare le tracce nell'agente o nel raccoglitore CloudWatch OpenTelemetry

  • X-Ray Propagator: necessario per propagare il contesto di traccia ai AWS servizi integrati con X-Ray

  • X-Ray Remote Sampler: necessario per le richieste di campionamento che utilizzano le regole di campionamento a raggi X

  • Rilevatori di risorse: per rilevare i metadati dell'host che esegue l'applicazione

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 }

Tracciamento delle richieste in arrivo (strumentazione del gestore HTTP)

With X-Ray SDK

Per strumentare un gestore HTTP con X-Ray, è stato utilizzato il metodo del gestore X-Ray per generare segmenti utilizzando. 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

Per strumentare un gestore HTTP OpenTelemetry, utilizzate il metodo NewHandler per racchiudere il codice OpenTelemetry del gestore originale.

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 per strumentazione Go v2

With X-Ray SDK

Per gestire le AWS richieste in uscita da AWS SDK, i vostri clienti hanno utilizzato la seguente strumentazione:

// 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

Il supporto di tracciamento per le chiamate AWS SDK downstream è fornito da SDK for AWS Go OpenTelemetry v2 Instrumentation. Ecco un esempio di tracciamento di una chiamata client 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 }

Analisi delle chiamate HTTP in uscita

With X-Ray SDK

Per strumentare le chiamate HTTP in uscita con X-Ray, XRay.Client è stato utilizzato per creare una copia di un client HTTP fornito.

myClient := xray.Client(http-client) resp, err := ctxhttp.Get(ctx, xray.Client(nil), url)
With OpenTelemetry SDK

Per strumentare i client HTTP, usa's otelhttp. OpenTelemetry OpenTelemetry NewTransport metodo per avvolgere l'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)

Supporto alla strumentazione per altre librerie

Puoi trovare l'elenco completo delle strumentazioni di libreria supportate per OpenTelemetry Go nella sezione Pacchetti Instrumentation.

In alternativa, puoi cercare OpenTelemetry nel registro per scoprire se OpenTelemetry supporta la strumentazione per la tua libreria sotto Registry.

Creazione manuale di dati di traccia

With X-Ray SDK

Con X-Ray SDK, erano necessari i BeginSubsegment metodi BeginSegment and per creare manualmente segmenti e sottosegmenti X-Ray.

// 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

Utilizza intervalli personalizzati per monitorare le prestazioni delle attività interne che non vengono acquisite dalle librerie di strumentazione. Nota che solo gli intervalli di tipo Server vengono convertiti in segmenti X-Ray, tutti gli altri intervalli vengono convertiti in sottosegmenti X-Ray.

Innanzitutto, è necessario creare un Tracer per generare intervalli, che è possibile ottenere tramite il metodo. otel.Tracer Ciò fornirà un'istanza Tracer tra quelle registrate globalmente nell'esempio di Tracing Setup. TracerProvider È possibile creare tutte le istanze Tracer necessarie, ma è comune avere una sola istanza Tracer per un'intera applicazione.

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()

Aggiungere annotazioni e metadati alle tracce con SDK OpenTelemetry

Nell'esempio precedente, il WithAttributes metodo viene utilizzato per aggiungere attributi a ogni intervallo. Si noti che per impostazione predefinita, tutti gli attributi span vengono convertiti in metadati nei dati grezzi X-Ray. Per garantire che un attributo venga convertito in un'annotazione e non in metadati, aggiungete la chiave dell'attributo all'elenco dell'attributo. aws.xray.annotations Per ulteriori informazioni, vedere Abilitare le annotazioni X-Ray personalizzate.

Strumentazione manuale Lambda

With X-Ray SDK

Con l'SDK X-Ray, dopo aver abilitato l'Active Tracing in Lambda, non erano necessarie configurazioni aggiuntive per utilizzare l'SDK X-Ray. Lambda ha creato un segmento che rappresenta l'invocazione del gestore Lambda e tu hai creato dei sottosegmenti utilizzando X-Ray SDK senza alcuna configurazione aggiuntiva.

With OpenTelemetry SDK

Il seguente codice di funzione Lambda (senza strumentazione) effettua una chiamata Amazon S3 e una richiesta HTTP in uscita ListBuckets .

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) }

Per strumentare manualmente il gestore Lambda e il client Amazon S3, procedi come segue:

  1. In main (), crea un'istanza a TracerProvider (tp) e registralo come fornitore di soluzioni di tracciamento globale. Si TracerProvider consiglia di configurarlo con:

    1. Simple Span Processor con un esportatore di span UDP a raggi X per inviare tracce all'endpoint UDP X-Ray di Lambda

    2. Risorsa con service.name impostato sul nome della funzione Lambda

  2. Cambia l'utilizzo di to. lambda.Start(lambdaHandler) lambda.Start(otellambda.InstrumentHandler(lambdaHandler, xrayconfig.WithRecommendedOptions(tp)...))

  3. Strumenta il client Amazon S3 con la strumentazione OpenTemetry AWS SDK aggiungendo OpenTelemetry middleware per aws-sdk-go-v2 nella configurazione del client Amazon S3.

  4. Strumenta il client http utilizzando il metodo's per avvolgere il. OpenTelemetry otelhttp.NewTransport http.DefaultTransport

Il codice seguente è un esempio di come apparirà la funzione Lambda dopo le modifiche. È possibile creare manualmente intervalli personalizzati aggiuntivi oltre agli intervalli forniti automaticamente.

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)...)) }

Quando richiami Lambda, vedrai la seguente traccia Trace Map nella CloudWatch console:

Traccia la mappa nella CloudWatch console per Golang.