Skip to content

docs(sdk): expand JS/TS v3 β†’ v4 migration guide#3129

Open
Sajith15 wants to merge 1 commit into
langfuse:mainfrom
Sajith15:docs/js-sdk-v3-to-v4-migration-guide
Open

docs(sdk): expand JS/TS v3 β†’ v4 migration guide#3129
Sajith15 wants to merge 1 commit into
langfuse:mainfrom
Sajith15:docs/js-sdk-v3-to-v4-migration-guide

Conversation

@Sajith15

@Sajith15 Sajith15 commented Jun 17, 2026

Copy link
Copy Markdown

Expands the JS/TS v3 β†’ v4 upgrade guide with before/after examples, shutdown/flushing, Anthropic + generic OTel instrumentation, platform-specific notes (Next.js edge, Cloudflare Workers, self-hosted minimums), and a migration checklist.

Addresses https://github.com/orgs/langfuse/discussions/14155 (approved for contribution in comment 17336507).

Greptile Summary

This PR expands the JS/TS v3 β†’ v4 migration guide with before/after code examples, a shutdown/flushing section, Anthropic and generic OTel instrumentation patterns, platform-specific notes (Next.js edge, Cloudflare Workers, self-hosted versions), and a migration checklist.

  • The new sections are well-structured and cover the most common migration pain points; the before/after tables and code blocks significantly improve the guide's usability.
  • One stray XML close-tag pair (</content> / </invoke>) was accidentally appended after checklist item 9 and will break MDX rendering.
  • The Anthropic instrumentation snippet both calls manuallyInstrument and passes the same object to the instrumentations array, which may cause double-wrapping; and the Cloudflare Workers snippet is missing the NodeSDK wiring and has the critical ctx.waitUntil line commented out.

Confidence Score: 4/5

The guide is a documentation-only change with no runtime code. The stray XML tags at the end of the file will break the page render and must be removed before merging.

The MDX file contains two spurious XML close-tags immediately after checklist item 9 that will cause the page to fail to render or produce visible broken markup in production docs. The Anthropic snippet may also instruct users to double-register an instrumentation object, and the Cloudflare Workers snippet is missing the NodeSDK setup with the flush call commented out.

content/docs/observability/sdk/upgrade-path/js-v3-to-v4.mdx β€” specifically the end of the file (stray XML tags) and the Anthropic/Cloudflare code snippets.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[v3 single langfuse package] --> B{Which features?}
    B --> |Tracing| C[langfuse/tracing + langfuse/otel]
    B --> |Prompts / Scores / Datasets| D[langfuse/client - LangfuseClient]
    B --> |OpenAI| E[langfuse/openai - observeOpenAI]
    B --> |LangChain| F[langfuse/langchain - CallbackHandler]
    B --> |Vercel AI SDK| G[langfuse/otel - LangfuseSpanProcessor]
    B --> |Anthropic| H[OpenInference AnthropicInstrumentation + langfuse/otel]
    C --> I[instrumentation.ts - NodeSDK + LangfuseSpanProcessor]
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J[sdk.start at app entry point]
    J --> K[Traces exported to Langfuse via OTel]
    J --> L[Shutdown via sdk.shutdown or langfuseSpanProcessor.forceFlush]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[v3 single langfuse package] --> B{Which features?}
    B --> |Tracing| C[langfuse/tracing + langfuse/otel]
    B --> |Prompts / Scores / Datasets| D[langfuse/client - LangfuseClient]
    B --> |OpenAI| E[langfuse/openai - observeOpenAI]
    B --> |LangChain| F[langfuse/langchain - CallbackHandler]
    B --> |Vercel AI SDK| G[langfuse/otel - LangfuseSpanProcessor]
    B --> |Anthropic| H[OpenInference AnthropicInstrumentation + langfuse/otel]
    C --> I[instrumentation.ts - NodeSDK + LangfuseSpanProcessor]
    E --> I
    F --> I
    G --> I
    H --> I
    I --> J[sdk.start at app entry point]
    J --> K[Traces exported to Langfuse via OTel]
    J --> L[Shutdown via sdk.shutdown or langfuseSpanProcessor.forceFlush]
