Skip to content

Commit b2e4a56

Browse files
committed
feat(node): Auto-detect ai module in CJS
Especially for next.js, this should work to avoid manual setup.
1 parent 65310d5 commit b2e4a56

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

packages/node/src/integrations/modules.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { existsSync, readFileSync } from 'node:fs';
22
import { dirname, join } from 'node:path';
33
import type { IntegrationFn } from '@sentry/core';
4-
import { defineIntegration, logger } from '@sentry/core';
4+
import { logger } from '@sentry/core';
55
import { DEBUG_BUILD } from '../debug-build';
66
import { isCjs } from '../utils/commonjs';
77

@@ -31,6 +31,7 @@ const _modulesIntegration = (() => {
3131

3232
return event;
3333
},
34+
getModules: _getModules,
3435
};
3536
}) satisfies IntegrationFn;
3637

@@ -39,7 +40,7 @@ const _modulesIntegration = (() => {
3940
*
4041
* Only works in CommonJS (CJS) environments.
4142
*/
42-
export const modulesIntegration = defineIntegration(_modulesIntegration);
43+
export const modulesIntegration = _modulesIntegration;
4344

4445
/** Extract information about paths */
4546
function getPaths(): string[] {

packages/node/src/integrations/tracing/vercelai/index.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/* eslint-disable @typescript-eslint/no-dynamic-delete */
22
/* eslint-disable complexity */
3-
import type { IntegrationFn } from '@sentry/core';
3+
import type { Client, IntegrationFn } from '@sentry/core';
44
import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, spanToJSON } from '@sentry/core';
55
import { generateInstrumentOnce } from '../../../otel/instrument';
66
import { addOriginToSpan } from '../../../utils/addOriginToSpan';
7+
import type { modulesIntegration } from '../../modules';
78
import {
89
AI_MODEL_ID_ATTRIBUTE,
910
AI_MODEL_PROVIDER_ATTRIBUTE,
@@ -23,6 +24,15 @@ import type { VercelAiOptions } from './types';
2324

2425
export const instrumentVercelAi = generateInstrumentOnce(INTEGRATION_NAME, () => new SentryVercelAiInstrumentation({}));
2526

27+
/**
28+
* Determines if the integration should be forced based on environment and package availability.
29+
* Returns true if the 'ai' package is available.
30+
*/
31+
function shouldForceIntegration(client: Client): boolean {
32+
const modules = client.getIntegrationByName<ReturnType<typeof modulesIntegration>>('Modules');
33+
return !!modules?.getModules?.()?.ai;
34+
}
35+
2636
const _vercelAIIntegration = ((options: VercelAiOptions = {}) => {
2737
let instrumentation: undefined | SentryVercelAiInstrumentation;
2838

@@ -190,7 +200,11 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => {
190200
});
191201
}
192202

193-
if (options.force) {
203+
// Auto-detect if we should force the integration when running with 'ai' package available
204+
// Note that this can only be detected if the 'Modules' integration is available, and running in CJS mode
205+
const shouldForce = options.force ?? shouldForceIntegration(client);
206+
207+
if (shouldForce) {
194208
registerProcessors();
195209
} else {
196210
instrumentation?.callWhenPatched(registerProcessors);
@@ -213,6 +227,9 @@ const _vercelAIIntegration = ((options: VercelAiOptions = {}) => {
213227
* });
214228
* ```
215229
*
230+
* The integration automatically detects when to force registration in CommonJS environments
231+
* when the 'ai' package is available. You can still manually set the `force` option if needed.
232+
*
216233
* By default this integration adds tracing support to all `ai` function calls. If you need to disable
217234
* collecting spans for a specific call, you can do so by setting `experimental_telemetry.isEnabled` to
218235
* `false` in the first argument of the function call.

0 commit comments

Comments
 (0)