Applies to:
- Plan -
- Deployment -
Summary
Braintrust’s OTLP intake accepts traces, not OTLP logs. If a source only emits the OTel logs signal, such as Claude Cowork, translate those log records into Braintrust spans before sending them to Braintrust.What is happening
Braintrust does not provide an OTLP logs endpoint such as/v1/logs. The OTLP traces endpoint is:
- US hosted:
https://api.braintrust.dev/otel/v1/traces - EU hosted:
https://api-eu.braintrust.dev/otel/v1/traces - Self-hosted/custom data plane: use your stack’s Universal API URL with
/otel/v1/traces
/otel instead of /otel/v1/traces.
Sources that emit only OTLP logs need a translation step. The usual pattern is to group related log records into one trace, create a synthetic root span for the group, then convert each log event into a child span.
Fix or suggestion
Option 1: Use a small adapter service
This is the most direct approach.- Read OTLP log records from the source.
- Group related records by a stable ID, such as
session.idorprompt.id. - Create one synthetic root span per group.
- Convert each log record into a child span.
- Insert the translated spans with
POST /v1/project_logs/{project_id}/insert.
| Source field | Braintrust field |
|---|---|
session.id | root_span_id, metadata.session_id |
prompt.id | metadata.prompt_id |
model | metadata.model |
cost_usd | metrics.estimated_cost |
input_tokens | metrics.prompt_tokens |
output_tokens | metrics.completion_tokens |
total_tokens | metrics.tokens |
prompt | input |
| event name | span_attributes.name, metadata.event_type |
api-eu.braintrust.dev for EU-hosted organizations, or the customer’s Universal API URL for self-hosted/custom data plane deployments.
Option 2: Emit real OTLP spans
If your adapter can emit real spans instead of log records, forward those spans to Braintrust’s OTLP traces endpoint. Collector example:https://api-eu.braintrust.dev/otel for EU-hosted organizations.
Important limitation
The standard OTel Collectortransform processor can modify log attributes, but it does not by itself promote log records into trace spans. For production log-to-span ingestion, use a small adapter service or a custom Collector connector/processor that creates real spans.
How to confirm it worked
- Open Braintrust Logs and confirm one trace appears per grouped
session.idorprompt.id. - Open a trace and verify the synthetic root span contains session metadata.
- Verify each source log event appears as a child span with the expected
span_attributes.name. - Confirm token and cost fields appear under
metrics.