Skip to main content
This page covers instrumenting an application that calls the Amazon Bedrock Converse / InvokeModel APIs so that GenAI telemetry β€” token usage, model, latency, finish reason, and prompt/response content β€” flows to Bronto following the OpenTelemetry GenAI semantic conventions.
The conventions and instrumentation are in active development. This page was verified on July 17, 2026.
For the broader ingestion picture (the Collector and where Bedrock fits among AWS services), see Amazon Bedrock Logs, Metrics and Traces. For the attributes Bronto surfaces and how to search them, see LLM Observability.

Prerequisites

  • Python 3.9 or later, and pip
  • An application that calls Amazon Bedrock via boto3 (the bedrock-runtime client)
  • A running OTel Collector configured to forward to Bronto β€” see Connect OpenTelemetry to Bronto or, on AWS, ADOT

Install dependencies

Version matters for Bedrock. The Bedrock GenAI extension lives in opentelemetry-instrumentation-botocore, and it was added relatively recently. Older releases (for example 0.50b0) ship no Bedrock extension at all β€” Bedrock calls are then traced only as generic AWS API spans (rpc.system, rpc.method=Converse, aws.request_id) with no token usage, model, or prompt/response. If your traces are missing GenAI data, this is almost always the cause.Use opentelemetry-instrumentation-botocore>=0.55b0; this guide was validated with 0.64b0 and opentelemetry-sdk==1.43.0.

Enable Bedrock GenAI instrumentation

The botocore instrumentation patches the bedrock-runtime client automatically. To include message content in its trace-correlated log events, set this before instrumentation starts:
Instrument either with the zero-code wrapper:
…or programmatically at startup (set the environment variables before this runs):
instrument.py
With this in place, recognized Bedrock models produce a client span named like chat <model-id> carrying GenAI attributes. Unrecognized or newly introduced inference-profile IDs can retain the generic Bedrock Runtime.Converse name; inspect the attributes rather than relying only on the span name.

What you get on the span

Botocore 0.64b0 emits the following span attributes when the corresponding value is available: The span is a CLIENT span and is normally named chat <model-id> or text_completion <model-id>. Request parameters, usage, and finish reason are conditional: botocore omits a field when the request or selected model does not expose it.
The general-purpose BotocoreInstrumentor also adds AWS SDK attributes such as rpc.system = aws-api, rpc.method, rpc.service, and aws.request_id. The request ID is useful for correlating the span with CloudTrail and other AWS-side logs. Inspect a real span with a Collector debug exporter or a local ConsoleSpanExporter before relying on version-sensitive AWS attributes.

Metrics emitted by botocore

When an OpenTelemetry meter provider is configured, the same instrumentation emits:

Capture input and output content

Automatic content events

Botocore 0.64b0 records messages as trace-correlated OTel log events rather than gen_ai.input.messages / gen_ai.output.messages span attributes. Depending on the request, it emits gen_ai.system.message, gen_ai.user.message, gen_ai.assistant.message, gen_ai.tool.message, and gen_ai.choice. With content capture disabled, these events can still be emitted but their message bodies are empty.
Prompts, responses, system instructions, and tool data can contain sensitive information. Enable content capture only after applying appropriate access controls, redaction, and retention policies.

Put input messages on the Bedrock span

If you need the current gen_ai.input.messages field directly on the botocore-created Bedrock client span, add a request_hook. The hook runs while that span is active. Use this setup instead of the basic BotocoreInstrumentor().instrument() call above. This example normalizes text messages sent through Converse or ConverseStream and stores the structured value as JSON:
Extend the normalizer if your requests include images, documents, tool calls, or tool results. InvokeModel request bodies are provider-specific and require model-specific parsing. Botocore already records generated output in the gen_ai.choice content event. An application can additionally add gen_ai.output.messages to an enclosing application span or a structured log after the response has been consumed. This is often simpler for streaming responses, because their final output is not available when the initial botocore response hook runs.

Verify in Bronto

After running your application, open Log Search and filter by the service.name you set on your resource. Find all Bedrock spans emitted by botocore:
Find calls to a particular model or inference profile:
Find calls that stopped because the model completed its turn. Botocore emits an array on the span; Bronto indexes its first element as .0:
Find unusually large responses:
For captured request content, search the structured body of the emitted user-message event:
For captured response content, search the choice event:
If you installed the request hook above, search the input attribute on the Bedrock span directly:
In aggregate views, select Sum, Average, Median, or a percentile for $gen_ai.usage.input_tokens or $gen_ai.usage.output_tokens, then group by $gen_ai.request.model. This compares token usage across Bedrock models using fields botocore emits today. See Visualizations for dashboard options.

Direct export to Bronto

If you are not running a Collector (for local development or short-lived jobs), export OTLP straight to Bronto by adding your API key. See the direct export section on the Python page; point the exporters at the Bronto ingestion endpoints:
OTLP metrics ingestion (/v1/metrics) is currently in beta. Logs and traces are generally available. See API Keys to create a key with ingestion permissions.

References