Loading
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
content/docs/observability/sdk/upgrade-path/js-v3-to-v4.mdx:411-413
Stray XML close-tags leaked into the end of the file. The lines `</content>` and `</invoke>` appear after checklist item 9 β€” they look like tool-output wrapper tags that were accidentally included when copying content. MDX will try to parse them as JSX/HTML elements, which will either break the page render or produce visible garbage in the browser.

```suggestion
9. If self-hosting, confirm your platform version meets the [minimum requirements](#self-hosted-minimum-versions).
```

### Issue 2 of 3
content/docs/observability/sdk/upgrade-path/js-v3-to-v4.mdx:285-293
**Anthropic: double-instrumentation risk**

`instrumentation.manuallyInstrument(Anthropic)` is called before `sdk.start()`, and the same `instrumentation` object is also passed in the `instrumentations` array. When `NodeSDK.start()` runs it calls `enable()` on every instrumentation in that array, which may wrap the Anthropic module a second time, producing duplicate spans.

The common OpenInference pattern for CJS is to pass the instrumentation to the `instrumentations` array only and let the SDK handle patching. `manuallyInstrument` is typically used *instead of* the array (e.g., for ESM where auto-patching is unreliable). Could you confirm which combination is correct for `@arizeai/openinference-instrumentation-anthropic` and update the snippet accordingly?

### Issue 3 of 3
content/docs/observability/sdk/upgrade-path/js-v3-to-v4.mdx:381-390
**Cloudflare Workers snippet is incomplete**

The snippet creates a `LangfuseSpanProcessor` but omits the surrounding `NodeSDK` setup (`new NodeSDK({ spanProcessors: [langfuseSpanProcessor] })` / `sdk.start()`). Without it, the processor is never wired to an active tracer provider and no spans will be exported. The `ctx.waitUntil(...)` call is also commented out, so a reader who copy-pastes the example will silently drop all traces. Consider showing the full setup (processor creation β†’ NodeSDK β†’ `sdk.start()` β†’ `ctx.waitUntil(langfuseSpanProcessor.forceFlush())`) so the Cloudflare pattern is self-contained.

Reviews (1): Last reviewed commit: "docs(sdk): expand JS/TS v3 β†’ v4 migratio..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Addresses langfuse/langfuse discussion #14155 by filling the gaps called
out in the migration documentation proposal.

Adds to the existing JS/TS v3 β†’ v4 upgrade guide:
- Overview with a v3 β†’ v4 package mapping table
- Installation before/after
- Initialization before/after (single Langfuse client β†’ OTel NodeSDK +
  LangfuseSpanProcessor in instrumentation.ts)
- Tracing before/after with a method-rename table
  (langfuse.trace/span/generation β†’ startObservation/startActiveObservation)
- Shutdown and flushing (shutdownAsync/flushAsync β†’ sdk.shutdown /
  langfuseSpanProcessor.forceFlush)
- Scoring before/after
- Anthropic SDK via OpenInference instrumentation and a generic
  "any OpenTelemetry instrumentation" section (covers LlamaIndexTS, etc.)
- Platform-specific notes: Next.js edge runtime (crypto/Node APIs),
  Cloudflare Workers, self-hosted minimum versions
- Migration checklist

All code samples and version requirements are grounded in the existing
SDK overview, instrumentation, and integration docs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This pull request is from a fork β€” automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@vercel

vercel Bot commented Jun 17, 2026

Copy link
Copy Markdown

@Sajith15 is attempting to deploy a commit to the langfuse Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 17, 2026
@CLAassistant

CLAassistant commented Jun 17, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@dosubot dosubot Bot added the documentation Improvements or additions to documentation label Jun 17, 2026
Comment on lines +285 to +293
const instrumentation = new AnthropicInstrumentation();
instrumentation.manuallyInstrument(Anthropic);

export const langfuseSpanProcessor = new LangfuseSpanProcessor();

export const sdk = new NodeSDK({
spanProcessors: [langfuseSpanProcessor],
instrumentations: [instrumentation],
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Anthropic: double-instrumentation risk

instrumentation.manuallyInstrument(Anthropic) is called before sdk.start(), and the same instrumentation object is also passed in the instrumentations array. When NodeSDK.start() runs it calls enable() on every instrumentation in that array, which may wrap the Anthropic module a second time, producing duplicate spans.

The common OpenInference pattern for CJS is to pass the instrumentation to the instrumentations array only and let the SDK handle patching. manuallyInstrument is typically used instead of the array (e.g., for ESM where auto-patching is unreliable). Could you confirm which combination is correct for @arizeai/openinference-instrumentation-anthropic and update the snippet accordingly?

Prompt To Fix With AI
This is a comment left during a code review.
Path: content/docs/observability/sdk/upgrade-path/js-v3-to-v4.mdx
Line: 285-293

Comment:
**Anthropic: double-instrumentation risk**

`instrumentation.manuallyInstrument(Anthropic)` is called before `sdk.start()`, and the same `instrumentation` object is also passed in the `instrumentations` array. When `NodeSDK.start()` runs it calls `enable()` on every instrumentation in that array, which may wrap the Anthropic module a second time, producing duplicate spans.

The common OpenInference pattern for CJS is to pass the instrumentation to the `instrumentations` array only and let the SDK handle patching. `manuallyInstrument` is typically used *instead of* the array (e.g., for ESM where auto-patching is unreliable). Could you confirm which combination is correct for `@arizeai/openinference-instrumentation-anthropic` and update the snippet accordingly?

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +381 to 390
```typescript /exportMode: "immediate"/ /forceFlush/
import { LangfuseSpanProcessor } from "@langfuse/otel";

await langfuse.score.create({
traceId: "trace_id_here",
name: "accuracy",
value: 0.9,
export const langfuseSpanProcessor = new LangfuseSpanProcessor({
exportMode: "immediate",
});

// In your fetch handler, keep the worker alive until the flush completes:
// ctx.waitUntil(langfuseSpanProcessor.forceFlush());
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Cloudflare Workers snippet is incomplete

The snippet creates a LangfuseSpanProcessor but omits the surrounding NodeSDK setup (new NodeSDK({ spanProcessors: [langfuseSpanProcessor] }) / sdk.start()). Without it, the processor is never wired to an active tracer provider and no spans will be exported. The ctx.waitUntil(...) call is also commented out, so a reader who copy-pastes the example will silently drop all traces. Consider showing the full setup (processor creation β†’ NodeSDK β†’ sdk.start() β†’ ctx.waitUntil(langfuseSpanProcessor.forceFlush())) so the Cloudflare pattern is self-contained.

Prompt To Fix With AI
This is a comment left during a code review.
Path: content/docs/observability/sdk/upgrade-path/js-v3-to-v4.mdx
Line: 381-390

Comment:
**Cloudflare Workers snippet is incomplete**

The snippet creates a `LangfuseSpanProcessor` but omits the surrounding `NodeSDK` setup (`new NodeSDK({ spanProcessors: [langfuseSpanProcessor] })` / `sdk.start()`). Without it, the processor is never wired to an active tracer provider and no spans will be exported. The `ctx.waitUntil(...)` call is also commented out, so a reader who copy-pastes the example will silently drop all traces. Consider showing the full setup (processor creation β†’ NodeSDK β†’ `sdk.start()` β†’ `ctx.waitUntil(langfuseSpanProcessor.forceFlush())`) so the Cloudflare pattern is self-contained.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants