Trace-Erfassung mit OpenTelemetry einrichten

In diesem Dokument erfahren Sie, wie Sie clientseitiges und End-to-End-Tracing mit OpenTelemetry einrichten. Sie müssen das clientseitige Tracing einrichten, bevor Sie das End-to-End-Tracing aktivieren können. Weitere Informationen finden Sie unter Übersicht zur Trace-Erfassung.

Hinweise

  • Damit das von Ihrer Anwendung verwendete Dienstkonto die erforderlichen Berechtigungen zum Einrichten der Trace-Erfassung hat, bitten Sie Ihren Administrator, dem Dienstkonto die IAM-Rolle Cloud Trace-Agent (roles/cloudtrace.agent) für Ihr Projekt zuzuweisen.

  • Prüfen Sie, ob die Cloud Trace API für Ihr Projekt aktiviert ist. Weitere Informationen zum Aktivieren von APIs finden Sie unter APIs aktivieren.

Clientseitiges Tracing konfigurieren

Wenn Sie die clientseitige Aufrufabfolge konfigurieren möchten, müssen Sie Traces exportieren. Sie können Traces in einen Collector oder direkt in ein Observability-Backend exportieren. Sie können die Tracing-Funktion mit OpenTelemetry APIs konfigurieren.

Traces mit OpenTelemetry APIs in einen Collector exportieren

Wenn Sie Traces mit OpenTelemetry APIs in einen Collector exportieren möchten, konfigurieren Sie das OpenTelemetry SDK und den OTLP-Exporter:

  1. Fügen Sie Ihrer Anwendung mit dem folgenden Code die erforderlichen Abhängigkeiten hinzu:

    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. Konfigurieren Sie das OpenTelemetry-Objekt und aktivieren Sie die Tracing-Funktion.

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

Direkter Export in ein Observability-Backend mit OpenTelemetry APIs

So konfigurieren Sie Spanner-Clientbibliotheken, um Trace-Bereiche direkt in Cloud Trace oder in das Backend eines anderen Anbieters von Observability-Diensten zu exportieren:

  1. Fügen Sie Ihrer Anwendung mit dem folgenden Code die erforderlichen Abhängigkeiten hinzu:

    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. Konfigurieren Sie das OpenTelemetry-Objekt und aktivieren Sie die Tracing-Funktion.

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

End-to-End-Analyse konfigurieren

In diesem Abschnitt finden Sie eine Anleitung zum Konfigurieren der End-to-End-Analyse (Vorabversion) in Spanner-Clientbibliotheken:

  1. Fügen Sie Ihrer Anwendung mit dem folgenden Code die erforderlichen Abhängigkeiten hinzu:

    Java

    Die vorhandenen clientseitigen Abhängigkeiten für die Tracing-Funktion reichen aus, um die End-to-End-Tracing-Funktion zu konfigurieren. Es sind keine zusätzlichen Abhängigkeiten erforderlich.

    Go

    Zusätzlich zu den Abhängigkeiten, die Sie für die clientseitige Analyse benötigen, ist auch die folgende Abhängigkeit erforderlich:

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

    Node.js

    Die vorhandenen clientseitigen Abhängigkeiten für die Tracing-Funktion reichen aus, um die End-to-End-Tracing-Funktion zu konfigurieren. Es sind keine zusätzlichen Abhängigkeiten erforderlich.

    Python

    Die vorhandenen clientseitigen Abhängigkeiten für die Tracing-Funktion reichen aus, um die End-to-End-Tracing-Funktion zu konfigurieren. Es sind keine zusätzlichen Abhängigkeiten erforderlich.

  2. Aktivieren Sie das End-to-End-Tracing.

    Java

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

    Go

    Aktivieren Sie die Option EnableEndToEndTracing in der Clientkonfiguration.

    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. Legen Sie die Weitergabe des Trace-Kontexts in OpenTelemetry fest.

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

End-to-End-Tracing-Attribute

End-to-End-Traces können die folgenden Informationen enthalten:

Attributname Beschreibung
service.name Der Attributwert ist immer spanner_api_frontend.
cloud.region Die Google Cloud -Cloud-Region des Spanner API-Front-Ends, das Ihre Anwendungsanfrage verarbeitet.
gcp.spanner.query.fingerprint Der Attributwert ist der Abfragefingerabdruck. Weitere Informationen zur Fehlerbehebung bei dieser Abfrage finden Sie in der Spalte TEXT_FINGERPRINT in den Abfragestatistiktabellen.
gcp.spanner.participants.count Die Anzahl der an der Transaktion beteiligten Teilnehmer. Weitere Informationen finden Sie unter Lebensdauer von Lese- und Schreibvorgängen in Cloud Spanner.

Beispiel-Trace

In einem End-to-End-Trace können Sie die folgenden Details sehen:

  • Die Latenz zwischen Ihrer Anwendung und Spanner. Sie können die Netzwerklatenz berechnen, um festzustellen, ob es Netzwerkprobleme gibt.
  • Die Cloud-Region des Spanner API-Front-Ends, von der aus Ihre Anwendungsanfragen gesendet werden. So können Sie nach regionenübergreifenden Aufrufen zwischen Ihrer Anwendung und Spanner suchen.

Im folgenden Beispiel wird Ihre Anwendungsanfrage vom Spanner API-Frontend in der Region us-west1 verarbeitet und die Netzwerklatenz beträgt 8,542 ms (55,47 ms – 46,928 ms).

End-to-End-Trace ansehen

Nächste Schritte