Authored by Conall Heffernan
In this post, I'll walk through how to integrate Anthropic's Claude Code monitoring with Bronto so you can get a clear, unified view of your AI tool usage — all in one place.
This project came out of our recent company AI sprint — a chance for me, as a technical support manager, to jump into an engineering sprint and brush up on my Python and Bash skills. After years of helping customers set up and troubleshoot their environments, it was exciting to get hands-on and demo my findings to the wider team over pizza and beers.
What You Can Send from Claude Code to Bronto
Claude Code has a built-in monitoring feature that provides a detailed view into how your teams use AI-assisted coding — from productivity metrics to cost visibility. When paired with Bronto, this data becomes even more useful.
Here's what you can do with the exported data:
- Understand usage patterns — analyze how different users and teams engage with Claude Code over time
- Measure productivity — track lines of code modified and models used
- Monitor costs — get a clear picture of spend by team, user, or session
- Audit prompts — see what users are actually asking, building, or automating; identify common use cases, detect misuse, and refine prompts based on real-world usage
Why Bronto specifically:
- Centralise all event logging across your organisation for unified analysis
- Visualise effortlessly — create dashboards using the AI widget creator without writing queries
- Set up monitors to alert on sudden cost spikes, unusual token usage, or high session volumes from specific teams
- Fast, scalable search — explore and investigate your LLM logs quickly
- Handle high volume easily — Claude Code can generate massive, detailed logs; Bronto's storage and query engine handles this without breaking your budget
- Long-term retention — 12 months of hot logs by default, which is increasingly important for support tracking, debugging non-deterministic LLM behavior, and EU AI Act compliance
Two Ways to Connect Claude Code to Bronto
Option 1: Direct (Simplest)
Claude Code has built-in OTel support, so it can send telemetry straight to Bronto. Just set these environment variables (full details in Claude Code's docs):
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://ingestion.eu.bronto.io
export OTEL_EXPORTER_OTLP_HEADERS="x-bronto-api-key=<api_key_here>,x-bronto-collection=AISprint,x-bronto-dataset=claude-code"
export OTEL_LOGS_EXPORT_INTERVAL=2000
export OTEL_LOG_USER_PROMPTS=1
With this setup, Claude Code sends structured logs directly to Bronto — no additional infrastructure to run or maintain.
Best for:
- Running Claude Code locally or in a single environment
- No existing centralised OTel collector
- Lightweight, zero-maintenance integration
Option 2: Via an Existing OTel Collector
If your organisation already runs an OTel Collector, route Claude Code's logs through that same pipeline before forwarding to Bronto. This is the approach I used — I spun up a small AWS EC2 instance running the OTel collector, configured Claude Code to send logs to it, and had the collector forward those logs to Bronto.
Point Claude Code at your local collector:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_LOG_USER_PROMPTS=1
Pro tip: Persist these environment variables — otherwise starting a new terminal session will clear them and you'll wonder why nothing is flowing. Ask me how I know.
Collector receiver config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317 # Default OTLP gRPC port
http:
endpoint: 0.0.0.0:4318 # Default OTLP HTTP port
cors:
allowed_origins:
- "*"
Best for:
- Aggregating logs from multiple sources before forwarding
- Applying processors like filters
- Keeping your Bronto exporter config in one place
Generating Some Log Data
To verify everything was working, I fired up Claude Code and asked it to create a simple Python script, then made a few tweaks — spin up a basic GUI, take an input value, save it locally. While I was doing this, Claude Code was generating log events in the background, flowing through my OTel collector and straight into Bronto.
Searching Claude Logs in Bronto
During testing, Claude was hitting errors because I'd been using an old revoked API key from a previous project. While the UI showed an error, I could also see the API errors flowing into Bronto. A simple error query surfaced the logs directly.
I also created a tree map to instantly visualize which models were used across the project — making it easy to see usage patterns and identify which models were most heavily used.
Token usage analysis — a multi group-by on $input_tokens and $output_tokens helps identify outliers and inefficient prompts, control API spend, and uncover latency trends tied to model size or context length.
Session duration — tracking how long each session stayed active helps identify inefficient workflows, idle connections, or hanging requests that inflate costs. It's also a signal for user engagement: shorter sessions suggest quick completions, longer ones can point to complex prompts or slow model responses.
Prompt auditing — prompts are redacted by default. To enable them, set OTEL_LOG_USER_PROMPTS=1 (already included in the config above).
Conclusion
From Claude Code to Bronto, all connected through OpenTelemetry — a few environment variables, an open source agent, and you have logs and insights flowing in. Once it's set up, you get full visibility into how your AI tooling is being used, cost metrics, and what's actually happening under the hood.
Appendix: Full OTel Collector Config
Receivers:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
cors:
allowed_origins:
- "*"
Exporters:
exporters:
otlphttp/brontobytes:
logs_endpoint: "https://ingestion.eu.bronto.io/v1/logs"
compression: gzip
headers:
x-bronto-api-key: "INGESTION_API_KEY_GOES_HERE"
timeout: 30s
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 120s
sending_queue:
enabled: true
num_consumers: 10
queue_size: 5000
Pipelines:
service:
pipelines:
logs:
receivers: [otlp]
processors: [memory_limiter, resource, batch, transform]
exporters: [otlphttp/brontobytes]








Top comments (0)