This guide provides instructions on how to migrate from the custom exporters in this repository to the standard OpenTelemetry OTLP exporters.
Google Cloud supports native OTLP (OpenTelemetry Protocol) ingestion for Cloud Trace, Cloud Monitoring, and Cloud Logging via the Telemetry API. This allows you to use standard OpenTelemetry OTLP exporters for sending telemetry data to Google Cloud.
All exporters in this repository (opentelemetry-exporter-gcp-trace, opentelemetry-exporter-gcp-monitoring, and opentelemetry-exporter-gcp-logging) are deprecated. Please migrate to standard OTLP exporters using standard OpenTelemetry libraries.
When migrating to OTLP exporters, installing the GCP Resource Detector package (opentelemetry-resourcedetector-gcp) automatically populates Google Cloud resource attributes (such as gcp.project_id, cloud.account.id, host.id, k8s.pod.name, etc.) for OpenTelemetry SDK providers (TracerProvider, MeterProvider, LoggerProvider).
pip install opentelemetry-resourcedetector-gcp- Manual SDK Setup (In Code): When manually setting up the SDK in Python (e.g., instantiating
TracerProvider(),MeterProvider(), orLoggerProvider()), the GCP resource detector is automatically discovered and applied simply by installingopentelemetry-resourcedetector-gcp. No additional code changes or environment variables are required. - Autoconfiguration / Zero-Code Instrumentation: When using OpenTelemetry autoconfiguration (
opentelemetry-sdk-extension-autoconfigureoropentelemetry-instrument), enable the GCP resource detector via theOTEL_EXPERIMENTAL_RESOURCE_DETECTORSenvironment variable:
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="gcp"You can also specify additional resource attributes via OTEL_RESOURCE_ATTRIBUTES:
export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=your-project-id,service.name=my-service"To migrate from opentelemetry-exporter-gcp-trace (CloudTraceSpanExporter) to the standard OpenTelemetry OTLP exporter, follow these steps:
Install the standard OpenTelemetry OTLP exporter, GCP resource detector, and GCP authentication dependencies:
pip install opentelemetry-exporter-otlp-proto-grpc opentelemetry-resourcedetector-gcp google-auth grpcio requestsYou can configure the SDK using environment variables:
# Environment Variables
export OTEL_EXPORTER_OTLP_ENDPOINT="https://telemetry.googleapis.com"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="gcp"Or programmatically in Python using GCP authentication:
import google.auth
import google.auth.transport.grpc
import google.auth.transport.requests
import grpc
from google.auth.transport.grpc import AuthMetadataPlugin
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
OTLPSpanExporter,
)
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# Configure GCP Authentication
credentials, project_id = google.auth.default()
request = google.auth.transport.requests.Request()
auth_metadata_plugin = AuthMetadataPlugin(
credentials=credentials, request=request
)
channel_creds = grpc.composite_channel_credentials(
grpc.ssl_channel_credentials(),
grpc.metadata_call_credentials(auth_metadata_plugin),
)
trace.set_tracer_provider(TracerProvider())
otlp_exporter = OTLPSpanExporter(
endpoint="telemetry.googleapis.com",
credentials=channel_creds,
)
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(otlp_exporter)
)For more details, follow the official Google Cloud guide: Migrate from the Trace exporter to the OTLP endpoint.
CloudTraceSpanExporter Parameter |
OTLP Equivalent Property / Env Var | Notes |
|---|---|---|
project_id / OTEL_EXPORTER_GCP_TRACE_PROJECT_ID |
Resource attribute: gcp.project_id |
Set via OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=your-project-id" or detected automatically via opentelemetry-resourcedetector-gcp. |
client |
N/A | Pre-configured TraceServiceClient is replaced by OTLP gRPC/HTTP channel credentials. |
resource_regex |
Standard Resource Attributes | Standard OpenTelemetry exports resource attributes attached to the TracerProvider. Filtering/copying resource attributes via regex is not supported in OTLP. |
- Attribute Mapping & Regex Filtering (
resource_regex):CloudTraceSpanExporterallowed filtering resource attributes via regex to copy matching keys into span attributes. The standard OTLP exporter exports standard OpenTelemetry resource attributes attached to theTracerProviderdirectly. - Custom Trace Service Client (
client): You cannot pass a pre-configuredTraceServiceClientinstance directly toOTLPSpanExporter. If custom gRPC channels or metadata credentials are required, configure gRPC channel credentials programmatically as shown above.
Cloud Trace’s internal storage system uses the OpenTelemetry data model natively for organizing and storing your trace data. For complete documentation on OTLP trace mapping and limits, see Migrate from the Trace exporter to the OTLP endpoint.
- Payload Hierarchy & Resource Model:
CloudTraceSpanExporter(API v2): Sent a flat list ofSpanobjects (BatchWriteSpansRequest). Because Cloud Trace v2 spans had no native resource container, resource attributes were flattened on the client side into span labels prefixed withg.co/r/<resource_type>/<label_key>.- OTLP Exporter (Native OTel Storage Model): Uses the structured OTLP hierarchy (
ExportTraceServiceRequest→ResourceSpans→ScopeSpans→Span). Resource attributes (gcp.project_id,host.id,k8s.pod.name, etc.) are stored natively in theResourceSpansenvelope and mapped server-side.
- Attribute Keys & Semantic Conventions:
CloudTraceSpanExporter: Performed client-side remapping of OpenTelemetry HTTP keys to legacy Cloud Trace/http/label keys (e.g.,http.method→/http/method,http.status_code→/http/status_code).- OTLP Exporter: Preserves standard OpenTelemetry semantic convention keys (e.g.,
http.request.method,http.response.status_code,url.full) verbatim, stored and indexed natively in Cloud Trace.
For complete documentation on OTLP trace mapping and limits, see Migrate from the Trace exporter to the OTLP endpoint.
Migrate from OpenTelemetry Google Cloud Monitoring Exporter (CloudMonitoringMetricsExporter) to OTLP Exporter
Warning
Breaking Change Warning: Migrating from the legacy Google Cloud Monitoring exporter to the standard OTLP exporter introduces breaking changes to your metric names.
- Legacy Exporter: Ingests metrics under the
workload.googleapis.com/domain (unless a custom prefix was configured). - OTLP Exporter: Ingests metrics under the
prometheus.googleapis.com/domain by default.
Because of this domain change, your metric names in Cloud Monitoring will change. This will break any existing dashboards, alerting policies, and cause data discontinuity between your historical and new metrics.
While this migration introduces breaking changes, transitioning to the standard OTLP exporter is recommended for the following reasons:
- Standardization: Aligns your application with the industry-standard OpenTelemetry Protocol (OTLP), ensuring vendor neutrality and compatibility with the broader OpenTelemetry ecosystem.
- Google Managed Prometheus (GMP) Cost Savings: Standard OTLP metrics are ingested into Google Managed Prometheus. GMP offers a robust, scalable, and cost-effective monitoring solution (~20x cheaper ingestion cost than legacy Cloud Monitoring API ingestion).
- Future-proofing: The legacy Google Cloud Monitoring exporter is deprecated. Migrating now ensures your monitoring pipeline remains supported.
We recommend three paths for migration, depending on your operational requirements:
- Direct Migration (Recommended): Migrate fully to the OTLP exporter and update your dashboards and alerts to use the new metric names under the
prometheus.googleapis.com/domain. - Transition via Double-Writing (Alternative): Run both the legacy exporter and the OTLP exporter in parallel. This allows you to validate the new OTLP pipeline and update dashboards/alerts without any monitoring downtime, at the cost of temporary double-ingestion charges.
- Custom Metric Renaming / View Configuration (Alternative): Use OpenTelemetry SDK Views or metric processors (or OpenTelemetry Collector relabeling) to map metric names and attributes, allowing you to maintain compatibility with existing dashboards.
Follow these steps to fully transition to the standard OTLP exporter.
pip install opentelemetry-exporter-otlp-proto-grpc opentelemetry-resourcedetector-gcp google-auth grpcioexport OTEL_EXPORTER_OTLP_ENDPOINT="https://telemetry.googleapis.com"
export OTEL_METRICS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="gcp"
export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=$PROJECT_ID,location=us-central1,service.name=otlp-sample,service.instance.id=1"import google.auth
import google.auth.transport.grpc
import google.auth.transport.requests
import grpc
from google.auth.transport.grpc import AuthMetadataPlugin
from opentelemetry import metrics
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
OTLPMetricExporter,
)
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
# Configure GCP Authentication
credentials, project_id = google.auth.default()
request = google.auth.transport.requests.Request()
auth_metadata_plugin = AuthMetadataPlugin(
credentials=credentials, request=request
)
channel_creds = grpc.composite_channel_credentials(
grpc.ssl_channel_credentials(),
grpc.metadata_call_credentials(auth_metadata_plugin),
)
exporter = OTLPMetricExporter(
endpoint="telemetry.googleapis.com",
credentials=channel_creds,
)
reader = PeriodicExportingMetricReader(exporter)
provider = MeterProvider(metric_readers=[reader])
metrics.set_meter_provider(provider)To avoid monitoring gaps, run both the legacy exporter (CloudMonitoringMetricsExporter) and the standard OTLP exporter (OTLPMetricExporter) concurrently. This sends metrics to both workload.googleapis.com/ and prometheus.googleapis.com/ simultaneously, allowing you to update dashboards and alerting policies without any monitoring downtime.
Note
Cost Consideration: Double-writing metrics will double your metric ingestion volume, which will increase your Google Cloud Monitoring costs during the transition period. It also increases CPU and memory usage on your application.
import google.auth
import google.auth.transport.grpc
import google.auth.transport.requests
import grpc
from google.auth.transport.grpc import AuthMetadataPlugin
from opentelemetry import metrics
from opentelemetry.exporter.cloud_monitoring import (
CloudMonitoringMetricsExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
OTLPMetricExporter,
)
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
credentials, project_id = google.auth.default()
request = google.auth.transport.requests.Request()
auth_metadata_plugin = AuthMetadataPlugin(
credentials=credentials, request=request
)
channel_creds = grpc.composite_channel_credentials(
grpc.ssl_channel_credentials(),
grpc.metadata_call_credentials(auth_metadata_plugin),
)
# 1. Instantiate legacy exporter (writes to workload.googleapis.com/)
legacy_exporter = CloudMonitoringMetricsExporter(project_id=project_id)
# 2. Instantiate OTLP exporter (writes to prometheus.googleapis.com/)
otlp_exporter = OTLPMetricExporter(
endpoint="telemetry.googleapis.com",
credentials=channel_creds,
)
# 3. Register both readers with MeterProvider
provider = MeterProvider(
metric_readers=[
PeriodicExportingMetricReader(legacy_exporter),
PeriodicExportingMetricReader(otlp_exporter),
]
)
metrics.set_meter_provider(provider)- Verify New Metrics Ingestion: Once double-writing is deployed, verify in Metrics Explorer that new metrics are arriving under the
prometheus.googleapis.com/domain. - Update Dashboards & Alerts: Duplicate or update existing Cloud Monitoring dashboards, charts, and alerting policies to query
prometheus.googleapis.com/metric names instead ofworkload.googleapis.com/. - Cutover & Decommission: Once all dashboards and alerting rules are updated and verified against the new OTLP metric data streams, remove
CloudMonitoringMetricsExporterfrom yourMeterProviderto complete the migration and eliminate double-ingestion.
If you want to preserve legacy metric prefixes (such as workload.googleapis.com/) during migration, wrap your MetricExporter with a custom exporter wrapper that prepends the prefix to metric names before export.
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
MetricExporter,
MetricExportResult,
MetricsData,
ResourceMetrics,
ScopeMetrics,
Metric,
PeriodicExportingMetricReader,
)
class PrefixMetricExporter(MetricExporter):
"""Wraps a MetricExporter to prepend a prefix to metric names before export."""
def __init__(
self,
delegate: MetricExporter,
prefix: str = "workload.googleapis.com/",
):
super().__init__(
preferred_temporality=getattr(delegate, "_preferred_temporality", None),
preferred_aggregation=getattr(delegate, "_preferred_aggregation", None),
)
self._delegate = delegate
self._prefix = prefix
def export(
self,
metrics_data: MetricsData,
timeout_millis: float = 10_000,
**kwargs,
) -> MetricExportResult:
new_resource_metrics = []
for rm in metrics_data.resource_metrics:
new_scope_metrics = []
for sm in rm.scope_metrics:
new_metrics = []
for m in sm.metrics:
new_metrics.append(
Metric(
name=f"{self._prefix}{m.name}",
description=m.description,
unit=m.unit,
data=m.data,
)
)
new_scope_metrics.append(
ScopeMetrics(
scope=sm.scope,
metrics=new_metrics,
schema_url=sm.schema_url,
)
)
new_resource_metrics.append(
ResourceMetrics(
resource=rm.resource,
scope_metrics=new_scope_metrics,
schema_url=rm.schema_url,
)
)
new_metrics_data = MetricsData(resource_metrics=new_resource_metrics)
return self._delegate.export(
new_metrics_data, timeout_millis=timeout_millis, **kwargs
)
def shutdown(self, timeout_millis: float = 30_000, **kwargs) -> None:
self._delegate.shutdown(timeout_millis=timeout_millis, **kwargs)
def force_flush(self, timeout_millis: float = 10_000, **kwargs) -> bool:
return self._delegate.force_flush(timeout_millis=timeout_millis, **kwargs)
# Wrap the OTLPMetricExporter with the prefix exporter
exporter = PrefixMetricExporter(
delegate=otlp_exporter,
prefix="workload.googleapis.com/",
)
provider = MeterProvider(
metric_readers=[PeriodicExportingMetricReader(exporter)],
)
metrics.set_meter_provider(provider)CloudMonitoringMetricsExporter Parameter |
OTLP Equivalent Property / Env Var | Notes |
|---|---|---|
prefix (default workload.googleapis.com) |
N/A | Legacy exporter ingested under workload.googleapis.com/ (or custom prefix). OTLP exporter ingests into Google Managed Prometheus under prometheus.googleapis.com/ by default. |
add_unique_identifier |
Resource Attributes (e.g. service.instance.id, host.id) |
Legacy exporter appended a random identifier to time series. OTLP relies on standard OpenTelemetry resource attributes to distinguish instances. |
project_id |
Resource attribute: gcp.project_id |
Set via OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=your-project-id" or detected automatically via opentelemetry-resourcedetector-gcp. |
client |
N/A | Pre-configured MetricServiceClient cannot be passed directly to OTLPMetricExporter. |
The conversion logic used in CloudMonitoringMetricsExporter can be found in opentelemetry-exporter-gcp-monitoring/src/opentelemetry/exporter/cloud_monitoring/__init__.py. Standard OTLP endpoints convert OTLP metric data server-side according to the Google Cloud Telemetry API Metric Mapping specification.
Key differences include:
- Metric Domain & Name Structure:
CloudMonitoringMetricsExporter: Ingests metrics underworkload.googleapis.com/<metric.name>(or customprefix).- Telemetry API: Ingests metrics under
prometheus.googleapis.com/<metric_name>/<suffix>(e.g./counter,/gauge,/histogram,/delta,/summary). You can override the prefix toworkload.googleapis.com/orcustom.google.com/using the strategies mentioned above, but no other prefix is accepted by the API.
- Value Types (
INT64vsDOUBLE):CloudMonitoringMetricsExporter: PreservesINT64value types when integer data points are passed (TypedValue(int64_value=...)).- Telemetry API: Translates all OTLP
INT64scalar metrics toDOUBLEin Cloud Monitoring to prevent Monarch value-type schema collisions.
- Metric Kind & Temporality:
- Monotonic cumulative sums map to
CUMULATIVE(suffixed with/counter). - Monotonic delta sums map to
DELTA(suffixed with/delta). - Non-monotonic sums map to
GAUGE(suffixed with/gauge). Non-monotonic delta sums are not supported. - Histograms support both
CUMULATIVE(/histogram) andDELTA(/histogram:delta) distributions. - Summary metrics are expanded into individual time series for
_count(CUMULATIVE),_sum(CUMULATIVE), andquantile(GAUGEwith aquantilelabel).
- Monotonic cumulative sums map to
- Resource Attributes &
target_infoMetric:CloudMonitoringMetricsExporter: Maps OpenTelemetry resources to GCPMonitoredResourceon the client side usingget_monitored_resource(). Optionally appends a randomopentelemetry_idlabel whenadd_unique_identifier=True.- Telemetry API: Maps resources server-side and automatically generates a
target_infometric for each unique OpenTelemetry resource containing non-identifying resource attributes.
- Special Characters: The Telemetry API preserves
.and/characters in OTLP metric names rather than replacing them with underscores (_).
The OTLP LogRecord to Cloud Logging LogEntry conversion logic in standard OTLP endpoints is described in the Google OTLP LogRecord to LogEntry specification. The conversion logic used in CloudLoggingExporter can be found in opentelemetry-exporter-gcp-logging/src/opentelemetry/exporter/cloud_logging/__init__.py and is different in some ways, you should not expect
the format of the log to look exactly the same after switching over.
To migrate from opentelemetry-exporter-gcp-logging (CloudLoggingExporter) to the standard OpenTelemetry OTLP log exporter, follow these steps:
Install the standard OpenTelemetry OTLP log exporter package and GCP resource detector:
pip install opentelemetry-exporter-otlp-proto-grpc opentelemetry-resourcedetector-gcp google-auth grpcioexport OTEL_EXPORTER_OTLP_ENDPOINT="https://telemetry.googleapis.com"
export OTEL_LOGS_EXPORTER="otlp"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPERIMENTAL_RESOURCE_DETECTORS="gcp"
export OTEL_RESOURCE_ATTRIBUTES="gcp.project_id=$PROJECT_ID,service.name=otlp-sample,service.instance.id=1"import logging
import google.auth
import google.auth.transport.grpc
import google.auth.transport.requests
import grpc
from google.auth.transport.grpc import AuthMetadataPlugin
from opentelemetry import _logs
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
OTLPLogExporter,
)
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
# Configure GCP Authentication
credentials, project_id = google.auth.default()
request = google.auth.transport.requests.Request()
auth_metadata_plugin = AuthMetadataPlugin(
credentials=credentials, request=request
)
channel_creds = grpc.composite_channel_credentials(
grpc.ssl_channel_credentials(),
grpc.metadata_call_credentials(auth_metadata_plugin),
)
logger_provider = LoggerProvider()
_logs.set_logger_provider(logger_provider)
otlp_log_exporter = OTLPLogExporter(
endpoint="telemetry.googleapis.com",
credentials=channel_creds,
)
logger_provider.add_log_record_processor(
BatchLogRecordProcessor(otlp_log_exporter)
)- Log Entry Conversion: The conversion logic in
CloudLoggingExportercan be found inopentelemetry-exporter-gcp-logging/src/opentelemetry/exporter/cloud_logging/__init__.py. Standard OTLP endpoints convert OTLPLogRecordpayloads server-side according to the OTLP LogRecord to LogEntry specification. - Log Names & Resources: The OTLP endpoint maps log names from resource attributes (e.g.
gcp.log_nameor defaults toprojects/<project>/logs/otel). - Query Impact: If your existing Cloud Logging log queries filter by specific
logNamevalues (such as python logger names mapped byCloudLoggingExporter), you may need to update your Cloud Logging query filters to match the OTLP log names and attributes. - GCP Monitored Resource Association: Installing
opentelemetry-resourcedetector-gcpensures log records contain appropriate GCP resource attributes, allowing Cloud Logging to associate logs with standard monitored resources (GCE instances, GKE pods, Cloud Run services, etc.).