From abe877b05cb7577c073c49fe7eeb3aff27fcf7fe Mon Sep 17 00:00:00 2001 From: Nicolas Hrubec Date: Mon, 3 Aug 2026 16:00:32 +0200 Subject: [PATCH] ref(langchain)!: Move LangChain and LangGraph integrations to `@sentry/server-utils` Move the LangChain and LangGraph gen-ai instrumentation from `@sentry/core` to `@sentry/server-utils/src/ai/{langchain,langgraph}`, consuming the shared `ai/core` base. The public helpers (`createLangChainCallbackHandler`, `instrumentLangChainEmbeddings`, `instrumentStateGraph`, `instrumentStateGraphCompile`, `instrumentCreateReactAgent`) are re-exported from `@sentry/server-utils` by node/cloudflare/vercel-edge, so the platform SDK public API is unchanged. LangChain and LangGraph move together because core's LangGraph imports functions and types from LangChain (`createLangChainCallbackHandler`, `normalizeLangChainMessages`, `_INTERNAL_mergeLangChainCallbackHandler`, `BaseChatModel`/`LangChainMessage`); splitting them across PRs would require a temporary core->server-utils import (circular dep) or duplicated code. Moving both keeps LangGraph on relative `../langchain` imports. As with the other providers, `vercel-edge` re-exports from `@sentry/server-utils/no-diagnostic-channels` to keep the edge build free of `node:diagnostics_channel`. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../suites/tracing/langchain/test.ts | 2 +- .../tracing/langchain/scenario-chain.mjs | 3 +- .../suites/tracing/langchain/test.ts | 2 +- .../suites/tracing/langchain/v1/test.ts | 2 +- packages/cloudflare/src/index.ts | 8 +-- packages/core/.oxlintrc.json | 6 -- packages/core/src/server-exports.ts | 14 ----- packages/node/src/index.ts | 8 +-- packages/server-utils/src/ai/index.ts | 2 + .../src/ai}/langchain/constants.ts | 0 .../src/ai}/langchain/embeddings.ts | 15 +++-- .../src/ai}/langchain/index.ts | 15 +++-- .../src/ai}/langchain/types.ts | 0 .../src/ai}/langchain/utils.ts | 12 ++-- .../src/ai}/langgraph/constants.ts | 0 .../src/ai}/langgraph/index.ts | 17 +++--- .../src/ai}/langgraph/types.ts | 0 .../src/ai}/langgraph/utils.ts | 15 +++-- .../integrations/tracing-channel/langchain.ts | 17 +++--- .../integrations/tracing-channel/langgraph.ts | 20 +++---- .../lib/tracing/langchain-embeddings.test.ts | 55 +++++++++++-------- .../ai}/lib/tracing/langchain-utils.test.ts | 4 +- .../test/ai}/lib/tracing/langgraph.test.ts | 2 +- .../ai}/lib/utils/langgraph-utils.test.ts | 2 +- packages/vercel-edge/src/index.ts | 6 +- 25 files changed, 110 insertions(+), 117 deletions(-) rename packages/{core/src/tracing => server-utils/src/ai}/langchain/constants.ts (100%) rename packages/{core/src/tracing => server-utils/src/ai}/langchain/embeddings.ts (93%) rename packages/{core/src/tracing => server-utils/src/ai}/langchain/index.ts (96%) rename packages/{core/src/tracing => server-utils/src/ai}/langchain/types.ts (100%) rename packages/{core/src/tracing => server-utils/src/ai}/langchain/utils.ts (98%) rename packages/{core/src/tracing => server-utils/src/ai}/langgraph/constants.ts (100%) rename packages/{core/src/tracing => server-utils/src/ai}/langgraph/index.ts (96%) rename packages/{core/src/tracing => server-utils/src/ai}/langgraph/types.ts (100%) rename packages/{core/src/tracing => server-utils/src/ai}/langgraph/utils.ts (96%) rename packages/{core/test => server-utils/test/ai}/lib/tracing/langchain-embeddings.test.ts (80%) rename packages/{core/test => server-utils/test/ai}/lib/tracing/langchain-utils.test.ts (98%) rename packages/{core/test => server-utils/test/ai}/lib/tracing/langgraph.test.ts (96%) rename packages/{core/test => server-utils/test/ai}/lib/utils/langgraph-utils.test.ts (97%) diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts index 09fabdefb3d3..c8860321780e 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts @@ -12,7 +12,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../../../../../packages/server-utils/src/ai/core/gen-ai-attributes'; import { createRunner } from '../../../runner'; // This test runs the `@langchain/openai` model (backed by the diff --git a/dev-packages/node-integration-tests/suites/tracing/langchain/scenario-chain.mjs b/dev-packages/node-integration-tests/suites/tracing/langchain/scenario-chain.mjs index b8394be972df..3bd67b163572 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langchain/scenario-chain.mjs +++ b/dev-packages/node-integration-tests/suites/tracing/langchain/scenario-chain.mjs @@ -1,6 +1,5 @@ import { ChatAnthropic } from '@langchain/anthropic'; import { RunnableLambda, RunnableSequence } from '@langchain/core/runnables'; -import { createLangChainCallbackHandler } from '@sentry/core'; import * as Sentry from '@sentry/node'; import express from 'express'; @@ -51,7 +50,7 @@ async function run() { const chain = RunnableSequence.from([formatStep, model, parseStep]); - const handler = createLangChainCallbackHandler(); + const handler = Sentry.createLangChainCallbackHandler(); await chain.invoke({ topic: 'weather' }, { callbacks: [handler] }); }); diff --git a/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts b/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts index e03769f462c4..32d30cdef4e9 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langchain/test.ts @@ -21,7 +21,7 @@ import { GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE, -} from '../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +} from '../../../../../packages/server-utils/src/ai/core/gen-ai-attributes'; import { getStringAttributeValue } from '../../../utils'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../utils/runner'; import { createEsmTests } from '../../../utils/runner/createEsmAndCjsTests'; diff --git a/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts b/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts index be472373c19e..9a9a7a8f75b6 100644 --- a/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts +++ b/dev-packages/node-integration-tests/suites/tracing/langchain/v1/test.ts @@ -16,7 +16,7 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../../../../../../packages/core/src/tracing/ai/gen-ai-attributes'; +import { GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../../../../../../packages/server-utils/src/ai/core/gen-ai-attributes'; import { conditionalTest, getStringAttributeValue } from '../../../../utils'; import { cleanupChildProcesses, createEsmAndCjsTests } from '../../../../utils/runner'; import { createEsmTests } from '../../../../utils/runner/createEsmAndCjsTests'; diff --git a/packages/cloudflare/src/index.ts b/packages/cloudflare/src/index.ts index bc27ec6e5d59..2a0a3050f8e3 100644 --- a/packages/cloudflare/src/index.ts +++ b/packages/cloudflare/src/index.ts @@ -101,16 +101,12 @@ export { wrapMcpServerWithSentry, consoleLoggingIntegration, createConsolaReporter, - createLangChainCallbackHandler, - instrumentLangChainEmbeddings, featureFlagsIntegration, growthbookIntegration, logger, metrics, withStreamedSpan, spanStreamingIntegration, - instrumentStateGraph, - instrumentCreateReactAgent, } from '@sentry/core'; export { withSentry } from './withSentry'; @@ -131,6 +127,10 @@ export { instrumentAnthropicAiClient, instrumentGoogleGenAIClient, instrumentWorkersAiClient, + createLangChainCallbackHandler, + instrumentLangChainEmbeddings, + instrumentStateGraph, + instrumentCreateReactAgent, } from '@sentry/server-utils'; // eslint-disable-next-line typescript/no-deprecated diff --git a/packages/core/.oxlintrc.json b/packages/core/.oxlintrc.json index 0ccd57100a48..227cf5b770b9 100644 --- a/packages/core/.oxlintrc.json +++ b/packages/core/.oxlintrc.json @@ -16,12 +16,6 @@ "rules": { "sdk/no-unsafe-random-apis": "off" } - }, - { - "files": ["src/tracing/langchain/utils.ts"], - "rules": { - "max-lines": "off" - } } ], "ignorePatterns": ["rollup.npm.config.mjs"] diff --git a/packages/core/src/server-exports.ts b/packages/core/src/server-exports.ts index 79ec35d49969..fc6b53710cf9 100644 --- a/packages/core/src/server-exports.ts +++ b/packages/core/src/server-exports.ts @@ -60,17 +60,3 @@ export { addVercelAiProcessors, getProviderMetadataAttributes } from './tracing/ export { getTruncatedJsonString, shouldEnableTruncation, resolveAIRecordingOptions } from './tracing/ai/utils'; export { _INTERNAL_getSpanContextForToolCallId, _INTERNAL_cleanupToolCallSpanContext } from './tracing/vercel-ai/utils'; export { toolCallSpanContextMap as _INTERNAL_toolCallSpanContextMap } from './tracing/vercel-ai/constants'; -export { createLangChainCallbackHandler, instrumentLangChainEmbeddings } from './tracing/langchain'; -export { _INTERNAL_getLangChainEmbeddingsSpanOptions } from './tracing/langchain/embeddings'; -export { _INTERNAL_mergeLangChainCallbackHandler } from './tracing/langchain/utils'; -export { LANGCHAIN_INTEGRATION_NAME } from './tracing/langchain/constants'; -export type { LangChainOptions, LangChainIntegration } from './tracing/langchain/types'; -export { - instrumentStateGraphCompile, - instrumentCreateReactAgent, - instrumentStateGraph, - instrumentCompiledGraphInvoke, -} from './tracing/langgraph'; -export { wrapToolsWithSpans, extractLLMFromParams, extractAgentNameFromParams } from './tracing/langgraph/utils'; -export { LANGGRAPH_INTEGRATION_NAME } from './tracing/langgraph/constants'; -export type { LangGraphOptions, LangGraphIntegration, CompiledGraph } from './tracing/langgraph/types'; diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 21b5de7685cd..997986bbb3a5 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -35,6 +35,10 @@ export { instrumentOpenAiClient, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, + createLangChainCallbackHandler, + instrumentLangChainEmbeddings, + instrumentStateGraph, + instrumentStateGraphCompile, } from '@sentry/server-utils'; export { setupHapiErrorHandler } from './integrations/tracing/hapi'; export { setupKoaErrorHandler } from './integrations/tracing/koa'; @@ -145,10 +149,6 @@ export { wrapMcpServerWithSentry, featureFlagsIntegration, spanStreamingIntegration, - createLangChainCallbackHandler, - instrumentLangChainEmbeddings, - instrumentStateGraph, - instrumentStateGraphCompile, } from '@sentry/core'; export type { diff --git a/packages/server-utils/src/ai/index.ts b/packages/server-utils/src/ai/index.ts index 9d1da2c0a107..769ab826e01d 100644 --- a/packages/server-utils/src/ai/index.ts +++ b/packages/server-utils/src/ai/index.ts @@ -8,3 +8,5 @@ export { instrumentOpenAiClient } from './openai'; export { instrumentAnthropicAiClient } from './anthropic-ai'; export { instrumentGoogleGenAIClient } from './google-genai'; export { instrumentWorkersAiClient } from './workers-ai'; +export { createLangChainCallbackHandler, instrumentLangChainEmbeddings } from './langchain'; +export { instrumentStateGraph, instrumentStateGraphCompile, instrumentCreateReactAgent } from './langgraph'; diff --git a/packages/core/src/tracing/langchain/constants.ts b/packages/server-utils/src/ai/langchain/constants.ts similarity index 100% rename from packages/core/src/tracing/langchain/constants.ts rename to packages/server-utils/src/ai/langchain/constants.ts diff --git a/packages/core/src/tracing/langchain/embeddings.ts b/packages/server-utils/src/ai/langchain/embeddings.ts similarity index 93% rename from packages/core/src/tracing/langchain/embeddings.ts rename to packages/server-utils/src/ai/langchain/embeddings.ts index 1ace6eaa4de2..6c8a095bd68d 100644 --- a/packages/core/src/tracing/langchain/embeddings.ts +++ b/packages/server-utils/src/ai/langchain/embeddings.ts @@ -1,8 +1,11 @@ /* eslint-disable typescript-eslint/no-deprecated */ -import { captureException } from '../../exports'; -import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; -import { startSpan } from '../../tracing/trace'; -import type { SpanAttributeValue } from '../../types/span'; +import { + captureException, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + startSpan, +} from '@sentry/core'; +import type { SpanAttributeValue } from '@sentry/core'; import { GEN_AI_EMBEDDINGS_INPUT, GEN_AI_OPERATION_NAME, @@ -13,8 +16,8 @@ import { GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, -} from '../ai/gen-ai-attributes'; -import { resolveAIRecordingOptions } from '../ai/utils'; +} from '../core/gen-ai-attributes'; +import { resolveAIRecordingOptions } from '../core/utils'; import { LANGCHAIN_ORIGIN } from './constants'; import type { LangChainOptions } from './types'; diff --git a/packages/core/src/tracing/langchain/index.ts b/packages/server-utils/src/ai/langchain/index.ts similarity index 96% rename from packages/core/src/tracing/langchain/index.ts rename to packages/server-utils/src/ai/langchain/index.ts index b6407692e49a..37b6f98b8b0a 100644 --- a/packages/core/src/tracing/langchain/index.ts +++ b/packages/server-utils/src/ai/langchain/index.ts @@ -1,10 +1,13 @@ /* eslint-disable typescript-eslint/no-deprecated */ /* eslint-disable max-lines */ -import { captureException } from '../../exports'; -import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; -import { SPAN_STATUS_ERROR } from '../../tracing'; -import { startSpanManual } from '../../tracing/trace'; -import type { Span, SpanAttributeValue } from '../../types/span'; +import { + captureException, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SPAN_STATUS_ERROR, + startSpanManual, +} from '@sentry/core'; +import type { Span, SpanAttributeValue } from '@sentry/core'; import { GEN_AI_OPERATION_NAME, GEN_AI_REQUEST_AVAILABLE_TOOLS, @@ -13,7 +16,7 @@ import { GEN_AI_TOOL_NAME, GEN_AI_TOOL_OUTPUT, } from '@sentry/conventions/attributes'; -import { resolveAIRecordingOptions, shouldEnableTruncation } from '../ai/utils'; +import { resolveAIRecordingOptions, shouldEnableTruncation } from '../core/utils'; import { LANGCHAIN_ORIGIN } from './constants'; import type { LangChainCallbackHandler, diff --git a/packages/core/src/tracing/langchain/types.ts b/packages/server-utils/src/ai/langchain/types.ts similarity index 100% rename from packages/core/src/tracing/langchain/types.ts rename to packages/server-utils/src/ai/langchain/types.ts diff --git a/packages/core/src/tracing/langchain/utils.ts b/packages/server-utils/src/ai/langchain/utils.ts similarity index 98% rename from packages/core/src/tracing/langchain/utils.ts rename to packages/server-utils/src/ai/langchain/utils.ts index a48dc2a536be..e380b0316ad7 100644 --- a/packages/core/src/tracing/langchain/utils.ts +++ b/packages/server-utils/src/ai/langchain/utils.ts @@ -1,7 +1,7 @@ +/* eslint-disable max-lines */ /* eslint-disable typescript-eslint/no-deprecated */ -import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; -import type { SpanAttributeValue } from '../../types/span'; -import { stringify } from '../../utils/string'; +import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, stringify } from '@sentry/core'; +import type { SpanAttributeValue } from '@sentry/core'; import { GEN_AI_AGENT_NAME, GEN_AI_INPUT_MESSAGES, @@ -25,9 +25,9 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_REQUEST_STREAM_ATTRIBUTE, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../ai/gen-ai-attributes'; -import { isContentMedia, stripInlineMediaFromSingleMessage } from '../ai/mediaStripping'; -import { extractSystemInstructions, getTruncatedJsonString } from '../ai/utils'; +import { GEN_AI_REQUEST_STREAM_ATTRIBUTE, GEN_AI_RESPONSE_STOP_REASON_ATTRIBUTE } from '../core/gen-ai-attributes'; +import { isContentMedia, stripInlineMediaFromSingleMessage } from '../core/mediaStripping'; +import { extractSystemInstructions, getTruncatedJsonString } from '../core/utils'; import { LANGCHAIN_ORIGIN, ROLE_MAP } from './constants'; import type { LangChainLLMResult, LangChainMessage, LangChainSerialized } from './types'; diff --git a/packages/core/src/tracing/langgraph/constants.ts b/packages/server-utils/src/ai/langgraph/constants.ts similarity index 100% rename from packages/core/src/tracing/langgraph/constants.ts rename to packages/server-utils/src/ai/langgraph/constants.ts diff --git a/packages/core/src/tracing/langgraph/index.ts b/packages/server-utils/src/ai/langgraph/index.ts similarity index 96% rename from packages/core/src/tracing/langgraph/index.ts rename to packages/server-utils/src/ai/langgraph/index.ts index 9a5963579990..3f4feeb5f2ca 100644 --- a/packages/core/src/tracing/langgraph/index.ts +++ b/packages/server-utils/src/ai/langgraph/index.ts @@ -1,7 +1,12 @@ /* eslint-disable typescript-eslint/no-deprecated */ -import { captureException } from '../../exports'; -import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; -import { SPAN_STATUS_ERROR } from '../../tracing'; +import { + captureException, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SPAN_STATUS_ERROR, + startSpan, + stringify, +} from '@sentry/core'; import { GEN_AI_AGENT_NAME, GEN_AI_CONVERSATION_ID, @@ -12,18 +17,16 @@ import { GEN_AI_REQUEST_MODEL, GEN_AI_SYSTEM_INSTRUCTIONS, } from '@sentry/conventions/attributes'; -import { GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE } from '../ai/gen-ai-attributes'; +import { GEN_AI_INVOKE_AGENT_OPERATION_ATTRIBUTE } from '../core/gen-ai-attributes'; import { extractSystemInstructions, getTruncatedJsonString, resolveAIRecordingOptions, shouldEnableTruncation, -} from '../ai/utils'; -import { stringify } from '../../utils/string'; +} from '../core/utils'; import { createLangChainCallbackHandler } from '../langchain'; import type { BaseChatModel, LangChainMessage } from '../langchain/types'; import { normalizeLangChainMessages } from '../langchain/utils'; -import { startSpan } from '../trace'; import { LANGGRAPH_ORIGIN } from './constants'; import type { CompiledGraph, LangGraphOptions } from './types'; import { diff --git a/packages/core/src/tracing/langgraph/types.ts b/packages/server-utils/src/ai/langgraph/types.ts similarity index 100% rename from packages/core/src/tracing/langgraph/types.ts rename to packages/server-utils/src/ai/langgraph/types.ts diff --git a/packages/core/src/tracing/langgraph/utils.ts b/packages/server-utils/src/ai/langgraph/utils.ts similarity index 96% rename from packages/core/src/tracing/langgraph/utils.ts rename to packages/server-utils/src/ai/langgraph/utils.ts index eb504e51bde7..07d1d0d0c2ba 100644 --- a/packages/core/src/tracing/langgraph/utils.ts +++ b/packages/server-utils/src/ai/langgraph/utils.ts @@ -1,8 +1,12 @@ /* eslint-disable typescript-eslint/no-deprecated */ -import { captureException } from '../../exports'; -import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../../semanticAttributes'; -import { SPAN_STATUS_ERROR } from '../../tracing'; -import type { Span, SpanAttributes } from '../../types/span'; +import { + captureException, + SEMANTIC_ATTRIBUTE_SENTRY_OP, + SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, + SPAN_STATUS_ERROR, + startSpan, +} from '@sentry/core'; +import type { Span, SpanAttributes } from '@sentry/core'; import { GEN_AI_AGENT_NAME, GEN_AI_OPERATION_NAME, @@ -19,10 +23,9 @@ import { GEN_AI_USAGE_OUTPUT_TOKENS, GEN_AI_USAGE_TOTAL_TOKENS, } from '@sentry/conventions/attributes'; -import { GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE, GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../ai/gen-ai-attributes'; +import { GEN_AI_EXECUTE_TOOL_OPERATION_ATTRIBUTE, GEN_AI_TOOL_CALL_ID_ATTRIBUTE } from '../core/gen-ai-attributes'; import type { BaseChatModel, LangChainMessage } from '../langchain/types'; import { normalizeLangChainMessages } from '../langchain/utils'; -import { startSpan } from '../trace'; import { LANGGRAPH_ORIGIN } from './constants'; import type { CompiledGraph, LangGraphOptions, LangGraphTool } from './types'; diff --git a/packages/server-utils/src/integrations/tracing-channel/langchain.ts b/packages/server-utils/src/integrations/tracing-channel/langchain.ts index e00a2977ed59..41c756266a2a 100644 --- a/packages/server-utils/src/integrations/tracing-channel/langchain.ts +++ b/packages/server-utils/src/integrations/tracing-channel/langchain.ts @@ -1,16 +1,13 @@ import * as diagnosticsChannel from 'node:diagnostics_channel'; -import type { IntegrationFn, LangChainOptions, Span } from '@sentry/core'; -import { - _INTERNAL_getLangChainEmbeddingsSpanOptions, - _INTERNAL_mergeLangChainCallbackHandler, - _INTERNAL_skipAiProviderWrapping, - createLangChainCallbackHandler, - defineIntegration, - LANGCHAIN_INTEGRATION_NAME, - startInactiveSpan, -} from '@sentry/core'; +import type { IntegrationFn, Span } from '@sentry/core'; +import { _INTERNAL_skipAiProviderWrapping, defineIntegration, startInactiveSpan } from '@sentry/core'; import { ANTHROPIC_AI_INTEGRATION_NAME } from '../../ai/anthropic-ai/constants'; import { GOOGLE_GENAI_INTEGRATION_NAME } from '../../ai/google-genai/constants'; +import { createLangChainCallbackHandler } from '../../ai/langchain'; +import { LANGCHAIN_INTEGRATION_NAME } from '../../ai/langchain/constants'; +import { _INTERNAL_getLangChainEmbeddingsSpanOptions } from '../../ai/langchain/embeddings'; +import type { LangChainOptions } from '../../ai/langchain/types'; +import { _INTERNAL_mergeLangChainCallbackHandler } from '../../ai/langchain/utils'; import { OPENAI_INTEGRATION_NAME } from '../../ai/openai/constants'; import { CHANNELS } from '../../orchestrion/channels'; import { langchainEmbeddingsChannels } from '../../orchestrion/config/langchain'; diff --git a/packages/server-utils/src/integrations/tracing-channel/langgraph.ts b/packages/server-utils/src/integrations/tracing-channel/langgraph.ts index 8ebb03020714..c3837b8dd8ea 100644 --- a/packages/server-utils/src/integrations/tracing-channel/langgraph.ts +++ b/packages/server-utils/src/integrations/tracing-channel/langgraph.ts @@ -1,16 +1,12 @@ import * as diagnosticsChannel from 'node:diagnostics_channel'; -import type { CompiledGraph, IntegrationFn, LangGraphOptions } from '@sentry/core'; -import { - createLangChainCallbackHandler, - debug, - defineIntegration, - extractAgentNameFromParams, - extractLLMFromParams, - instrumentCompiledGraphInvoke, - LANGGRAPH_INTEGRATION_NAME, - resolveAIRecordingOptions, - wrapToolsWithSpans, -} from '@sentry/core'; +import type { IntegrationFn } from '@sentry/core'; +import { debug, defineIntegration } from '@sentry/core'; +import { resolveAIRecordingOptions } from '../../ai/core/utils'; +import { createLangChainCallbackHandler } from '../../ai/langchain'; +import { instrumentCompiledGraphInvoke } from '../../ai/langgraph'; +import { LANGGRAPH_INTEGRATION_NAME } from '../../ai/langgraph/constants'; +import type { CompiledGraph, LangGraphOptions } from '../../ai/langgraph/types'; +import { extractAgentNameFromParams, extractLLMFromParams, wrapToolsWithSpans } from '../../ai/langgraph/utils'; import { DEBUG_BUILD } from '../../debug-build'; import { CHANNELS } from '../../orchestrion/channels'; import { langgraphModuleNames } from '../../orchestrion/config/langgraph'; diff --git a/packages/core/test/lib/tracing/langchain-embeddings.test.ts b/packages/server-utils/test/ai/lib/tracing/langchain-embeddings.test.ts similarity index 80% rename from packages/core/test/lib/tracing/langchain-embeddings.test.ts rename to packages/server-utils/test/ai/lib/tracing/langchain-embeddings.test.ts index 0c9651ea6ad1..b820869743d1 100644 --- a/packages/core/test/lib/tracing/langchain-embeddings.test.ts +++ b/packages/server-utils/test/ai/lib/tracing/langchain-embeddings.test.ts @@ -1,4 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; +import type * as AiCoreUtils from '../../../../src/ai/core/utils'; +import type * as SentryCore from '@sentry/core'; import { GEN_AI_EMBEDDINGS_INPUT, GEN_AI_OPERATION_NAME, @@ -9,33 +11,38 @@ import { GEN_AI_EMBEDDINGS_OPERATION_ATTRIBUTE, GEN_AI_REQUEST_DIMENSIONS_ATTRIBUTE, GEN_AI_REQUEST_ENCODING_FORMAT_ATTRIBUTE, -} from '../../../src/tracing/ai/gen-ai-attributes'; -import { instrumentEmbeddingMethod, instrumentLangChainEmbeddings } from '../../../src/tracing/langchain/embeddings'; - -vi.mock('../../../src/tracing/ai/utils', () => ({ - resolveAIRecordingOptions: (options: { recordInputs?: boolean; recordOutputs?: boolean } = {}) => ({ - recordInputs: options.recordInputs ?? false, - recordOutputs: options.recordOutputs ?? false, - }), -})); +} from '../../../../src/ai/core/gen-ai-attributes'; +import { instrumentEmbeddingMethod, instrumentLangChainEmbeddings } from '../../../../src/ai/langchain/embeddings'; + +vi.mock('../../../../src/ai/core/utils', async importOriginal => { + const actual = (await importOriginal()) as typeof AiCoreUtils; + return { + ...actual, + resolveAIRecordingOptions: (options: { recordInputs?: boolean; recordOutputs?: boolean } = {}) => ({ + recordInputs: options.recordInputs ?? false, + recordOutputs: options.recordOutputs ?? false, + }), + }; +}); let capturedSpanConfig: { name: string; op: string; attributes: Record } | undefined; -vi.mock('../../../src/tracing/trace', () => ({ - startSpan: ( - config: { name: string; op: string; attributes: Record }, - callback: (span: unknown) => unknown, - ) => { - capturedSpanConfig = config; - return callback({ setAttribute: vi.fn() }); - }, -})); - -import { captureException } from '../../../src/exports'; - -vi.mock('../../../src/exports', () => ({ - captureException: vi.fn(), -})); +vi.mock('@sentry/core', async importOriginal => { + const actual = (await importOriginal()) as typeof SentryCore; + return { + ...actual, + startSpan: ( + config: { name: string; op: string; attributes: Record }, + callback: (span: unknown) => unknown, + ) => { + capturedSpanConfig = config; + return callback({ setAttribute: vi.fn() }); + }, + captureException: vi.fn(), + }; +}); + +import { captureException } from '@sentry/core'; describe('instrumentEmbeddingMethod', () => { beforeEach(() => { diff --git a/packages/core/test/lib/tracing/langchain-utils.test.ts b/packages/server-utils/test/ai/lib/tracing/langchain-utils.test.ts similarity index 98% rename from packages/core/test/lib/tracing/langchain-utils.test.ts rename to packages/server-utils/test/ai/lib/tracing/langchain-utils.test.ts index cbfc384685cf..29eb1794e93a 100644 --- a/packages/core/test/lib/tracing/langchain-utils.test.ts +++ b/packages/server-utils/test/ai/lib/tracing/langchain-utils.test.ts @@ -1,11 +1,11 @@ import { describe, expect, it, vi } from 'vitest'; import { GEN_AI_INPUT_MESSAGES } from '@sentry/conventions/attributes'; -import type { LangChainMessage } from '../../../src/tracing/langchain/types'; +import type { LangChainMessage } from '../../../../src/ai/langchain/types'; import { _INTERNAL_mergeLangChainCallbackHandler, extractChatModelRequestAttributes, normalizeLangChainMessages, -} from '../../../src/tracing/langchain/utils'; +} from '../../../../src/ai/langchain/utils'; describe('normalizeLangChainMessages', () => { it('normalizes messages with _getType()', () => { diff --git a/packages/core/test/lib/tracing/langgraph.test.ts b/packages/server-utils/test/ai/lib/tracing/langgraph.test.ts similarity index 96% rename from packages/core/test/lib/tracing/langgraph.test.ts rename to packages/server-utils/test/ai/lib/tracing/langgraph.test.ts index b36f9b5afe63..b1f79c9d184c 100644 --- a/packages/core/test/lib/tracing/langgraph.test.ts +++ b/packages/server-utils/test/ai/lib/tracing/langgraph.test.ts @@ -3,7 +3,7 @@ import { instrumentCreateReactAgent, instrumentStateGraph, instrumentStateGraphCompile, -} from '../../../src/tracing/langgraph'; +} from '../../../../src/ai/langgraph'; describe('langgraph double-patch guard', () => { it('instrumentStateGraphCompile returns the same wrapper when applied twice', () => { diff --git a/packages/core/test/lib/utils/langgraph-utils.test.ts b/packages/server-utils/test/ai/lib/utils/langgraph-utils.test.ts similarity index 97% rename from packages/core/test/lib/utils/langgraph-utils.test.ts rename to packages/server-utils/test/ai/lib/utils/langgraph-utils.test.ts index b5943784b282..cba539ae6e3a 100644 --- a/packages/core/test/lib/utils/langgraph-utils.test.ts +++ b/packages/server-utils/test/ai/lib/utils/langgraph-utils.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { extractAgentNameFromParams, extractLLMFromParams } from '../../../src/tracing/langgraph/utils'; +import { extractAgentNameFromParams, extractLLMFromParams } from '../../../../src/ai/langgraph/utils'; describe('extractLLMFromParams', () => { it('returns null for empty or invalid args', () => { diff --git a/packages/vercel-edge/src/index.ts b/packages/vercel-edge/src/index.ts index f92158288162..c67b84ed1ff7 100644 --- a/packages/vercel-edge/src/index.ts +++ b/packages/vercel-edge/src/index.ts @@ -73,7 +73,6 @@ export { functionToStringIntegration, // eslint-disable-next-line typescript/no-deprecated inboundFiltersIntegration, - instrumentStateGraph, eventFiltersIntegration, linkedErrorsIntegration, requestDataIntegration, @@ -97,8 +96,6 @@ export { wrapMcpServerWithSentry, consoleLoggingIntegration, createConsolaReporter, - createLangChainCallbackHandler, - instrumentLangChainEmbeddings, featureFlagsIntegration, logger, metrics, @@ -109,6 +106,9 @@ export { instrumentOpenAiClient, instrumentAnthropicAiClient, instrumentGoogleGenAIClient, + createLangChainCallbackHandler, + instrumentLangChainEmbeddings, + instrumentStateGraph, } from '@sentry/server-utils/no-diagnostic-channels'; export { VercelEdgeClient } from './client';