Configura la recopilación de registros de seguimiento con OpenTelemetry

En este documento, se muestra cómo configurar el seguimiento del cliente y de extremo a extremo con OpenTelemetry. Antes de habilitar el seguimiento de extremo a extremo, debes configurar el seguimiento del cliente. Para obtener más información, consulta Trace collection overview.

Antes de comenzar

  • Para asegurarte de que la cuenta de servicio que usa tu aplicación tenga los permisos necesarios para configurar la recopilación de seguimientos, pídele a tu administrador que le otorgue los siguientes roles de IAM en tu proyecto:

  • Verifica que la API de Cloud Trace y Telemetry estén habilitadas en tu proyecto. Para obtener más información sobre cómo habilitar las APIs, consulta Habilita lasAPIs.

Configura el seguimiento del cliente

Para exportar seguimientos con el protocolo OpenTelemetry (OTLP), configura tu aplicación. Puedes enviar datos a un recopilador de OpenTelemetry o directamente a Cloud Trace a través de la API de Telemetry. Ambos métodos usan las mismas dependencias y configuración. Solo difieren en el extremo de OTLP que usa el exportador.

Exporta seguimientos con el protocolo OpenTelemetry

Para exportar seguimientos con el protocolo OpenTelemetry, configura el SDK de OpenTelemetry y el exportador de OTLP:

  1. Agrega las dependencias necesarias a tu aplicación con el siguiente código:

    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. Configura el objeto OpenTelemetry y habilita el seguimiento.

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

Configura el seguimiento de extremo a extremo

En esta sección, se proporcionan instrucciones para configurar el seguimiento de extremo a extremo en las bibliotecas cliente de Spanner:

  1. Agrega las dependencias necesarias a tu aplicación con el siguiente código:

    Java

    Las dependencias de seguimiento del cliente existentes son suficientes para configurar el seguimiento de extremo a extremo. No necesitas dependencias adicionales.

    Go

    Además de las dependencias que necesitas para el seguimiento del cliente, también necesitas la siguiente dependencia:

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

    Node.js

    Las dependencias de seguimiento del cliente existentes son suficientes para configurar el seguimiento de extremo a extremo. No necesitas dependencias adicionales.

    Python

    Las dependencias de seguimiento del cliente existentes son suficientes para configurar el seguimiento de extremo a extremo. No necesitas dependencias adicionales.

  2. Habilita el seguimiento de extremo a extremo.

    Java

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

    Go

    Usa la opción EnableEndToEndTracing en la configuración del cliente para habilitarlo.

    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={
    "tracer_provider": tracer_provider,
    "enable_end_to_end_tracing": True,
    }
    spanner = spanner.Client(project_id, observability_options=observability_options)

  3. Establece la propagación del contexto de seguimiento en 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())

Atributos de seguimiento de extremo a extremo

Los seguimientos de extremo a extremo pueden incluir la siguiente información:

Nombre del atributo Descripción
service.name El valor del atributo siempre es spanner_api_frontend.
cloud.region La Google Cloud región de Cloud del frontend de la API de Spanner que entrega la solicitud de tu aplicación.
gcp.spanner.server.query.fingerprint El valor del atributo es la huella digital de la consulta. Para depurar más esta consulta, consulta la TEXT_FINGERPRINT columna en las tablas de estadísticas de consultas.
gcp.spanner.server.paxos.participantcount Es la cantidad de participantes involucrados en la transacción. Para obtener más información, consulta Ciclo de vida de las operaciones de lectura y escritura de Spanner.
gcp.spanner.isolation_level El valor del atributo es el nivel de aislamiento de la transacción. Los valores posibles son SERIALIZABLE y REPEATABLE_READ. Para obtener más información, consulta Descripción general de los niveles de aislamiento.

Seguimiento de muestra

Un seguimiento de extremo a extremo te permite ver los siguientes detalles:

  • La latencia entre tu aplicación y Spanner. Puedes calcular la latencia de la red para ver si tienes algún problema de red.
  • La región de Cloud del frontend de la API de Spanner desde la que se entregan las solicitudes de tu aplicación. Puedes usar esto para verificar las llamadas entre regiones entre tu aplicación y Spanner.

En el siguiente ejemplo, el frontend de la API de Spanner entrega la solicitud de tu aplicación en la región us-west1 y la latencia de la red es de 8.542 ms (55.47 ms - 46.928 ms).

Ver un registro de extremo a extremo

¿Qué sigue?