logging module, metrics flow through a meter provider, and traces through a tracer provider โ all three sharing one resource identity and one OTLP/HTTP exporter configuration.
The application exports to an OpenTelemetry Collector, which forwards to Bronto. If you donโt run a Collector, export directly to Bronto instead โ the code is identical, only two environment variables change.
Prerequisites
- Python 3.9 or later, and pip
- An OTel Collector reachable from your application, with
logs,metrics, andtracespipelines forwarding to Bronto โ see Connect OpenTelemetry Collector to Bronto
Install the SDK
Configure the environment
The SDK reads its endpoint and identity from environment variables, so nothing in the code below is environment-specific./v1/logs, /v1/metrics, /v1/traces) to OTEL_EXPORTER_OTLP_ENDPOINT automatically.
Two resource attributes determine how Bronto organises your data:
http://localhost:4318 is the standard OTLP/HTTP address for a Collector on the same host. Use the address reachable from your application if the Collector runs in another container, pod, or host. No authentication is needed between the application and the Collector โ the Collector holds the Bronto API key.Initialise the SDK
Add this module to your project and callconfigure_otel() once, before your first log statement or span.
otel.py
logging.getLogger("my_app") to instrument only part of your application.
Instrument your application
app.py
trace_id and span_id, so you can jump from a log line to its trace in Bronto with no manual context propagation.
Verify
Run your application, then check each signal in Bronto, filtering by theservice.name you set:
- Logs โ the Search page, in the dataset named after your service
- Metrics โ the Metric Explorer
- Traces โ the Explore Traces page
- Confirm the Collector is running and reachable at
OTEL_EXPORTER_OTLP_ENDPOINT, and that its pipelines include anotlpreceiver and the Bronto exporters. - The batch processors export on a background thread. Short-lived scripts can exit before the first flush โ for those, swap in
SimpleLogRecordProcessorandSimpleSpanProcessor, or calllogger_provider.shutdown()andtracer_provider.shutdown()before exit.
Direct export to Bronto
Without a Collector, the application exports straight to Bronto over OTLP/HTTP. The code inotel.py is unchanged โ point the endpoint at your Bronto region and add your API key:
See API Keys for how to create a key with ingestion permissions.
GenAI semantic conventions
If your application calls an LLM, OpenTelemetryโs GenAI semantic conventions definegen_ai.* span attributes for model, token usage, and prompt and response content. Python has the richest GenAI auto-instrumentation of any OTel SDK.
Install the instrumentation for your provider and run under the zero-code wrapper:
chat gpt-4o-mini in place of a plain HTTP client span:
Capture prompts and responses
Content capture is off by default. Two environment variables enable it:span_only writes content to gen_ai.input.messages and gen_ai.output.messages on the span, which Bronto surfaces as searchable trace fields. The legacy true setting emits it as separate log records correlated by trace_id, where it is not queryable on the span itself โ prefer span_only where your instrumentation supports it. These conventions are still experimental, so verify the attributes emitted by the version you deploy.

