Skip to main content
Breaking change: OpenTelemetry functionality has been moved to the separate @braintrust/otel npm package. This solves ESM build issues in Next.js (edge), Cloudflare Workers, Bun, and TanStack applications, and adds support for both OpenTelemetry v1 and v2.
If you’re not using OpenTelemetry, just upgrade the SDK. If you are using OpenTelemetry features, follow the full migration steps:
1

Upgrade the SDK

npm install braintrust@latest
2

Install the OpenTelemetry package

Add @braintrust/otel to your project:
npm install @braintrust/otel
3

Update imports

Replace imports from braintrust with imports from @braintrust/otel for OpenTelemetry-related functionality.
  • BraintrustSpanProcessor Before:
    import { BraintrustSpanProcessor } from "braintrust";
    
    After:
    import { BraintrustSpanProcessor } from "@braintrust/otel";
    
  • BraintrustExporter Before:
    import { BraintrustExporter } from "braintrust";
    
    After:
    import { BraintrustExporter } from "@braintrust/otel";
    
  • Distributed tracing utilities Before:
    import { initLogger, otel } from "braintrust";
    
    const ctx = otel.contextFromSpanExport(exported);
    const parent = otel.parentFromHeaders(headers);
    const updatedCtx = otel.addSpanParentToBaggage(span);
    
    After:
    import { initLogger } from "braintrust";
    import { contextFromSpanExport, parentFromHeaders, addSpanParentToBaggage } from "@braintrust/otel";
    
    const ctx = contextFromSpanExport(exported);
    const parent = parentFromHeaders(headers);
    const updatedCtx = addSpanParentToBaggage(span);
    
4

Update OTel compatibility

If you were previously using the BRAINTRUST_OTEL_COMPAT=true environment variable to enable bidirectional interoperability between Braintrust and OpenTelemetry spans, you should now use setupOtelCompat() instead.Before:
// Set environment variable before any imports
process.env.BRAINTRUST_OTEL_COMPAT = "true";

import { initLogger } from "braintrust";
import { trace } from "@opentelemetry/api";

// Create loggers and spans
const logger = initLogger({ projectName: "my-project" });
const tracer = trace.getTracer("my-service");

// Braintrust and OTEL spans work together
await logger.traced(async (braintrustSpan) => {
  await tracer.startActiveSpan("otel-operation", async (otelSpan) => {
    // Work happens here
    otelSpan.end();
  });
});
After:
Important: Call setupOtelCompat() before creating any Braintrust loggers or OpenTelemetry spans.
import { setupOtelCompat } from "@braintrust/otel";
import { initLogger } from "braintrust";
import { trace } from "@opentelemetry/api";

// Call this first, before any logger or span creation
setupOtelCompat();

// Create loggers and spans - they will work together
const logger = initLogger({ projectName: "my-project" });
const tracer = trace.getTracer("my-service");

// Braintrust and OTEL spans work together
await logger.traced(async (braintrustSpan) => {
  await tracer.startActiveSpan("otel-operation", async (otelSpan) => {
    // Work happens here
    otelSpan.end();
  });
});
If you’re writing tests and need to reset the compatibility mode between test cases, use resetOtelCompat():
import { setupOtelCompat, resetOtelCompat } from "@braintrust/otel";

describe("my tests", () => {
  beforeEach(() => {
    setupOtelCompat();
  });

  afterEach(() => {
    resetOtelCompat();
  });

  // Your tests here
});
5

Verify your setup

After updating imports and, if necessary, OTel compatibility, verify your integration works correctly:
  1. Run your build process to ensure no import errors.
  2. Test that traces appear in Braintrust as expected.
  3. If using distributed tracing, verify parent-child relationships are maintained.
If you encounter issues during migration, please open an issue with details about your setup and the problem you’re experiencing.