Configurer la collecte de traces à l'aide d'OpenTelemetry

Ce document vous explique comment configurer le traçage de bout en bout et côté client à l'aide d'OpenTelemetry. Vous devez configurer le traçage côté client avant de pouvoir activer le traçage de bout en bout. Pour en savoir plus, consultez la présentation de la collecte des traces.

Avant de commencer

  • Pour vous assurer que le compte de service utilisé par votre application dispose des autorisations nécessaires pour configurer la collecte de traces, demandez à votre administrateur d'accorder au compte de service utilisé par votre application le rôle IAM Agent Cloud Trace (roles/cloudtrace.agent) sur votre projet.

  • Vérifiez que l'API Cloud Trace est activée pour votre projet. Pour en savoir plus sur l'activation des API, consultez Activer des API.

Configurer le traçage côté client

Pour configurer le traçage côté client, vous devez exporter les traces. Vous pouvez exporter des traces vers un collecteur ou directement vers un backend d'observabilité. Vous pouvez configurer le traçage à l'aide des API OpenTelemetry.

Exporter des traces vers un collecteur à l'aide des API OpenTelemetry

Pour exporter des traces vers un collecteur à l'aide des API OpenTelemetry, configurez le SDK OpenTelemetry et l'exportateur OLTP :

  1. Ajoutez les dépendances nécessaires à votre application à l'aide du code suivant :

    Java

    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-spanner</artifactId>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-sdk</artifactId>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-sdk-trace</artifactId>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-exporter-otlp</artifactId>
    </dependency>

    Go

    go.opentelemetry.io/otel v1.28.0
    go.opentelemetry.io/otel/sdk v1.28.0
    go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0

    Node.js

    "@opentelemetry/exporter-trace-otlp-grpc": "^0.57.0",
    "@opentelemetry/sdk-trace-base": "^1.26.0",
    "@opentelemetry/sdk-trace-node": "^1.26.0",

    Python

    pip install opentelemetry-api opentelemetry-sdk
    pip install opentelemetry-exporter-otlp

  2. Configurez l'objet OpenTelemetry et activez le traçage.

    Java

    Resource resource = Resource
        .getDefault().merge(Resource.builder().put("service.name", "My App").build());
    
    OtlpGrpcSpanExporter otlpGrpcSpanExporter =
        OtlpGrpcSpanExporter
            .builder()
            .setEndpoint(otlpEndpoint) // Replace with your OTLP endpoint
            .build();
    
    // Using a batch span processor
    // You can use `.setScheduleDelay()`, `.setExporterTimeout()`,
    // `.setMaxQueueSize`(), and `.setMaxExportBatchSize()` to further customize.
    BatchSpanProcessor otlpGrpcSpanProcessor =
        BatchSpanProcessor.builder(otlpGrpcSpanExporter).build();
    
    // Create a new tracer provider
    sdkTracerProvider = SdkTracerProvider.builder()
        // Use Otlp exporter or any other exporter of your choice.
        .addSpanProcessor(otlpGrpcSpanProcessor)
        .setResource(resource)
        .setSampler(Sampler.traceIdRatioBased(0.1))
        .build();
    
    // Export to a collector that is expecting OTLP using gRPC.
    OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
        .setTracerProvider(sdkTracerProvider).build();
    
    // Enable OpenTelemetry traces before Injecting OpenTelemetry
    SpannerOptions.enableOpenTelemetryTraces();
    
    // Inject OpenTelemetry object via Spanner options or register as GlobalOpenTelemetry.
    SpannerOptions options = SpannerOptions.newBuilder()
        .setOpenTelemetry(openTelemetry)
        .build();
    Spanner spanner = options.getService();

    Go

    
    // Ensure that your Go runtime version is supported by the OpenTelemetry-Go
    // compatibility policy before enabling OpenTelemetry instrumentation.
    
    // Enable OpenTelemetry traces by setting environment variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING
    // to the case-insensitive value "opentelemetry" before loading the client library.
    
    ctx := context.Background()
    
    // Create a new resource to uniquely identify the application
    res, err := resource.Merge(resource.Default(),
    	resource.NewWithAttributes(semconv.SchemaURL,
    		semconv.ServiceName("My App"),
    		semconv.ServiceVersion("0.1.0"),
    	))
    if err != nil {
    	log.Fatal(err)
    }
    
    // Create a new OTLP exporter.
    defaultOtlpEndpoint := "http://localhost:4317" // Replace with the endpoint on which OTLP collector is running
    traceExporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithEndpoint(defaultOtlpEndpoint))
    if err != nil {
    	log.Fatal(err)
    }
    
    // Create a new tracer provider
    tracerProvider := sdktrace.NewTracerProvider(
    	sdktrace.WithResource(res),
    	sdktrace.WithBatcher(traceExporter),
    	sdktrace.WithSampler(sdktrace.TraceIDRatioBased(0.1)),
    )
    
    // Register tracer provider as global
    otel.SetTracerProvider(tracerProvider)

    Node.js

    const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
    const {
      OTLPTraceExporter,
    } = require('@opentelemetry/exporter-trace-otlp-grpc');
    const {
      BatchSpanProcessor,
      TraceIdRatioBasedSampler,
    } = require('@opentelemetry/sdk-trace-base');
    const {Resource} = require('@opentelemetry/resources');
    const {Spanner} = require('@google-cloud/spanner');
    
    // Define a Resource with service metadata
    const resource = new Resource({
      'service.name': 'my-service',
      'service.version': '1.0.0',
    });
    
    // Create an OTLP gRPC trace exporter
    const traceExporter = new OTLPTraceExporter({
      url: 'http://localhost:4317', // Default OTLP gRPC endpoint
    });
    
    // Create a provider with a custom sampler
    const provider = new NodeTracerProvider({
      sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
      resource,
      spanProcessors: [new BatchSpanProcessor(traceExporter)],
    });
    
    // Uncomment following line to register tracerProvider globally or pass it in Spanner object
    // provider.register();
    
    // Create the Cloud Spanner Client.
    const spanner = new Spanner({
      projectId: projectId,
      observabilityOptions: {
        tracerProvider: provider,
        enableExtendedTracing: true,
        enableEndToEndTracing: true,
      },
    });
    

    Python

    # Setup OpenTelemetry, trace and OTLP exporter.
    tracer_provider = TracerProvider(sampler=ALWAYS_ON)
    otlp_exporter = OTLPSpanExporter(endpoint="http://localhost:4317")
    tracer_provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
    
    # Setup the Cloud Spanner Client.
    spanner_client = spanner.Client(
        project_id,
        observability_options=dict(tracer_provider=tracer_provider, enable_extended_tracing=True, enable_end_to_end_tracing=True),
    )

Exporter directement vers un backend d'observabilité à l'aide des API OpenTelemetry

Pour configurer les bibliothèques clientes Spanner afin d'exporter directement les étendues de trace vers Cloud Trace ou un autre backend de fournisseur de services d'observabilité, procédez comme suit :

  1. Ajoutez les dépendances nécessaires à votre application à l'aide du code suivant :

    Java

    <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-common</artifactId>
    </dependency>
    <dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-trace</artifactId>
    </dependency>
    <dependency>
    <groupId>com.google.cloud.opentelemetry</groupId>
    <artifactId>exporter-trace</artifactId>
    <version>0.30.0</version>
    </dependency>

    Go

    go.opentelemetry.io/otel v1.28.0
    go.opentelemetry.io/otel/sdk v1.28.0
    github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.24.1

    Node.js

    "@google-cloud/opentelemetry-cloud-trace-exporter": "^2.4.1",
    "@opentelemetry/sdk-trace-base": "^1.26.0",
    "@opentelemetry/sdk-trace-node": "^1.26.0",

    Python

    pip install opentelemetry-api opentelemetry-sdk
    pip install opentelemetry-exporter-gcp-trace

  2. Configurez l'objet OpenTelemetry et activez le traçage.

    Java

    Resource resource = Resource
        .getDefault().merge(Resource.builder().put("service.name", "My App").build());
    
    SpanExporter traceExporter = TraceExporter.createWithConfiguration(
        TraceConfiguration.builder().setProjectId(projectId).build()
    );
    
    // Using a batch span processor
    // You can use `.setScheduleDelay()`, `.setExporterTimeout()`,
    // `.setMaxQueueSize`(), and `.setMaxExportBatchSize()` to further customize.
    BatchSpanProcessor otlpGrpcSpanProcessor =
        BatchSpanProcessor.builder(traceExporter).build();
    
    // Create a new tracer provider
    sdkTracerProvider = SdkTracerProvider.builder()
        // Use Otlp exporter or any other exporter of your choice.
        .addSpanProcessor(otlpGrpcSpanProcessor)
        .setResource(resource)
        .setSampler(Sampler.traceIdRatioBased(0.1))
        .build();
    
    // Export to a collector that is expecting OTLP using gRPC.
    OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
        .setTracerProvider(sdkTracerProvider).build();
    
    // Enable OpenTelemetry traces before Injecting OpenTelemetry
    SpannerOptions.enableOpenTelemetryTraces();
    
    // Inject OpenTelemetry object via Spanner options or register it as global object.
    // To register as the global OpenTelemetry object,
    // use "OpenTelemetrySdk.builder()....buildAndRegisterGlobal()".
    SpannerOptions options = SpannerOptions.newBuilder()
        .setOpenTelemetry(openTelemetry)
        .build();
    Spanner spanner = options.getService();

    Go

    
    // Ensure that your Go runtime version is supported by the OpenTelemetry-Go
    // compatibility policy before enabling OpenTelemetry instrumentation.
    
    // Enable OpenTelemetry traces by setting environment variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING
    // to the case-insensitive value "opentelemetry" before loading the client library.
    
    // Create a new resource to uniquely identify the application
    res, err := resource.Merge(resource.Default(),
    	resource.NewWithAttributes(semconv.SchemaURL,
    		semconv.ServiceName("My App"),
    		semconv.ServiceVersion("0.1.0"),
    	))
    if err != nil {
    	log.Fatal(err)
    }
    
    // Create a new cloud trace exporter
    exporter, err := traceExporter.New(traceExporter.WithProjectID(projectID))
    if err != nil {
    	log.Fatal(err)
    }
    
    // Create a new tracer provider
    tracerProvider := sdktrace.NewTracerProvider(
    	sdktrace.WithResource(res),
    	sdktrace.WithBatcher(exporter),
    	sdktrace.WithSampler(sdktrace.TraceIDRatioBased(0.1)),
    )
    
    // Register tracer provider as global
    otel.SetTracerProvider(tracerProvider)

    Node.js

    
    const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
    const {
      TraceExporter,
    } = require('@google-cloud/opentelemetry-cloud-trace-exporter');
    const {
      BatchSpanProcessor,
      TraceIdRatioBasedSampler,
    } = require('@opentelemetry/sdk-trace-base');
    const {Spanner} = require('@google-cloud/spanner');
    
    const traceExporter = new TraceExporter();
    
    // Create a provider with a custom sampler
    const provider = new NodeTracerProvider({
      sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
      spanProcessors: [new BatchSpanProcessor(traceExporter)],
    });
    
    // Uncomment following line to register tracerProvider globally or pass it in Spanner object
    // provider.register();
    
    // Set global propagator to propogate the trace context for end to end tracing.
    const {propagation} = require('@opentelemetry/api');
    const {W3CTraceContextPropagator} = require('@opentelemetry/core');
    propagation.setGlobalPropagator(new W3CTraceContextPropagator());
    
    const spanner = new Spanner({
      projectId: projectId,
      observabilityOptions: {
        tracerProvider: provider,
        // Enable extended tracing to allow your SQL statements to be annotated.
        enableExtendedTracing: true,
        // Enable end to end tracing.
        enableEndToEndTracing: true,
      },
    });
    

    Python

    # Setup OpenTelemetry, trace and Cloud Trace exporter.
    tracer_provider = TracerProvider(sampler=ALWAYS_ON)
    trace_exporter = CloudTraceSpanExporter(project_id=project_id)
    tracer_provider.add_span_processor(BatchSpanProcessor(trace_exporter))
    
    # Setup the Cloud Spanner Client.
    spanner_client = spanner.Client(
        project_id,
        observability_options=dict(tracer_provider=tracer_provider, enable_extended_tracing=True, enable_end_to_end_tracing=True),
    )
    

Configurer le traçage de bout en bout

Cette section fournit des instructions pour configurer le traçage de bout en bout sur les bibliothèques clientes Spanner :

  1. Ajoutez les dépendances nécessaires à votre application à l'aide du code suivant :

    Java

    Les dépendances de traçage côté client existantes suffisent pour configurer le traçage de bout en bout. Vous n'avez besoin d'aucune dépendance supplémentaire.

    Go

    En plus des dépendances dont vous avez besoin pour le traçage côté client, vous avez également besoin de la dépendance suivante :

    go.opentelemetry.io/otel/propagation v1.28.0

    Node.js

    Les dépendances de traçage côté client existantes suffisent pour configurer le traçage de bout en bout. Vous n'avez besoin d'aucune dépendance supplémentaire.

    Python

    Les dépendances de traçage côté client existantes suffisent pour configurer le traçage de bout en bout. Vous n'avez besoin d'aucune dépendance supplémentaire.

  2. Activez le traçage de bout en bout.

    Java

    SpannerOptions options = SpannerOptions.newBuilder()
      .setOpenTelemetry(openTelemetry)
      .setEnableEndToEndTracing(/* enableEndtoEndTracing= */ true)
      .build();

    Go

    Utilisez l'option EnableEndToEndTracing dans la configuration du client pour l'activer.

    client, _ := spanner.NewClientWithConfig(ctx, "projects/test-project/instances/test-instance/databases/test-db", spanner.ClientConfig{
    SessionPoolConfig: spanner.DefaultSessionPoolConfig,
    EnableEndToEndTracing:      true,
    }, clientOptions...)

    Node.js

    const spanner = new Spanner({
    projectId: projectId,
    observabilityOptions: {
    tracerProvider: openTelemetryTracerProvider,
    enableEndToEndTracing: true,
    }
    })

    Python

    observability_options = dict(
    tracer_provider=tracer_provider,
    enable_end_to_end_tracing=True,
    )
    spanner = spanner.NewClient(project_id, observability_options=observability_options)

  3. Définissez la propagation du contexte de trace dans OpenTelemetry.

    Java

    OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
      .setTracerProvider(sdkTracerProvider)
      .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
      .buildAndRegisterGlobal();

    Go

    // Register the TraceContext propagator globally.
    otel.SetTextMapPropagator(propagation.TraceContext{})

    Node.js

    const {propagation} = require('@opentelemetry/api');
    const {W3CTraceContextPropagator} = require('@opentelemetry/core');
    propagation.setGlobalPropagator(new W3CTraceContextPropagator());

    Python

    from opentelemetry.propagate import set_global_textmap
    from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
    set_global_textmap(TraceContextTextMapPropagator())

Attributs de traçage de bout en bout

Les traces de bout en bout peuvent inclure les informations suivantes :

Nom de l'attribut Description
service.name La valeur de l'attribut est toujours spanner_api_frontend.
cloud.region Région cloud Google Cloud de l'interface de l'API Spanner qui traite la requête de votre application.
gcp.spanner.server.query.fingerprint La valeur de l'attribut correspond à l'empreinte de la requête. Pour déboguer davantage cette requête, consultez la colonne TEXT_FINGERPRINT dans les tables de statistiques sur les requêtes.
gcp.spanner.server.paxos.participantcount Nombre de participants impliqués dans la transaction. Pour en savoir plus, consultez Déroulement des opérations de lecture et d'écriture Spanner.

Exemple de trace

Une trace de bout en bout vous permet d'afficher les informations suivantes :

  • Latence entre votre application et Spanner. Vous pouvez calculer la latence du réseau pour vérifier si vous rencontrez des problèmes de réseau.
  • Région Cloud de l'interface de l'API Spanner à partir de laquelle les requêtes de votre application sont traitées. Vous pouvez l'utiliser pour vérifier les appels interrégionaux entre votre application et Spanner.

Dans l'exemple suivant, la requête de votre application est traitée par le frontend de l'API Spanner dans la région us-west1. La latence réseau est de 8,542 ms (55,47 ms - 46,928 ms).

Affichez une trace de bout en bout.

Étapes suivantes