Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Migrer vers OpenTelemetry Go
Utilisez les exemples de code suivants pour instrumenter manuellement vos applications Go avec le OpenTelemetry SDK lors de la migration depuis X-Ray.
Instrumentation manuelle avec le SDK
- Tracing setup with X-Ray SDK
-
Lors de l'utilisation du SDK X-Ray pour Go, les plug-ins de service ou les règles d'échantillonnage locales devaient être configurés avant d'instrumenter votre code.
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
-
Configurez le OpenTelemetry SDK en instanciant un TracerProvider et en l'enregistrant en tant que fournisseur de traceurs global. Nous vous recommandons de configurer les composants suivants :
-
Exportateur de traces OTLP — Nécessaire pour exporter des traces vers l' CloudWatch agent ou OpenTelemetry le collecteur
-
X-Ray Propagator — Nécessaire pour propager le contexte de trace aux AWS services intégrés à X-Ray
-
X-Ray Remote Sampler : obligatoire pour les demandes d'échantillonnage utilisant les règles d'échantillonnage X-Ray
-
Détecteurs de ressources : pour détecter les métadonnées de l'hôte exécutant votre application
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 }
-
Suivi des demandes entrantes (instrumentation du gestionnaire HTTP)
- With X-Ray SDK
-
Pour instrumenter un gestionnaire HTTP avec X-Ray, la méthode du gestionnaire X-Ray a été utilisée pour générer des segments à l'aide de. 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
Pour instrumenter un gestionnaire HTTP OpenTelemetry, utilisez la OpenTelemetry méthode newHandler pour encapsuler le code de votre gestionnaire d'origine.
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 pour l'instrumentation du SDK Go v2
- With X-Ray SDK
-
Pour instrumenter les AWS demandes sortantes depuis le AWS SDK, vos clients ont été instrumentés comme suit :
// 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
-
La prise en charge du suivi des appels du AWS SDK en aval est fournie par OpenTelemetry le AWS SDK for Go v2 Instrumentation. Voici un exemple de suivi d'un appel 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 }
Instrumentation des appels HTTP sortants
- With X-Ray SDK
-
Pour instrumenter les appels HTTP sortants avec X-Ray, le Xray.Client a été utilisé pour créer une copie d'un client HTTP fourni.
myClient := xray.Client(http-client) resp, err := ctxhttp.Get(ctx, xray.Client(nil), url)
- With OpenTelemetry SDK
-
Pour instrumenter les clients HTTP OpenTelemetry, utilisez OpenTelemetry otelhttp. NewTransport méthode pour encapsuler le 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)
Support d'instrumentation pour d'autres bibliothèques
Vous trouverez la liste complète des instrumentations de bibliothèque prises en charge pour les packages OpenTelemetry Go sous Instrumentation
Vous pouvez également effectuer une recherche OpenTelemetry dans le registre pour savoir si l'instrumentation est OpenTelemetry compatible avec votre bibliothèque sous Registre
Création manuelle de données de trace
- With X-Ray SDK
-
Avec le SDK X-Ray, les BeginSubsegment méthodes BeginSegment et étaient nécessaires pour créer manuellement des segments et des sous-segments 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
Utilisez des intervalles personnalisés pour surveiller les performances des activités internes qui ne sont pas capturées par les bibliothèques d'instrumentation. Notez que seules les plages de type Server sont converties en segments X-Ray, toutes les autres plages sont converties en sous-segments de X-Ray.
Tout d'abord, vous devez créer un traceur pour générer des spans, que vous pouvez obtenir grâce à la
otel.Tracer
méthode. Cela fournira une instance de Tracer TracerProvider qui a été enregistrée globalement dans l'exemple de configuration du suivi. Vous pouvez créer autant d'instances de Tracer que nécessaire, mais il est courant d'avoir un seul Tracer pour l'ensemble d'une application.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()
Ajouter des annotations et des métadonnées aux traces avec OpenTelemetry le SDK
Dans l'exemple ci-dessus, la
WithAttributes
méthode est utilisée pour ajouter des attributs à chaque intervalle. Notez que par défaut, tous les attributs de span sont convertis en métadonnées dans les données brutes de X-Ray. Pour vous assurer qu'un attribut est converti en annotation et non en métadonnées, ajoutez la clé de l'attribut à la liste de l'aws.xray.annotations
attribut. Pour plus d'informations, consultez Enable The Customized X-Ray Annotations.
Instrumentation manuelle Lambda
- With X-Ray SDK
-
Avec le SDK X-Ray, une fois qu'Active Tracing a été activé sur votre Lambda, aucune configuration supplémentaire n'était requise pour utiliser le SDK X-Ray. Lambda a créé un segment représentant l'invocation du gestionnaire Lambda, et vous avez créé des sous-segments à l'aide du SDK X-Ray sans aucune configuration supplémentaire.
- With OpenTelemetry SDK
-
Le code de fonction Lambda suivant (sans instrumentation) effectue un ListBuckets appel Amazon S3 et une requête HTTP sortante.
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) }
Pour instrumenter manuellement votre gestionnaire Lambda et le client Amazon S3, procédez comme suit :
-
Dans main (), instanciez a TracerProvider (tp) et enregistrez-le en tant que fournisseur de traceurs global. TracerProvider Il est recommandé de le configurer avec :
-
Processeur Span simple avec un exportateur de span UDP X-Ray pour envoyer des traces au point de terminaison UDP X-Ray de Lambda
-
Ressource avec service.name défini sur le nom de la fonction Lambda
-
-
Modifiez l'utilisation
lambda.Start(lambdaHandler)
delambda.Start(otellambda.InstrumentHandler(lambdaHandler, xrayconfig.WithRecommendedOptions(tp)...))
. -
Instrumentez le client Amazon S3 à l'aide de l'instrumentation du OpenTemetry AWS SDK en ajoutant un OpenTelemetry intergiciel à la configuration du client
aws-sdk-go-v2
Amazon S3. -
Instrumentez le client HTTP en utilisant OpenTelemetry la
otelhttp.NewTransport
méthode pour encapsuler lehttp.DefaultTransport
.
Le code suivant est un exemple de ce à quoi ressemblera la fonction Lambda après les modifications. Vous pouvez créer manuellement des travées personnalisées supplémentaires en plus des travées fournies automatiquement.
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)...)) }
-
Lorsque vous appelez Lambda, vous verrez la trace suivante dans Trace Map
CloudWatch la console :
