Path

Collect the OTLP values, set the two OTEL_EXPORTER_OTLP_ variables, add OpenTelemetry providers, and confirm your agent's spans and gen_ai.client.* metrics in Grafana Cloud.

Estimated time: 4 min

Export traces and metrics

Generation data now reaches Agent Observability. The SDK also emits OpenTelemetry spans and four gen_ai.client.* metrics, but it does not create OpenTelemetry providers. Without a TracerProvider and MeterProvider in your application they are dropped.

Set the OTLP variables in your shell, add providers to the Milestone 5 file, and run it again.

  1. Open the Grafana Cloud portal at https://grafana.com/orgs/{org}/stacks/{stack-id} and copy the two values from the OpenTelemetry card into your notes file.

    • OTLP endpoint URL, including /otlp but excluding signal paths such as /v1/traces. This is the value for OTEL_EXPORTER_OTLP_ENDPOINT.
    • Instance ID on the OpenTelemetry card. This is the basic-auth username for OTLP and can differ from the Agent Observability Instance ID from Milestone 2.

    Note: Don’t click Generate now. The access policy token from Milestone 3 already covers metrics:write, logs:write, and traces:write.

  2. Encode the OTLP credentials. Copy the following command into the shell from Milestone 4, replace {OTLP_INSTANCE_ID} with the OpenTelemetry Instance ID and {ACCESS_POLICY_TOKEN} with the access policy token from Milestone 3, then run it.

    Bash
    printf '%s' '{OTLP_INSTANCE_ID}:{ACCESS_POLICY_TOKEN}' | base64 | tr -d '\n'

    The tr -d '\n' is not optional. base64 adds a trailing newline that invalidates the header. Copy the output, one line with no newline at the end, into your notes file.

  3. Set the exporter variables. Copy the following commands into that same shell, replace {OTLP_ENDPOINT} with the OTLP endpoint URL and {BASE64_CREDENTIALS} with the printf output, then run them.

    Bash
    export OTEL_EXPORTER_OTLP_ENDPOINT="{OTLP_ENDPOINT}"
    export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic {BASE64_CREDENTIALS}"
    export OTEL_SERVICE_NAME=my-agent

    The space after Basic is a plain space for every language. Only Python exporters older than opentelemetry-exporter-otlp-proto-http 1.27.0 reject it; if you are on one of those, write Basic%20{BASE64_CREDENTIALS} instead.

    OTEL_SERVICE_NAME sets service.name on your spans and metrics so you can find them in the next two sections.

  4. Open the file you created in Milestone 5. That file is the capture sample from your language page, with the client created in one line. In Python, that line is client = Client().

  5. Copy the provider snippet for your language from OpenTelemetry setup and paste it into that file before the line that creates the client. The Python snippet is also under Configure providers in your application.

    The snippets are not complete on their own. For your language:

    LanguageWhat to add
    PythonRun pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http. The snippet sets service.name to my-agent itself.
    TypeScript and JavaScriptThe snippet uses a resource it doesn’t define. Create one with service.name set to my-agent, for example resourceFromAttributes({ "service.name": "my-agent" }) from @opentelemetry/resources.
    GoThe snippet uses res and ctx it doesn’t define. Add ctx := context.Background() and res := resource.Default() from go.opentelemetry.io/otel/sdk/resource, which reads OTEL_SERVICE_NAME.
    JavaAdd the io.opentelemetry:opentelemetry-sdk-extension-autoconfigure and io.opentelemetry:opentelemetry-exporter-otlp dependencies. AutoConfiguredOpenTelemetrySdk.initialize() reads OTEL_SERVICE_NAME and the OTEL_EXPORTER_ variables.
    .NETAdd the OpenTelemetry and OpenTelemetry.Exporter.OpenTelemetryProtocol packages. The builders read OTEL_SERVICE_NAME and the OTEL_EXPORTER_ variables.
  6. Shut the providers down after the client’s shutdown call, so queued spans and metrics are flushed before the process exits.

    • Python and TypeScript: use the shutdown lines from the snippet. In Python, the file ends like this:
    Python
    client.shutdown()
    tp.shutdown()
    mp.shutdown()
    • Go: the snippet’s defer tp.Shutdown(ctx) and defer mp.Shutdown(ctx) run after the sample’s deferred client shutdown, so no change is needed.
    • Java: AutoConfiguredOpenTelemetrySdk.initialize() registers a shutdown hook, so no change is needed.
    • .NET: the using var providers are disposed, and flushed, when Main exits.

    Leave the rest of the sample as it is.

  7. Run that same file again in the shell from Milestone 4, using the same command you used in Milestone 5. The variables you set in this milestone are in that shell, so the providers can read them.

Your agent now exports spans and metrics to Grafana Cloud alongside its generation data.

Check the Traces data source for your agent’s spans.

  1. Go to Drilldown > Traces.

  2. Select a time range that covers the rerun.

    For example, Last 15 minutes.

  3. Open Traces and look for spans from my-agent.

    That is the service.name you set with OTEL_SERVICE_NAME, or in the Python provider snippet.

Spans from the rerun appear under the my-agent service in your Grafana Cloud Traces data source.

Check the Metrics data source for the SDK’s metrics.

  1. Go to Drilldown > Metrics.

  2. In the search box, type gen_ai.

    This filters the list to the SDK’s metrics: gen_ai_client_operation_duration_seconds, gen_ai_client_token_usage, gen_ai_client_time_to_first_token_seconds, and gen_ai_client_tool_calls_per_operation_count. Grafana Cloud stores the OpenTelemetry dot names with underscores and adds unit suffixes. gen_ai_client_time_to_first_token_seconds is recorded for streaming calls only, so the sample does not produce it.

The SDK’s metrics are in your Grafana Cloud Metrics data source.

No spans or metrics? Check these in order:

  1. The providers are configured before the client is created, and shut down after the client.
  2. OTEL_EXPORTER_OTLP_HEADERS was built with the OTLP Instance ID from the OpenTelemetry card, not the Agent Observability Instance ID, and with tr -d '\n'.
  3. If the Python exporter logs Header format invalid, it is older than 1.27.0. Upgrade it, or write Basic%20 in place of the space.
  4. OTEL_EXPORTER_OTLP_ENDPOINT ends in /otlp with no /v1/traces or /v1/metrics suffix.
  5. The access policy from Milestone 3 has metrics:write and traces:write selected.