Migrate from the Trace exporter to the OTLP endpoint

This document describes how to migrate an application that is instrumented with OpenTelemetry and relies on Google Cloud exporters, to use OpenTelemetry's OTLP exporters. Both configurations send telemetry to your Google Cloud project. The steps in this document are for the in-process export performed by the OpenTelemetry SDK.

This document describes how to export trace data when you use manual instrumentation. This guidance, which is provided for Java, Go and Python, doesn't apply to sending log or metric data to your Google Cloud project.

Why you should migrate

The OpenTelemetry SDKs generate log, metric, and trace data in the OTLP format. When an application exports that data to a Google Cloud project by using a Google Cloud exporter, that exporter performs the following steps:

  1. Transforms the recorded data from OTLP-format into a proprietary format defined by the Cloud Logging API, the Cloud Monitoring API, or the Cloud Trace API.
  2. Sends the transformed data to the appropriate API, which is then stored in your Google Cloud project.

For trace data, we recommend that you migrate your application to use the Telemetry (OTLP) API to export data, because this export doesn't require a data transformation. Data transformation might cause loss of some data. For example, the proprietary format might have lower limits for certain fields, or some OTLP fields might not map to a field in the proprietary format.

Before you begin

Before you migrate your application to send trace data to the OTLP endpoint, enable the Telemetry API and make sure that you have been granted the required Identity and Access Management (IAM) roles. You might also need to grant IAM roles to a service account.

Enable billing and the Telemetry API

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Telemetry, Cloud Logging, Cloud Monitoring, and Cloud Trace APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the Telemetry, Cloud Logging, Cloud Monitoring, and Cloud Trace APIs.

    Enable the APIs

Configure permissions

Migration guide for manual instrumentation

This section describes how to modify your application so that it sends your trace data to your Google Cloud project by using the Telemetry API. You can't send metric or log data to this endpoint.

Add dependencies

The first step is to add dependencies for OpenTelemetry's OTLP trace exporter in your application. Select the dependency versions appropriate for your application and build system.

Java

For a Java application using the Gradle build system:

// build.gradle
implementation("io.opentelemetry:opentelemetry-exporter-otlp:1.47.0")

Go

For a Golang application ensure the go.mod file has the following dependencies:

// go.mod file
require(
  // OTLP exporter that uses grpc protocol for export
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0
  // Alternatively, for export using http/protobuf protocol, use:
  go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0
)

Python

For a Python application install the following dependencies or update the requirements.txt file:

# Requirements.txt - use appropriate versions
#
# OTLP exporter that uses grcp protocol for export
opentelemetry-exporter-otlp-proto-grpc==1.30.0
grpcio==1.70.0
# Alternatively, for export using http/protobuf protocol, use:
opentelemetry-exporter-otlp-proto-http==1.30.0

Replace the use of Google Cloud exporters with OTLP exporters

Update your application code such that the OpenTelemetry SDK is configured to use the OpenTelemetry OTLP exporters instead of Google Cloud trace exporter. The required changes are language-specific.

Java

import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;

// Initialize OpenTelemetry SDK with OTLP exporters
public static OpenTelemetry initOpenTelemetry() {
    // Initialize the OTLP gRPC exporter
    SpanExporter otlpGrpcSpanExporter =
        OtlpGrpcSpanExporter.builder()
            .setTimeout(2, TimeUnit.SECONDS)
            .build();

    // Initialize OpenTelemetry tracer provider
    SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
        .setResource(resource)
        .setSampler(Sampler.traceIdRatioBased(0.02))
        .addSpanProcessor(
            BatchSpanProcessor.builder(otlpGrpcSpanExporter)
                .setScheduleDelay(100, TimeUnit.MILLISECONDS)
                .build());

    // Configure OpenTelemetry SDK instacne to use the tracer provider
    // configured with OTLP exporter
    OpenTelemetrySdk openTelemetrySdk =
        OpenTelemetrySdk.builder()
            .setTracerProvider(tracerProvider)
            .build();
}

Go

import (
    "context"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    // other dependencies
)

// Initializes OpenTelemetry with OTLP exporters
func init() {
    ctx := context.Background()

    // Initialize the OTLP gRPC exporter
    exporter, err := otlptracegrpc.New(ctx)
    if err != nil {
        panic(err)
    }
    // initialize OpenTelemetry tracer provdier
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithSampler(sdktrace.TraceIDRatioBased(0.02)),
        sdktrace.WithBatcher(exporter)
    )

    // configure OpenTelemetry SDK instance to use the tracer provider
    // configured with OTLP exporter
    otel.SetTracerProvider(tp)
}

Python

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
    OTLPSpanExporter,
)
from opentelemetry.sdk.resources import SERVICE_NAME, Resource

# Initialize OpenTelemetry with OTLP exporters
def init():
    # Initialize the OTLP gRPC or http exporter
    otlp_grpc_exporter = OTLPSpanExporter()

    # Initialize OpenTelemetry TracerProvider
    trace_provider = TracerProvider(resource=resource).add_span_processor(
    BatchSpanProcessor(otlp_grpc_exporter)
    )

    # Configure OpenTelemetry tracing API with the initialized tracer provider
    trace.set_tracer_provider(trace_provider)

Configure authentication

With the previous changes to the OpenTelemetry SDK configuration, your application is configured to export traces using the OpenTelemetry OTLP exporters using either gRPC or HTTP. Next, you need to configure the exporters to send those traces to your Google Cloud project.

To configure authentication, do the following:

  1. Configure authentication headers for the export calls.
  2. Configure the required OpenTelemetry resource attributes and OTLP headers.
  3. Configure the exporter endpoint.

This section details each of these steps.

Configure authentication headers for the export calls

To configure the exporter with your Google Cloud Application Default Credentials (ADC), add a language-specific Google Auth Library.

Java

To authenticate to Google Cloud Observability, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

// build.gradle
// Google Auth Library
implementation("com.google.auth:google-auth-library-oauth2-http:1.32.1")

Go

To authenticate to Google Cloud Observability, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

// go.mod file
require (
    // When using gRPC based OTLP exporter, auth is built-in
    google.golang.org/grpc v1.70.0
    // When using http based OTLP exported, use explicit auth library
    golang.org/x/oauth2 v0.26.0
)

Python

To authenticate to Google Cloud Observability, set up Application Default Credentials. For more information, see Set up authentication for a local development environment.

# requirements.txt
# Google Auth Library
google-auth==2.38.0

Next, update the application code that constructs the OTLP span exporter so that it adds the authorization tokens retrieved from the library to the headers. This step is language-specific, but the implementation is similar for all languages.

Java

We recommend that you use the Google Cloud Authentication Extension when you are using the OpenTelemetry SDK Autoconfigure module. For a complete example that uses this extension, see OTLP Trace with Google Auth Example.

import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.opentelemetry.sdk.trace.export.SpanExporter;
import io.opentelemetry.sdk.trace.samplers.Sampler;

import com.google.auth.oauth2.GoogleCredentials;

// Initialize OpenTelemetry SDK with OTLP exporters
public static OpenTelemetry initOpenTelemetry() {
    // Retrieve and store application-default credentials
    GoogleCredentials credentials;
    try {
       credentials = GoogleCredentials.getApplicationDefault();
    } catch (IOException e) {
      // Handle authentication error
      throw new RuntimeException(e);
    }

    // Update gRPC span exporter to add the authorization headers
    // If you are using the Autoconfigure module, we recommend using
    // Google Cloud Authentication Extension.
    // See https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/gcp-auth-extension
    SpanExporter otlpGrpcSpanExporter =
        OtlpGrpcSpanExporter.builder()
            .setHeaders(
                () -> {
                  Map<String, List<String>> gcpHeaders;
                  try {
                    credentials.refreshIfExpired();
                    gcpHeaders = credentials.getRequestMetadata();
                  } catch (IOException e) {
                    // Handle authentication error
                    throw new RuntimeException(e);
                  }
                  Map<String, String> flattenedHeaders =
                      gcpHeaders.entrySet().stream()
                          .collect(
                              Collectors.toMap(
                                  Map.Entry::getKey,
                                  entry ->
                                      entry.getValue().stream()
                                          .filter(Objects::nonNull)
                                          .filter(s -> !s.isEmpty())
                                          .collect(Collectors.joining(",")),
                                  (v1, v2) -> v2));
                  return flattenedHeaders;
                })
            .setTimeout(2, TimeUnit.SECONDS)
            .build();

  // Other OpenTelemetry configuration remains unaffected
}

