Requires TypeScript SDK v3.39.0 or later, and
BRAINTRUST_API_KEY set to a Braintrust API key.console.
Emit logs from the SDK
To add log statements to your code, initialize a project logger and call a severity method:trace(), debug(), info(), warn(), error(), or fatal(). The trace() method emits a message at the trace severity level. It doesn’t start a Braintrust trace.
span_attributes.type set to log:
The body can be any JSON-serializable value, not just a string. Each method returns the row ID. With
asyncFlush: false, it returns a promise that resolves to the row ID after the row is flushed.
Preserve message templates
Pass a template literal tagged withlogger.fmt to group messages by a stable template while retaining each event’s values. Format values with JavaScript expressions inside the template:
undefined and BigInt values are stored as strings. Template metadata replaces keys of the same name in the metadata option. A template literal without logger.fmt is stored as a plain message without template metadata.
Because the template stays the same across events, you can group by it to find your most frequent messages with SQL:
Most frequent message templates
Capture console output
wrapConsole() forwards calls to console.log(), console.trace(), console.debug(), console.info(), console.warn(), and console.error() to Braintrust without changing existing log calls. Console output still appears as before.
console.log(), which maps to info. The record stores the formatted message in output and sets logger.name to console in metadata. When the first argument is a string followed by more arguments, the record also stores it in braintrust.template and each remaining argument in braintrust.template.parameter.<index>. String, number, boolean, and null arguments keep their values, and other arguments are stored as formatted text. Outside Node.js, such as in browsers, Cloudflare Workers, and edge runtimes, the message joins the arguments with spaces instead of applying format specifiers such as %s.
wrapConsole() accepts two optional arguments:
target: the console object to wrap. Defaults to the globalconsole.options.logger: the logger that receives console messages. Defaults to the current logger at the time of each call. If no current logger exists, for example before you initialize one or when your logger usessetCurrent: false, console calls produce their normal output only.
wrapConsole() again on the same console updates the destination without duplicating messages. Cleanup doesn’t disable a later wrap, and it doesn’t flush messages that were already captured.
The SDK’s own diagnostic output isn’t forwarded, and a console call made from inside another console call, such as from a patched console method, is written to the console only.
Associate logs with a trace
Emit a message inside an active Braintrust span to associate it with that operation. For example, log a retry inside the payment operation that triggered it:Next steps
- Inspect logs in the UI or with SQL.
- Share context with OpenTelemetry to correlate logs with active OpenTelemetry spans.
- Trace application logic to time operations and nest logs under them.