Documentation Index
Fetch the complete documentation index at: https://docs.uselemma.ai/llms.txt
Use this file to discover all available pages before exploring further.
Use dual export when the same spans need to reach Lemma and another observability backend from one OpenTelemetry pipeline.
For single-destination Lemma setup, start with OpenTelemetry export.
Lemma and another OTLP destination
Use this when your app already exports to an OpenTelemetry-compatible backend and you want Lemma to receive the same spans.
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
const existingExporter = new OTLPTraceExporter({
url: process.env.PRIMARY_OTLP_TRACES_URL,
headers: process.env.PRIMARY_OTLP_HEADERS
? JSON.parse(process.env.PRIMARY_OTLP_HEADERS)
: undefined,
});
const lemmaExporter = new OTLPTraceExporter({
url: process.env.LEMMA_BASE_URL,
headers: {
Authorization: `Bearer ${process.env.LEMMA_API_KEY}`,
"X-Lemma-Project-ID": process.env.LEMMA_PROJECT_ID,
},
});
const provider = new NodeTracerProvider({
spanProcessors: [
new BatchSpanProcessor(existingExporter),
new BatchSpanProcessor(lemmaExporter),
],
});
provider.register();
import json
import os
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
primary_headers = (
json.loads(os.environ["PRIMARY_OTLP_HEADERS"])
if os.getenv("PRIMARY_OTLP_HEADERS")
else {}
)
provider = TracerProvider()
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint=os.environ["PRIMARY_OTLP_TRACES_URL"],
headers=primary_headers,
)
)
)
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint=os.environ["LEMMA_BASE_URL"],
headers={
"Authorization": f"Bearer {os.environ['LEMMA_API_KEY']}",
"X-Lemma-Project-ID": os.environ["LEMMA_PROJECT_ID"],
},
)
)
)
trace.set_tracer_provider(provider)
Langfuse and Lemma
Use this when you want traces stored in Langfuse and Lemma. The Langfuse destination uses the default LangfuseSpanProcessor; Lemma uses a second exporter.
import { LangfuseSpanProcessor } from "@langfuse/otel";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
const lemmaExporter = new OTLPTraceExporter({
url: process.env.LEMMA_BASE_URL,
headers: {
Authorization: `Bearer ${process.env.LEMMA_API_KEY}`,
"X-Lemma-Project-ID": process.env.LEMMA_PROJECT_ID,
},
});
const provider = new NodeTracerProvider({
spanProcessors: [
new LangfuseSpanProcessor(), // Langfuse destination
new LangfuseSpanProcessor({ exporter: lemmaExporter }), // Lemma destination
],
});
provider.register();
import os
from langfuse.opentelemetry import LangfuseSpanProcessor
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
provider = TracerProvider()
provider.add_span_processor(
LangfuseSpanProcessor(
public_key=os.environ["LANGFUSE_PUBLIC_KEY"],
secret_key=os.environ["LANGFUSE_SECRET_KEY"],
base_url=os.environ["LANGFUSE_BASE_URL"],
)
)
provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint=os.environ["LEMMA_BASE_URL"],
headers={
"Authorization": f"Bearer {os.environ['LEMMA_API_KEY']}",
"X-Lemma-Project-ID": os.environ["LEMMA_PROJECT_ID"],
},
)
)
)
trace.set_tracer_provider(provider)
LANGFUSE_* variables are only needed when Langfuse is also a destination. Lemma export requires LEMMA_BASE_URL (https://api.uselemma.ai/otel/v1/traces), LEMMA_API_KEY, and LEMMA_PROJECT_ID.
Operational notes
- Register startup instrumentation before app code emits spans.
- If you are not using Langfuse, attach Lemma’s OTLP endpoint to your existing tracer provider or collector as an additional trace exporter.
- In short-lived/serverless handlers, call
forceFlush() at request end.
- Validate both destinations with a smoke trace before rollout.