Go

import (
    "context"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/oauth"
)

// Initializes OpenTelemetry with OTLP exporters
func init() {
    ctx := context.Background()

    // Retrieve and store Google application-default credentials
    creds, err := oauth.NewApplicationDefault(ctx)
    if err != nil {
        panic(err)
    }

    // Update the previously created OTLP gRPC span exporter to
    // add authorization headers
    exporter, err := otlptracegrpc.New(
        ctx,
        otlptracegrpc.WithDialOption(grpc.WithPerRPCCredentials(creds))
    )

    // Other OpenTelemetry configuration remains unaffected.
}

Python

from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
    OTLPSpanExporter,
)
from opentelemetry.sdk.resources import SERVICE_NAME, Resource

import google.auth
import google.auth.transport.grpc
import google.auth.transport.requests
import grpc
from google.auth.transport.grpc import AuthMetadataPlugin

# Initialize OpenTelemetry with OTLP exporters
def init():
    # Retrieve and store Google application-default credentials
    credentials, project_id = google.auth.default()
    # Request used to refresh credentials upon expiry
    request = google.auth.transport.requests.Request()

    # Supply the request and credentials to AuthMetadataPlugin
    # AuthMeatadataPlugin inserts credentials into each request
    auth_metadata_plugin = AuthMetadataPlugin(
        credentials=credentials, request=request
    )

    # Initialize gRPC channel credentials using the AuthMetadataPlugin
    channel_creds = grpc.composite_channel_credentials(
        grpc.ssl_channel_credentials(),
        grpc.metadata_call_credentials(auth_metadata_plugin),
    )

    # Update the previously created OTLP gRPC span exporter to add authorization
    # credentials
    otlp_grpc_exporter = OTLPSpanExporter(credentials=channel_creds)

    # Other OpenTelementry configuration remains unaffected

Configure the required OpenTelemetry resource attributes

Add to the OTEL_RESOURCE_ATTRIBUTES environment variable the key-value pair that specifies your project. For the key, use gcp.project_id. For the value, use the ID of your Google Cloud project.

Example:

export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=PROJECT_ID"

For more information about OpenTelemetry environment variables, see General SDK Configuration.

Set the quota project ID

The quota project is the Google Cloud project that tracks your usage of API requests. Because the Telemetry API is a client-based API, how you authenticate determines whether the quota project is automatically identified. For example, you don't need to specify the quota project when you use a service account for authentication. However, you do need to specify the quota project when user credentials are used for authentication.

You can set a quota project by using an environment variable. To determine which environment variable to set for your programming language, see Set the quota project using an environment variable.

For example, for Go, you can set the quota project as follows:

export GOOGLE_CLOUD_QUOTA_PROJECT="QUOTA_PROJECT_ID"

For information about how to resolve authentication errors, see User credentials not working.

Configure the exporter endpoint

Set the value of the OTEL_EXPORTER_OTLP_ENDPOINT environment variable to the OTLP endpoint for Google Cloud.

Example:

export OTEL_EXPORTER_OTLP_ENDPOINT=https://telemetry.googleapis.com

For more information about OpenTelemetry environment variables, see General SDK Configuration.