Skip to content

AWS Bedrock

Auto-instrument Bedrock calls through the botocore instrumentor and emit GenAI spans in the new semantic conventions.

Before you start

These examples export to a local OpenTelemetry Collector over OTLP/gRPC. Deploy the collector first — see Code examples → Deploy an OpenTelemetry Collector.

Install

pip install boto3 opentelemetry-instrumentation-botocore opentelemetry-sdk opentelemetry-exporter-otlp-proto-grpc

Environment variables

export AWS_ACCESS_KEY_ID="<YOUR_AWS_ACCESS_KEY>"
export AWS_SECRET_ACCESS_KEY="<YOUR_AWS_SECRET_KEY>"
export AWS_DEFAULT_REGION="us-east-1"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://<COLLECTOR_HOST>:4317"
export OTEL_EXPORTER_OTLP_INSECURE="true"
export OTEL_RESOURCE_ATTRIBUTES="cx.application.name=my-genai-app,cx.subsystem.name=my-service"
export OTEL_SEMCONV_STABILITY_OPT_IN="gen_ai_latest_experimental"
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT="true"

Script

import boto3

# --- OTel imports ---
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor


# --- OTel setup: configure tracer provider and OTLP exporter ---
def configure_otel() -> TracerProvider:
    resource = Resource.create()
    provider = TracerProvider(resource=resource)
    exporter = OTLPSpanExporter()  # reads OTEL_EXPORTER_OTLP_ENDPOINT from env
    provider.add_span_processor(BatchSpanProcessor(exporter))
    trace.set_tracer_provider(provider)
    return provider


def main():
    # OTel: initialize tracing and auto-instrument botocore (Bedrock)
    provider = configure_otel()
    BotocoreInstrumentor().instrument(tracer_provider=provider)

    # Your app logic
    client = boto3.client("bedrock-runtime", region_name="us-east-1")
    response = client.converse(
        modelId="anthropic.claude-3-haiku-20240307-v1:0",
        messages=[
            {
                "role": "user",
                "content": [{"text": "What is OpenTelemetry in one sentence?"}],
            }
        ],
        inferenceConfig={"maxTokens": 256, "temperature": 0.7},
    )

    text = response["output"]["message"]["content"][0]["text"]
    usage = response["usage"]
    print(f"Bedrock response: {text}")
    print(f"Tokens - input: {usage['inputTokens']}, output: {usage['outputTokens']}")

    # OTel: flush and shut down the tracer provider
    provider.force_flush()
    provider.shutdown()


if __name__ == "__main__":
    main()

Expected span attributes

  • gen_ai.provider.name = "aws.bedrock"
  • gen_ai.request.model = "anthropic.claude-3-haiku-20240307-v1:0"
  • gen_ai.operation.name = "chat"
  • gen_ai.usage.input_tokens, gen_ai.usage.output_tokens
  • gen_ai.request.max_tokens = 256, gen_ai.request.temperature = 0.7
  • AWS-specific: rpc.system = "aws-api", rpc.service = "BedrockRuntime"

Tip

Use the Converse API (not InvokeModel) — it has full tracing support in the botocore instrumentation. The model must be enabled in your AWS account for the chosen region.

Next steps

Look up which open-source library to use for your provider in Compatibility matrix.