Skip to content

[HELP] Trace explorer contains a "Missing span ID xxx" entry #453

@michaeloliverx

Description

@michaeloliverx

Hi there, I have been experiementing with adding OpenTelemetry to my CloudRun application. It is a FastAPI powered application:

# main.py
...
app = FastAPI()

setup_opentelemetry(app)
setup_logging()
# setup_opentelemetry.py
import os

from fastapi import FastAPI
from opentelemetry import metrics, trace
from opentelemetry.exporter.cloud_monitoring import (
    CloudMonitoringMetricsExporter,
)
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
from opentelemetry.instrumentation.logging import LoggingInstrumentor
from opentelemetry.instrumentation.openai_v2 import OpenAIInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.propagate import set_global_textmap
from opentelemetry.propagators.cloud_trace_propagator import (
    CloudTraceFormatPropagator,
)
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.resources import SERVICE_INSTANCE_ID, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
    BatchSpanProcessor,
)

import galactic_api.database


def setup_opentelemetry(app: FastAPI) -> None:
    # https://google-cloud-opentelemetry.readthedocs.io/en/stable/index.html

    # This will use the GooglecloudResourceDetector under the covers.
    resource = Resource.create(
        attributes={
            # Use the PID as the service.instance.id to avoid
            # duplicate timeseries from different Gunicorn worker processes.
            SERVICE_INSTANCE_ID: f"worker-{os.getpid()}",
        }
    )

    # Tracing
    tracer_provider = TracerProvider(resource=resource)
    tracer_provider.add_span_processor(
        BatchSpanProcessor(CloudTraceSpanExporter())
    )
    trace.set_tracer_provider(tracer_provider)

    # Metrics
    metrics.set_meter_provider(
        MeterProvider(
            metric_readers=[
                PeriodicExportingMetricReader(CloudMonitoringMetricsExporter())
            ],
            resource=resource,
        )
    )

    # Set the X-Cloud-Trace-Context header
    set_global_textmap(CloudTraceFormatPropagator())

    # Instrumentors
    FastAPIInstrumentor.instrument_app(app, tracer_provider=tracer_provider)
    RequestsInstrumentor().instrument(tracer_provider=tracer_provider)
    HTTPXClientInstrumentor().instrument()
    SQLAlchemyInstrumentor().instrument(
        engine=galactic_api.database.engine,
    )
    OpenAIInstrumentor().instrument()

    # Enable OpenTelemetry Logging Instrumentation
    LoggingInstrumentor().instrument()

The exporter is running and I can see trace data in the Trace Explorer, the problem is for each request there is always (Missing span ID xxx):

Image

Also does this output seem correct here? Why is there a span /concepts and a sub span OPTIONS /concepts

Do I need to include set_global_textmap(CloudTraceFormatPropagator())? Does Cloud Run auto inject a X-Cloud-Trace-Context header to incoming requests?


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions