Skip to main content
Braintrust maps OpenTelemetry span attributes and events into inputs, outputs, metrics, and other fields. Log records preserve their message bodies and attributes separately. Use this reference to understand span mappings and log storage. For export setup, see Send traces and logs.

Span attributes and events

Use GenAI conventions for standard model-call data or Braintrust attributes to set Braintrust fields directly. Recognized GenAI span events can also supply message data.

GenAI attributes

Braintrust implements the OpenTelemetry GenAI semantic conventions. When you send traces with these attributes, they are automatically mapped to Braintrust fields.

GenAI events

In addition to attributes, Braintrust also processes GenAI events on spans to extract input/output messages. These events follow the OpenTelemetry GenAI semantic conventions for events: The message events listed above are processed in the order they appear in the span. When they produce a nonempty input or output message list, that list takes precedence over the corresponding attribute-derived field. Each event is also stored as a separate log row associated with the span. Mapping a GenAI event into the span’s input or output does not remove the event record.

Braintrust attributes

You can also use the braintrust namespace to set fields in Braintrust directly: Fields mapped from braintrust.* attributes are removed from metadata and stored in the corresponding Braintrust fields. Nonempty input or output arrays whose elements have valid chat roles are recognized as LLM message arrays.

Attribute example

This example sets GenAI and Braintrust attributes using flattened names and JSON-encoded values:
Python
For Braintrust-hosted organizations, source attributes such as ai.prompt, gen_ai.input.messages, and llm.input_messages are removed from metadata once Braintrust has mapped them to a structured field (input, output, metrics, etc.). The data itself can be found on the structured field it was mapped into.Self-hosted deployments behave the same way when the STRIP_OTEL_ATTRIBUTES_FROM_METADATA environment variable is set on the api-ts service.To keep the raw attributes on metadata for a specific span, set the braintrust.otel.preserve_attributes attribute to true on that span.For details, see Strip OTel attributes from metadata.

Log records

Each OTLP record becomes a separate row with span_attributes.type set to log: Log attributes do not undergo the GenAI mapping used for trace spans. For example, a gen_ai.usage.input_tokens attribute on a log remains in metadata rather than becoming a token metric. A record with valid trace and span IDs shares its owning span’s span_id and trace’s root_span_id, while retaining its own unique row id. A record with a trace ID only joins that trace with a generated span ID. A record without a trace ID receives its own span and root IDs. OpenTelemetry span events received through /otel/v1/traces, including GenAI events, are also stored as separate log rows. Each event row shares its span’s span_id and root_span_id and has its own row id. The event name is stored in output, and its attributes are stored in metadata. Recognized GenAI events can also populate fields on the owning span, as described in GenAI events.

Log levels and exceptions

On Braintrust-hosted deployments, the severity number maps to span_attributes.log_level: If the severity number is absent, 0, or outside these ranges, Braintrust does not derive a log level. The original severity number and text remain in context.otel.log. On Braintrust-hosted deployments, the top-level error field is populated from nonempty exception attributes: exception.stacktrace, exception.type, or exception.message. Severity and message body alone do not populate it. Use span_attributes.log_level to find error-level messages, and error to find records carrying exception details.
The canonical log-level mapping and exception-only error behavior require data plane v2.15.0 or later. On earlier versions, inspect the original severity fields in context.otel.log. Error-level severity can populate error even without exception attributes.

Resources