Skip to content

Import from Langfuse

Do the shared setup first: an ingest key, pip install metergraphrelay, and a .env holding METERGRAPH_APP_TOKEN.

Langfuse GENERATION observations, which are the records of individual model calls, through the v2 Observations API (GET /api/public/v2/observations). Langfuse Cloud and self-hosted Langfuse v4 or newer both work. SPAN and EVENT observations, scores and evals are never read.

CredentialsA Langfuse project’s public and secret key
Langfuse versionCloud, or self-hosted v4 and newer
HostLangfuse Cloud US by default. Set LANGFUSE_BASE_URL for the EU region or your own instance

Add the keys to the .env you created during the shared setup.

.env
METERGRAPH_APP_TOKEN=<your ingest key>
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
# LANGFUSE_BASE_URL=https://cloud.langfuse.com # EU region, or your own host

Both keys can also be passed as --langfuse-public-key and --langfuse-secret-key, but the .env route keeps them off the process list.

  1. Langfuse’s trace name is the closest thing it has to a workflow name, and tags are the usual way a project separates environments. Work out which names and tags identify the traffic you want, and how far back to go.

  2. metergraphrelay pull langfuse --trace-name support-bot --tag prod \
    --since 2026-08-01T00:00:00Z --until 2026-08-08T00:00:00Z \
    --output langfuse.jsonl
    SelectorMeaning
    --trace-nameThe Langfuse trace name. Repeatable, and any of the names matches
    --tagA trace tag. Repeatable, and all of the tags must be present
    --environmentA single Langfuse environment value
    --since / --untilBound the observation’s start time. --since is inclusive, --until is exclusive and defaults to the moment the command started
    -n, --countCaps observations, never traces. Defaults to 100
    --routeOverrides the route on every row. Not a selector

    With no selectors at all you get the latest 100 GENERATION observations in the project.

  3. head -n 2 langfuse.jsonl
    metergraphrelay push langfuse.jsonl
  4. Open Traces in Metergraph. The route should read as your Langfuse trace name. If every row shows something else, pass --route and pull again.

metergraphrelay sync langfuse --source-scope support-bot-prod \
--initial-since 2026-08-01T00:00:00Z --trace-name support-bot --tag prod

Sync takes no --since, --until or -n: the server picks the window. It takes the same --trace-name, --tag and --environment selectors as pull, plus --source-scope, --initial-since, --max-window-seconds, --route and --allow-skipped.

Give each selector set its own --source-scope, and never change one once it has run. The full contract, including windows, overlap, leases and exit codes, is on How ongoing sync works.

FieldWhere it comes from
RouteThe Langfuse trace name. If the trace has none, the generation’s own name. --route overrides both
TimestampThe observation’s startTime
Provider and modelInferred from the observation’s model field
Input tokensThe named input total plus every other input bucket Langfuse reported, so it is the whole prompt
Output tokensThe same rollup on the output side
Cache reads, cache writes, reasoningLangfuse’s own buckets, wherever the integration recorded them
CostLangfuse’s totalCost
Statuserror when the observation’s level is ERROR, otherwise success
Error typeThe observation’s statusMessage
ContentInput and output, copied verbatim
Trace, span and parent spanThe Langfuse trace id, observation id and parent observation id
SessionThe observation’s sessionId
EnvironmentThe observation’s environment
TagsLangfuse trace tags, under langfuse_tags
  • Latency. The relay reads the observation’s start time only, so an imported Langfuse row has no latency_ms. This is the one supported source where that is true.
  • Tool calls and tool names.
  • Function attribution, streaming detail, outcomes and repository identity, as on every import path.
  • Spans, events, scores and evals, which are never read.
SymptomLikely causeWhat to do
A self-hosted Langfuse rejects the requestLangfuse older than v4Upgrade. The relay needs the v2 Observations API
Cache or reasoning columns are emptyThe integration never recorded those bucketsNothing to fix. The totals are still right
Every route is the generation name rather than a workflowThe traces carry no namePass --route
A pull returns 0 rows just after a runLangfuse Cloud has not made the observations readable yetWait, then rerun