Skip to content

feat(#126): migrate Langfuse to JS SDK v5 for the v4 observations model - #162

Merged
alexosugo merged 7 commits into
feat/126-langfuse-observabilityfrom
feat/langfuse-v4-migration
Oct 1, 2026
Merged

alexosugo merged 7 commits into
feat/126-langfuse-observabilityfrom
feat/langfuse-v4-migration

Conversation

@alexosugo

@alexosugo alexosugo commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Description

Stacked on #127: migrates the Langfuse tracing added there from the legacy langfuse v3 npm package to the OpenTelemetry-based JS SDK v5 (@langfuse/tracing, @langfuse/otel, @langfuse/client), targeting Langfuse's v4 observations-first data model. The legacy batch-ingestion API that v3 uses is removed from Langfuse Cloud on 2026-11-16.

  • src/observability now exposes withTrace, observeGeneration, scoreTrace, and shutdownLangfuse. Session id, tags, and metadata are propagated to every observation, so session and tag aggregations include generation cost.
  • The root observation carries the overall input/output; the deprecated trace-level input/output setters are not used.
  • Trace ids are generated per run instead of being derived from the PR number, so reprocessing a PR produces a distinct trace.
  • Generations record usageDetails on the API path and costDetails on the Claude CLI path.
  • Span export uses a 3s timeout; score requests use the @langfuse/client default of 60s (5.11.1 ignores its timeout option). Langfuse is shut down once per run, and flush failures only log a warning.
  • Tracing is off unless LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY are both set.
  • docs/observability.md is updated for the new API.

Verification:

  • tsc, lint, and unit tests (1133 passing) run locally.
  • One live pipeline run on the API path (OpenRouter), checked in Langfuse Cloud: the trace, session, tags, distill-outcome score, token usage, and inferred cost all arrived.
  • The Claude CLI path was not verified live here: an existing bug in the parser for the CLI's JSON output blocked it. feat(#126): trace research/dev runs and record code-gen model, usage and cost #163 fixes that parser.

Part of the #127 → #162 → #163 stack; merge after #127.

#126

Code review checklist

  • Readable: Concise, well named, follows the style guide, documented if necessary.
  • Tested: Unit and/or e2e where appropriate
  • Backwards compatible: Works with existing data and configuration or includes a migration. Any breaking changes documented in the release notes.

License

The software is provided under AGPL-3.0. Contributions to this project are accepted under the same license.

@sugat009 sugat009 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the migration. The v5 wiring is correct. I tested it against a local fake Langfuse.

Two items block the merge: index.ts:35 and index.ts:24. Both have one-click suggestions.

CI is green. With all the suggestions applied, 1023 tests pass locally.

Comment thread src/observability/index.ts
Comment thread test/observability/index.spec.ts
Comment thread src/observability/index.ts Outdated
Comment thread test/observability/index.spec.ts Outdated
Comment thread src/observability/index.ts Outdated
Comment thread docs/observability.md Outdated
Comment thread docs/observability.md Outdated
@alexosugo
alexosugo requested a review from sugat009 September 24, 2026 11:00

@sugat009 sugat009 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. All 7 round-1 points are fixed. I checked each one on 012d77e:

  • A failed span export now logs a warning, the score still goes out, and the run keeps its exit code (0, or 2 on a rate limit).
  • With no keys, or with one key only, nothing is sent.

Local gates pass: fresh npm ci, build, lint, validate-schema, and test:coverage with 1023 tests. The CI test job did not run on this head, because it runs only for PRs to main.

note (non-blocking): .env.example:66-67 sets placeholder keys (pk-lf-...). The README tells new developers to copy that file and edit only ANTHROPIC_API_KEY. The new key check then sees two keys, and tracing stays on with invalid keys. Commenting out those two lines would close this. The file is outside this diff, so I note it here.

Comment thread test/observability/index.spec.ts Outdated
alexosugo and others added 6 commits September 30, 2026 18:26
Replace langfuse@3 (legacy batch ingestion, removed on Langfuse Cloud
2026-11-16) with @langfuse/tracing, @langfuse/otel and @langfuse/client
over OpenTelemetry.

- withTrace propagates session id, tags and metadata to every
  observation, including generations, so session cost aggregates work
- overall input/output live on the root observation
- scores go through LangfuseClient; one shutdown flushes spans and scores
- metadata values are strings per the v5 propagation contract

Verified with a live API-path run: trace, session, score, token usage
and inferred cost all ingested.
Tracing now stays off when LANGFUSE_PUBLIC_KEY or LANGFUSE_SECRET_KEY is unset,
so spans with prompt text are not sent unauthenticated. shutdownLangfuse() logs
span and score flush failures instead of rejecting. The unused client timeout
is dropped and the docs now state the 60 s SDK default for scores.
Co-authored-by: Sugat Bajracharya <30311933+sugat009@users.noreply.github.com>
@alexosugo
alexosugo force-pushed the feat/langfuse-v4-migration branch from 987f66c to 5b7e01f Compare September 30, 2026 19:26
@alexosugo
alexosugo merged commit de9bd62 into main Oct 1, 2026
5 checks passed
@alexosugo
alexosugo deleted the feat/langfuse-v4-migration branch October 1, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants