feat(server-utils): Rewrite SentryLangChainInstrumentation to orchestrion#22266
feat(server-utils): Rewrite SentryLangChainInstrumentation to orchestrion#22266logaretm wants to merge 4 commits into
SentryLangChainInstrumentation to orchestrion#22266Conversation
size-limit report 📦
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6abf5e8. Configure here.
| diagnosticsChannel.tracingChannel<EmbeddingsChannelContext>(channelName), | ||
| data => createEmbeddingsSpan(data, options), | ||
| { captureError: () => ({ mechanism: { handled: false, type: 'auto.ai.langchain' } }) }, | ||
| ); |
There was a problem hiding this comment.
Embedding errors double-reported
Medium Severity
The orchestrion LangChain embeddings binding enables captureError on bindTracingChannelToSpan, so rejected embedding calls call captureException while the underlying LangChain error still propagates to the caller. That can produce duplicate Sentry error events alongside the global unhandled-rejection path, unlike other orchestrion gen-AI channel integrations that omit captureError.
Triggered by project rule: PR Review Guidelines for Cursor Bot
Reviewed by Cursor Bugbot for commit 6abf5e8. Configure here.
| ); | ||
|
|
||
| // Embeddings have no shared concrete method on the base class (each provider implements | ||
| // `embedQuery`/`embedDocuments`), so they're hooked per provider. Only `@langchain/openai` is wired |
There was a problem hiding this comment.
m: do we also only support openai in the otel path?
There was a problem hiding this comment.
Good catch, I wasn't sure how to do the others since unlike RITM/IITM we need exact matchers for the other providers and also need to check their implementations as it seems like not all 6 providers have the same capabilities.
Also some inherit from one another like Google's so it would cause double instrumentation. I had a clanker do it just now and document these cases.
9c28a7a to
25b5c5c
Compare
Rewrites the LangChain integration to a diagnostics-channel listener instead of `InstrumentationBase`, with orchestrion injecting the channels. Chat models are hooked once on `@langchain/core`'s `BaseChatModel` (`invoke` + `_streamIterator`), which every provider class inherits, so a single module covers all providers. The listener injects the Sentry callback handler into the call options, and LangChain's own callback dispatch creates the spans exactly as before, so the span output is identical. Embeddings have no shared base method, so they're hooked per provider (`@langchain/openai` for now) and get their span via `bindTracingChannelToSpan`, reusing the same core span builder as the OTel path. The OTel path stays as the fallback when orchestrion isn't injected. The existing node-integration suite runs against both paths under `INJECT_ORCHESTRION`, proving parity for langchain v0.3 and v1.
The OTel path covered 6 chat provider packages; chat is already handled by the single @langchain/core BaseChatModel hook. For embeddings (the per-package surface), wire the packages that ship an Embeddings subclass: openai, google-genai, mistralai, and google-vertexai (whose methods live on the shared @langchain/google-common base). anthropic and groq are chat-only. The embeddings channel list is derived from the provider list so adding a provider is a single edit.
…sted duplicate span
25b5c5c to
e90583e
Compare


Rewrites the LangChain integration to a
node:diagnostics_channellistener instead ofInstrumentationBase, with orchestrion injecting the channels. Follows the OpenAI/Anthropic/dataloader pattern; the vendored OTel path stays as the fallback when orchestrion isn't injected.Some decisions due to some differences with other integrations:
auto.ai.langchain(spans come from the shared core handler/builder, not the subscriber). The dual-mode test still catches broken selectors: under orchestrion the OTel integration is filtered out, so wrong selectors yield zero spans.embedQuery/embedDocumentscall the SDK internally.@langchain/corerange>=0.1.0 <2.0.0covers langchain v0.3 and v1.closes #20915