Skip to content

Commit 301e032

Browse files
andreiborzamydea
authored andcommitted
Expose vercel ai integration
1 parent 9659275 commit 301e032

File tree

8 files changed

+1294
-0
lines changed

8 files changed

+1294
-0
lines changed

packages/cloudflare/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ export { CloudflareClient } from './client';
107107
export { getDefaultIntegrations } from './sdk';
108108

109109
export { fetchIntegration } from './integrations/fetch';
110+
export { vercelAIIntegration } from './integrations/tracing/vercelai';
110111

111112
export { instrumentD1WithSentry } from './d1';
112113

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { existsSync, readFileSync } from 'node:fs';
2+
import { dirname, join } from 'node:path';
3+
import type { IntegrationFn } from '@sentry/core';
4+
import { isCjs } from '../utils/commonjs';
5+
6+
type ModuleInfo = Record<string, string>;
7+
8+
let moduleCache: ModuleInfo | undefined;
9+
10+
const INTEGRATION_NAME = 'Modules';
11+
12+
declare const __SENTRY_SERVER_MODULES__: Record<string, string>;
13+
14+
/**
15+
* `__SENTRY_SERVER_MODULES__` can be replaced at build time with the modules loaded by the server.
16+
* Right now, we leverage this in Next.js to circumvent the problem that we do not get access to these things at runtime.
17+
*/
18+
const SERVER_MODULES = typeof __SENTRY_SERVER_MODULES__ === 'undefined' ? {} : __SENTRY_SERVER_MODULES__;
19+
20+
const _modulesIntegration = (() => {
21+
return {
22+
name: INTEGRATION_NAME,
23+
processEvent(event) {
24+
event.modules = {
25+
...event.modules,
26+
..._getModules(),
27+
};
28+
29+
return event;
30+
},
31+
getModules: _getModules,
32+
};
33+
}) satisfies IntegrationFn;
34+
35+
/**
36+
* Add node modules / packages to the event.
37+
* For this, multiple sources are used:
38+
* - They can be injected at build time into the __SENTRY_SERVER_MODULES__ variable (e.g. in Next.js)
39+
* - They are extracted from the dependencies & devDependencies in the package.json file
40+
* - They are extracted from the require.cache (CJS only)
41+
*/
42+
export const modulesIntegration = _modulesIntegration;
43+
44+
function getRequireCachePaths(): string[] {
45+
try {
46+
return require.cache ? Object.keys(require.cache as Record<string, unknown>) : [];
47+
} catch (e) {
48+
return [];
49+
}
50+
}
51+
52+
/** Extract information about package.json modules */
53+
function collectModules(): ModuleInfo {
54+
return {
55+
...SERVER_MODULES,
56+
...getModulesFromPackageJson(),
57+
...(isCjs() ? collectRequireModules() : {}),
58+
};
59+
}
60+
61+
/** Extract information about package.json modules from require.cache */
62+
function collectRequireModules(): ModuleInfo {
63+
const mainPaths = require.main?.paths || [];
64+
const paths = getRequireCachePaths();
65+
66+
// We start with the modules from package.json (if possible)
67+
// These may be overwritten by more specific versions from the require.cache
68+
const infos: ModuleInfo = {};
69+
const seen = new Set<string>();
70+
71+
paths.forEach(path => {
72+
let dir = path;
73+
74+
/** Traverse directories upward in the search of package.json file */
75+
const updir = (): void | (() => void) => {
76+
const orig = dir;
77+
dir = dirname(orig);
78+
79+
if (!dir || orig === dir || seen.has(orig)) {
80+
return undefined;
81+
}
82+
if (mainPaths.indexOf(dir) < 0) {
83+
return updir();
84+
}
85+
86+
const pkgfile = join(orig, 'package.json');
87+
seen.add(orig);
88+
89+
if (!existsSync(pkgfile)) {
90+
return updir();
91+
}
92+
93+
try {
94+
const info = JSON.parse(readFileSync(pkgfile, 'utf8')) as {
95+
name: string;
96+
version: string;
97+
};
98+
infos[info.name] = info.version;
99+
} catch (_oO) {
100+
// no-empty
101+
}
102+
};
103+
104+
updir();
105+
});
106+
107+
return infos;
108+
}
109+
110+
/** Fetches the list of modules and the versions loaded by the entry file for your node.js app. */
111+
function _getModules(): ModuleInfo {
112+
if (!moduleCache) {
113+
moduleCache = collectModules();
114+
}
115+
return moduleCache;
116+
}
117+
118+
interface PackageJson {
119+
dependencies?: Record<string, string>;
120+
devDependencies?: Record<string, string>;
121+
}
122+
123+
function getPackageJson(): PackageJson {
124+
try {
125+
const filePath = join(process.cwd(), 'package.json');
126+
const packageJson = JSON.parse(readFileSync(filePath, 'utf8')) as PackageJson;
127+
128+
return packageJson;
129+
} catch (e) {
130+
return {};
131+
}
132+
}
133+
134+
function getModulesFromPackageJson(): ModuleInfo {
135+
const packageJson = getPackageJson();
136+
137+
return {
138+
...packageJson.dependencies,
139+
...packageJson.devDependencies,
140+
};
141+
}

0 commit comments

Comments
 (0)