Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
Zu OpenTelemetry Go migrieren
Verwenden Sie die folgenden Codebeispiele, um Ihre Go-Anwendungen bei der Migration von X-Ray manuell mit dem OpenTelemetry SDK zu instrumentieren.
Manuelle Instrumentierung mit dem SDK
- Tracing setup with X-Ray SDK
-
Bei der Verwendung des X-Ray-SDK SDK for Go mussten Service-Plugins oder lokale Sampling-Regeln konfiguriert werden, bevor Ihr Code instrumentiert wurde.
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
-
Konfigurieren Sie das OpenTelemetry SDK, indem Sie a instanziieren TracerProvider und es als globalen Tracer-Anbieter registrieren. Wir empfehlen die Konfiguration der folgenden Komponenten:
-
OTLP Trace Exporter — Erforderlich für den Export von Traces an den CloudWatch Agent oder Collector OpenTelemetry
-
X-Ray Propagator — Erforderlich für die Weitergabe des Trace-Kontextes an in X-Ray integrierte AWS Dienste
-
X-Ray Remote Sampler — Erforderlich für Probenentnahmeanfragen unter Verwendung von Röntgenprobenregeln
-
Ressourcendetektoren — Um Metadaten des Hosts zu erkennen, auf dem Ihre Anwendung ausgeführt wird
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 }
-
Nachverfolgung eingehender Anfragen (HTTP-Handler-Instrumentierung)
- With X-Ray SDK
-
Um einen HTTP-Handler mit X-Ray zu instrumentieren, wurde die X-Ray-Handler-Methode verwendet, um Segmente zu generieren mit 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
Um einen HTTP-Handler zu instrumentieren OpenTelemetry, verwenden Sie die NewHandler-Methode OpenTelemetry von, um Ihren ursprünglichen Handler-Code zu umschließen.
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-Instrumentierung
- With X-Ray SDK
-
Um ausgehende AWS Anfragen vom AWS SDK zu instrumentieren, wurden Ihre Kunden wie folgt instrumentiert:
// 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
-
Die Ablaufverfolgungsunterstützung für AWS Downstream-SDK-Aufrufe wird vom OpenTelemetry AWS SDK for Go v2 Instrumentation bereitgestellt. Hier ist ein Beispiel für die Nachverfolgung eines S3-Client-Anrufs:
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 }
Instrumentieren von ausgehenden HTTP-Aufrufen
- With X-Ray SDK
-
Um ausgehende HTTP-Aufrufe mit X-Ray zu instrumentieren, wurde der Xray.Client verwendet, um eine Kopie eines bereitgestellten HTTP-Clients zu erstellen.
myClient := xray.Client(http-client) resp, err := ctxhttp.Get(ctx, xray.Client(nil), url)
- With OpenTelemetry SDK
-
Um HTTP-Clients mit zu instrumentieren OpenTelemetry, verwenden Sie OpenTelemetry otelhttp. NewTransport Methode, um das HTTP zu umschließen. 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)
Instrumentierungsunterstützung für andere Bibliotheken
Die vollständige Liste der unterstützten Bibliotheksinstrumentierungen für OpenTelemetry Go finden Sie unter Instrumentierungspakete
Alternativ können Sie in der OpenTelemetry Registry
Manuelles Erstellen von Trace-Daten
- With X-Ray SDK
-
Mit dem X-Ray-SDK waren die BeginSubsegment Methoden BeginSegment und erforderlich, um X-Ray-Segmente und Untersegmente manuell zu erstellen.
// 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
Verwenden Sie benutzerdefinierte Zeitspannen, um die Leistung interner Aktivitäten zu überwachen, die nicht in den Instrumentenbibliotheken erfasst werden. Beachten Sie, dass nur Bereiche der Art Server in X-Ray-Segmente umgewandelt werden, alle anderen Bereiche werden in X-Ray-Untersegmente umgewandelt.
Zunächst müssen Sie einen Tracer erstellen, um Spannen zu generieren, die Sie mit der Methode abrufen können.
otel.Tracer
Dadurch wird eine Tracer-Instanz aus dem bereitgestellt TracerProvider , der im Tracing-Setup-Beispiel global registriert wurde. Sie können so viele Tracer-Instanzen wie nötig erstellen, aber es ist üblich, einen Tracer für eine gesamte Anwendung zu verwenden.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()
Hinzufügen von Anmerkungen und Metadaten zu Traces mit dem SDK OpenTelemetry
Im obigen Beispiel wird die
WithAttributes
Methode verwendet, um jedem Bereich Attribute hinzuzufügen. Beachten Sie, dass standardmäßig alle Span-Attribute in X-Rohdaten in Metadaten umgewandelt werden. Um sicherzustellen, dass ein Attribut in eine Anmerkung und nicht in Metadaten umgewandelt wird, fügen Sie den Schlüssel des Attributs zur Liste desaws.xray.annotations
Attributs hinzu. Weitere Informationen finden Sie unter Aktivieren der benutzerdefinierten X-Ray-Anmerkungen.
Manuelle Lambda-Instrumentierung
- With X-Ray SDK
-
Mit dem X-Ray-SDK waren nach der Aktivierung von Active Tracing auf Ihrem Lambda keine zusätzlichen Konfigurationen erforderlich, um das X-Ray-SDK zu verwenden. Lambda hat ein Segment erstellt, das den Lambda-Handler-Aufruf darstellt, und Sie haben Untersegmente mit dem X-Ray SDK ohne zusätzliche Konfiguration erstellt.
- With OpenTelemetry SDK
-
Der folgende Lambda-Funktionscode (ohne Instrumentierung) führt einen Amazon S3 ListBuckets S3-Aufruf und eine ausgehende HTTP-Anfrage aus.
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) }
Gehen Sie wie folgt vor, um Ihren Lambda-Handler und den Amazon S3 S3-Client manuell zu instrumentieren:
-
Instanziieren Sie in main () a TracerProvider (tp) und registrieren Sie es als globalen Tracer-Anbieter. TracerProvider Es wird empfohlen, den zu konfigurieren mit:
-
Einfacher Span-Prozessor mit einem X-Ray-UDP-Span-Exporter zum Senden von Traces an den UDP-X-Ray-Endpunkt von Lambda
-
Ressource, bei der service.name auf den Lambda-Funktionsnamen gesetzt ist
-
-
Ändern Sie die Verwendung von to.
lambda.Start(lambdaHandler)
lambda.Start(otellambda.InstrumentHandler(lambdaHandler, xrayconfig.WithRecommendedOptions(tp)...))
-
Instrumentieren Sie den Amazon S3 S3-Client mit der OpenTemetry AWS SDK-Instrumentierung, indem Sie OpenTelemetry Middleware für an
aws-sdk-go-v2
die Amazon S3 S3-Client-Konfiguration anhängen. -
Instrumentieren Sie den HTTP-Client, indem Sie die
otelhttp.NewTransport
Methode verwenden, um OpenTelemetry den zu umschließen.http.DefaultTransport
Der folgende Code ist ein Beispiel dafür, wie die Lambda-Funktion nach den Änderungen aussehen wird. Sie können zusätzlich zu den automatisch bereitgestellten Bereichen manuell weitere benutzerdefinierte Bereiche erstellen.
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)...)) }
-
Wenn Sie Lambda aufrufen, sehen Sie in der Konsole den folgenden Trace: Trace Map
CloudWatch
