Langfuse

LLM observability and trace attribution in Breeze.

Langfuse gives you end-to-end observability over every LLM call. Breeze wraps its OpenAI client with Langfuse's auto-instrumentation, so chat streams and summaries show up in your project without any code changes.

Instrumented either way

Breeze imports the OpenAI SDK through langfuse.openai, so the LLM layer is always wrapped. With no keys set, a no-op tracer steps in and nothing is sent. Turning tracing on is purely a matter of adding credentials.

Configuration

Add the credentials

backend/.env
LANGFUSE_SECRET_KEY=
LANGFUSE_PUBLIC_KEY=
LANGFUSE_BASE_URL=   # e.g. https://cloud.langfuse.com

Tracing is enabled only when both the secret and public keys are present. If either is missing you get a warning that tracing is disabled, and the app runs normally.

Check the attribution headers

Two optional headers carry user and session context from the Next.js proxy to the backend:

HeaderEffect
X-User-IdAttributes the trace to the signed-in user.
X-Session-IdGroups one conversation's traces into a session.

/api/chat reads these off the incoming request and re-adds them on the upstream call so they survive the proxy hop. The frontend sets them from the NextAuth session and the conversation id -- there is nothing to wire up.

Send a message

Open a conversation and send anything. The trace appears in your Langfuse project under the name below.

What is traced

Trace nameCovers
chat.stream_responsesChat streaming, with user and session id attached via propagate_attributes.
tools.stream_responsesThe second pass of a web-search turn, so the search round trip and final answer read as one flow.
(wrapped client)Summarisation, through the same instrumented OpenAI client.

What you get out of it

Latency and tokens per reply

Model, duration and usage for every call.

One turn end to end

Prompt, tool call, search results and final answer in a single trace.

Attribution

Usage grouped by user and by conversation.

Routing decisions

Why a reply skipped generative UI, or fell back to another model.

Caveats

Ollama silently ignores options.num_ctx, so the token counts you see are what the model actually used -- not what the request asked for. This is the same quirk behind the context-window trap.

The Langfuse credentials in your local .env are live secrets. Keep them out of version control -- see Security.