@senzops/apm-node 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/index.global.js +1 -1
  2. package/dist/index.global.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/register.js +1 -1
  8. package/dist/register.js.map +1 -1
  9. package/dist/register.mjs +1 -1
  10. package/dist/register.mjs.map +1 -1
  11. package/package.json +1 -1
  12. package/src/instrumentation/express.ts +12 -2
  13. package/.claude/worktrees/infallible-chatelet-f3fb36/.claude/settings.local.json +0 -9
  14. package/.claude/worktrees/infallible-chatelet-f3fb36/CHANGELOG.md +0 -49
  15. package/.claude/worktrees/infallible-chatelet-f3fb36/README.md +0 -398
  16. package/.claude/worktrees/infallible-chatelet-f3fb36/package-lock.json +0 -1494
  17. package/.claude/worktrees/infallible-chatelet-f3fb36/package.json +0 -42
  18. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/client.ts +0 -451
  19. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/context.ts +0 -48
  20. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/normalizer.ts +0 -44
  21. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/sanitizer.ts +0 -203
  22. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/transport.ts +0 -273
  23. package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/types.ts +0 -106
  24. package/.claude/worktrees/infallible-chatelet-f3fb36/src/index.ts +0 -36
  25. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/bullmq.ts +0 -195
  26. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/cron.ts +0 -204
  27. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/express.ts +0 -338
  28. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/fastify.ts +0 -296
  29. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/framework.ts +0 -301
  30. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/hook.ts +0 -134
  31. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/http.ts +0 -530
  32. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/koa.ts +0 -173
  33. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongo.ts +0 -202
  34. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongoose.ts +0 -156
  35. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mysql.ts +0 -169
  36. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/patch.ts +0 -56
  37. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/pg.ts +0 -131
  38. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/redis.ts +0 -109
  39. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/span.ts +0 -73
  40. package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/undici.ts +0 -189
  41. package/.claude/worktrees/infallible-chatelet-f3fb36/src/middleware/express.ts +0 -48
  42. package/.claude/worktrees/infallible-chatelet-f3fb36/src/register.ts +0 -58
  43. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/getClientIp.ts +0 -175
  44. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/ids.ts +0 -7
  45. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/internal.ts +0 -1
  46. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/sdkMeta.ts +0 -6
  47. package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/traceContext.ts +0 -44
  48. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/fastify.ts +0 -35
  49. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/h3.ts +0 -59
  50. package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/next.ts +0 -131
  51. package/.claude/worktrees/infallible-chatelet-f3fb36/tsconfig.json +0 -15
  52. package/.claude/worktrees/infallible-chatelet-f3fb36/tsup.config.ts +0 -21
  53. package/.claude/worktrees/infallible-chatelet-f3fb36/wiki.md +0 -852
@@ -1,296 +0,0 @@
1
- import { SenzorOptions } from '../core/types';
2
- import { hookRequire } from './hook';
3
- import { patchMethod } from './patch';
4
- import { wrapFrameworkHandlerWithArity } from './framework';
5
-
6
- const FACTORY_PATCHED = Symbol.for('senzor.fastify.factory.patched');
7
- const INSTANCE_PATCHED = Symbol.for('senzor.fastify.instance.patched');
8
-
9
- const lifecycleHookNames = new Set([
10
- 'onRequest',
11
- 'preParsing',
12
- 'preValidation',
13
- 'preHandler',
14
- 'preSerialization',
15
- 'onSend',
16
- 'onResponse',
17
- 'onError',
18
- 'onTimeout',
19
- 'onRequestAbort'
20
- ]);
21
-
22
- const routeLifecycleKeys = [
23
- 'onRequest',
24
- 'preParsing',
25
- 'preValidation',
26
- 'preHandler',
27
- 'preSerialization',
28
- 'onSend',
29
- 'onResponse',
30
- 'onError'
31
- ];
32
-
33
- const getRoute = (request: any, fallback?: string): string | undefined =>
34
- request?.routeOptions?.url ||
35
- request?.routerPath ||
36
- request?.context?.config?.url ||
37
- fallback;
38
-
39
- const wrapHook = (
40
- hookName: string,
41
- handler: any,
42
- options?: SenzorOptions,
43
- route?: string
44
- ) => {
45
- if (typeof handler !== 'function') return handler;
46
-
47
- return wrapFrameworkHandlerWithArity(
48
- handler,
49
- (_thisArg, args) => {
50
- const request = args[0];
51
- const reply = args[1];
52
- const currentRoute = getRoute(request, route);
53
-
54
- return {
55
- framework: 'fastify',
56
- type: hookName === 'onError' ? 'error_handler' : 'lifecycle_hook',
57
- name: `fastify.${hookName} ${currentRoute || request?.url || ''}`.trim(),
58
- route: currentRoute,
59
- method: request?.method,
60
- handlerName: handler.name || hookName,
61
- request,
62
- response: reply?.raw || reply,
63
- attributes: {
64
- 'fastify.hook': hookName,
65
- 'fastify.type': hookName === 'onError' ? 'error_handler' : 'lifecycle_hook',
66
- 'http.route': currentRoute,
67
- url: request?.url
68
- }
69
- };
70
- },
71
- options,
72
- {
73
- callbackCompletesSpan: true,
74
- responseEndsSpan: false
75
- }
76
- );
77
- };
78
-
79
- const wrapRouteHandler = (
80
- handler: any,
81
- options?: SenzorOptions,
82
- route?: string
83
- ) => {
84
- if (typeof handler !== 'function') return handler;
85
-
86
- return wrapFrameworkHandlerWithArity(
87
- handler,
88
- (_thisArg, args) => {
89
- const request = args[0];
90
- const reply = args[1];
91
- const currentRoute = getRoute(request, route);
92
-
93
- return {
94
- framework: 'fastify',
95
- type: 'route_handler',
96
- name: `fastify.route_handler ${request?.method || ''} ${currentRoute || request?.url || ''}`.trim(),
97
- route: currentRoute,
98
- method: request?.method,
99
- handlerName: handler.name || 'handler',
100
- request,
101
- response: reply?.raw || reply,
102
- attributes: {
103
- 'fastify.type': 'route_handler',
104
- 'http.route': currentRoute,
105
- url: request?.url
106
- }
107
- };
108
- },
109
- options,
110
- {
111
- callbackCompletesSpan: true,
112
- responseEndsSpan: true
113
- }
114
- );
115
- };
116
-
117
- const wrapMaybeArray = (
118
- value: any,
119
- wrap: (handler: any) => any
120
- ) => {
121
- if (Array.isArray(value)) return value.map(wrap);
122
- return wrap(value);
123
- };
124
-
125
- const patchFastifyInstance = (
126
- instance: any,
127
- options?: SenzorOptions
128
- ) => {
129
- if (!instance || instance[INSTANCE_PATCHED]) return instance;
130
-
131
- Object.defineProperty(instance, INSTANCE_PATCHED, {
132
- value: true,
133
- enumerable: false
134
- });
135
-
136
- patchMethod(
137
- instance,
138
- 'addHook',
139
- 'senzor.fastify.addHook',
140
- (original) =>
141
- function patchedFastifyAddHook(this: any, hookName: string, handler: any) {
142
- if (lifecycleHookNames.has(hookName)) {
143
- return original.call(this, hookName, wrapHook(hookName, handler, options));
144
- }
145
-
146
- return original.apply(this, arguments as any);
147
- }
148
- );
149
-
150
- patchMethod(
151
- instance,
152
- 'route',
153
- 'senzor.fastify.route',
154
- (original) =>
155
- function patchedFastifyRoute(this: any, routeOptions: any) {
156
- if (!routeOptions || typeof routeOptions !== 'object') {
157
- return original.apply(this, arguments as any);
158
- }
159
-
160
- const nextRouteOptions = { ...routeOptions };
161
- const route =
162
- nextRouteOptions.url ||
163
- nextRouteOptions.path ||
164
- nextRouteOptions.routePath;
165
-
166
- if (nextRouteOptions.handler) {
167
- nextRouteOptions.handler = wrapRouteHandler(
168
- nextRouteOptions.handler,
169
- options,
170
- route
171
- );
172
- }
173
-
174
- for (const key of routeLifecycleKeys) {
175
- if (nextRouteOptions[key]) {
176
- nextRouteOptions[key] = wrapMaybeArray(
177
- nextRouteOptions[key],
178
- (handler) => wrapHook(key, handler, options, route)
179
- );
180
- }
181
- }
182
-
183
- return original.call(this, nextRouteOptions);
184
- }
185
- );
186
-
187
- patchMethod(
188
- instance,
189
- 'setErrorHandler',
190
- 'senzor.fastify.setErrorHandler',
191
- (original) =>
192
- function patchedFastifySetErrorHandler(this: any, handler: any) {
193
- return original.call(
194
- this,
195
- wrapFrameworkHandlerWithArity(
196
- handler,
197
- (_thisArg, args) => {
198
- const request = args[1];
199
- const reply = args[2];
200
- const route = getRoute(request);
201
-
202
- return {
203
- framework: 'fastify',
204
- type: 'error_handler',
205
- name: `fastify.error_handler ${route || request?.url || ''}`.trim(),
206
- route,
207
- method: request?.method,
208
- handlerName: handler?.name || 'errorHandler',
209
- request,
210
- response: reply?.raw || reply,
211
- attributes: {
212
- 'fastify.type': 'error_handler',
213
- error: args[0]?.message,
214
- 'error.type': args[0]?.name || typeof args[0]
215
- }
216
- };
217
- },
218
- options,
219
- {
220
- callbackCompletesSpan: true,
221
- responseEndsSpan: true
222
- }
223
- )
224
- );
225
- }
226
- );
227
-
228
- return instance;
229
- };
230
-
231
- const copyFactoryProperties = (
232
- source: any,
233
- target: any
234
- ) => {
235
- for (const key of Reflect.ownKeys(source)) {
236
- if (['length', 'name', 'prototype'].includes(String(key))) continue;
237
-
238
- try {
239
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)!);
240
- } catch { }
241
- }
242
- };
243
-
244
- const wrapFastifyFactory = (
245
- factory: any,
246
- options?: SenzorOptions
247
- ) => {
248
- if (typeof factory !== 'function' || factory[FACTORY_PATCHED]) {
249
- return factory;
250
- }
251
-
252
- const wrapped = function senzorFastifyFactory(this: unknown, ...args: any[]) {
253
- const instance = factory.apply(this, args);
254
- return patchFastifyInstance(instance, options);
255
- };
256
-
257
- copyFactoryProperties(factory, wrapped);
258
-
259
- Object.defineProperty(wrapped, FACTORY_PATCHED, {
260
- value: true,
261
- enumerable: false
262
- });
263
-
264
- const mutableWrapped = wrapped as any;
265
-
266
- if (mutableWrapped.fastify === factory) {
267
- mutableWrapped.fastify = mutableWrapped;
268
- }
269
- if (mutableWrapped.default === factory) {
270
- mutableWrapped.default = mutableWrapped;
271
- }
272
-
273
- return mutableWrapped;
274
- };
275
-
276
- export const instrumentFastify = (options?: SenzorOptions) => {
277
- hookRequire('fastify', (exports: any) => {
278
- if (typeof exports === 'function') {
279
- return wrapFastifyFactory(exports, options);
280
- }
281
-
282
- if (exports?.fastify) {
283
- exports.fastify = wrapFastifyFactory(exports.fastify, options);
284
- }
285
- if (exports?.default) {
286
- exports.default = wrapFastifyFactory(exports.default, options);
287
- }
288
-
289
- return exports;
290
- });
291
- };
292
-
293
- export const instrumentFastifyInstance = (
294
- instance: any,
295
- options?: SenzorOptions
296
- ) => patchFastifyInstance(instance, options);
@@ -1,301 +0,0 @@
1
- import { Context } from '../core/context';
2
- import { SenzorOptions } from '../core/types';
3
- import { CapturedSpan, runWithCapturedSpan, startCapturedSpan } from './span';
4
-
5
- export type FrameworkSpanType =
6
- | 'middleware'
7
- | 'router'
8
- | 'request_handler'
9
- | 'route_handler'
10
- | 'controller_handler'
11
- | 'lifecycle_hook'
12
- | 'error_handler'
13
- | 'event_handler';
14
-
15
- export interface FrameworkSpanInfo {
16
- framework: string;
17
- type: FrameworkSpanType;
18
- name: string;
19
- route?: string;
20
- method?: string;
21
- layerPath?: string;
22
- handlerName?: string;
23
- request?: any;
24
- response?: any;
25
- attributes?: Record<string, unknown>;
26
- }
27
-
28
- interface InvokeOptions {
29
- callbackIndex?: number;
30
- callbackCompletesSpan?: boolean;
31
- responseEndsSpan?: boolean;
32
- }
33
-
34
- const ignoredNextValues = new Set([undefined, null, 'route', 'router']);
35
-
36
- export const shouldCaptureFrameworkSpan = (
37
- type: FrameworkSpanType,
38
- options?: SenzorOptions
39
- ): boolean => {
40
- if (options?.frameworkSpans === false) return false;
41
- if (type === 'middleware' && options?.captureMiddlewareSpans === false) return false;
42
- if (type === 'router' && options?.captureRouterSpans === false) return false;
43
- if (type === 'lifecycle_hook' && options?.captureLifecycleHookSpans === false) return false;
44
- if (options?.ignoreFrameworkSpanTypes?.includes(type)) return false;
45
- return true;
46
- };
47
-
48
- const statusFrom = (
49
- info: FrameworkSpanInfo,
50
- fallback = 0
51
- ): number => {
52
- const res = info.response;
53
- return (
54
- res?.statusCode ||
55
- res?.status ||
56
- res?.raw?.statusCode ||
57
- res?.status_code ||
58
- fallback
59
- );
60
- };
61
-
62
- const isPromiseLike = (value: unknown): value is Promise<unknown> =>
63
- Boolean(value && typeof (value as any).then === 'function');
64
-
65
- const runWithParentOf = <T>(
66
- span: CapturedSpan,
67
- fn: () => T
68
- ): T => {
69
- if (!span.parentSpanId) return fn();
70
- return Context.withActiveSpan(span.parentSpanId, fn);
71
- };
72
-
73
- const copyFunctionProperties = (
74
- source: Function,
75
- target: Function
76
- ) => {
77
- for (const key in source as any) {
78
- try {
79
- Object.defineProperty(target, key, {
80
- configurable: true,
81
- enumerable: true,
82
- get() {
83
- return (source as any)[key];
84
- },
85
- set(value) {
86
- (source as any)[key] = value;
87
- }
88
- });
89
- } catch { }
90
- }
91
- };
92
-
93
- export const invokeWithFrameworkSpan = (
94
- handler: Function,
95
- thisArg: unknown,
96
- args: any[],
97
- info: FrameworkSpanInfo,
98
- options?: SenzorOptions,
99
- invokeOptions: InvokeOptions = {}
100
- ) => {
101
- if (!shouldCaptureFrameworkSpan(info.type, options) || !Context.current()) {
102
- return handler.apply(thisArg, args);
103
- }
104
-
105
- const span = startCapturedSpan(
106
- info.name,
107
- 'function',
108
- {
109
- framework: info.framework,
110
- 'senzor.framework': info.framework,
111
- 'senzor.framework.type': info.type,
112
- 'http.route': info.route,
113
- route: info.route,
114
- method: info.method,
115
- layerPath: info.layerPath,
116
- handlerName: info.handlerName,
117
- ...info.attributes
118
- },
119
- options
120
- );
121
-
122
- if (!span) return handler.apply(thisArg, args);
123
-
124
- let ended = false;
125
- const cleanup: Array<() => void> = [];
126
-
127
- const endSpan = (
128
- status = statusFrom(info),
129
- meta: Record<string, unknown> = {}
130
- ) => {
131
- if (ended) return;
132
- ended = true;
133
-
134
- for (const clean of cleanup) {
135
- try { clean(); } catch { }
136
- }
137
-
138
- span.end(status, meta);
139
- };
140
-
141
- const res = info.response;
142
- if (invokeOptions.responseEndsSpan !== false && res?.once) {
143
- const onFinish = () =>
144
- endSpan(statusFrom(info), { completion: 'response.finish' });
145
- const onClose = () =>
146
- endSpan(statusFrom(info), { completion: 'response.close' });
147
-
148
- res.once('finish', onFinish);
149
- res.once('close', onClose);
150
-
151
- cleanup.push(() => {
152
- try { res.removeListener?.('finish', onFinish); } catch { }
153
- try { res.removeListener?.('close', onClose); } catch { }
154
- });
155
- }
156
-
157
- const callbackIndex =
158
- invokeOptions.callbackIndex ??
159
- args.findIndex((arg) => typeof arg === 'function');
160
-
161
- if (
162
- invokeOptions.callbackCompletesSpan !== false &&
163
- callbackIndex >= 0 &&
164
- typeof args[callbackIndex] === 'function'
165
- ) {
166
- const originalCallback = args[callbackIndex];
167
- args[callbackIndex] = function wrappedFrameworkCallback(
168
- this: unknown,
169
- ...callbackArgs: any[]
170
- ) {
171
- const maybeError = callbackArgs[0];
172
- const hasError = !ignoredNextValues.has(maybeError);
173
-
174
- endSpan(hasError ? 500 : statusFrom(info), {
175
- completion: 'callback',
176
- error: hasError ? String(maybeError?.message || maybeError) : undefined,
177
- 'error.type': hasError
178
- ? maybeError?.name || typeof maybeError
179
- : undefined
180
- });
181
-
182
- return runWithParentOf(span, () =>
183
- originalCallback.apply(this, callbackArgs)
184
- );
185
- };
186
- }
187
-
188
- return runWithCapturedSpan(span, () => {
189
- try {
190
- const result = handler.apply(thisArg, args);
191
-
192
- if (isPromiseLike(result)) {
193
- return result.then(
194
- (value) => {
195
- endSpan(statusFrom(info), { completion: 'promise.resolve' });
196
- return value;
197
- },
198
- (error) => {
199
- endSpan(500, {
200
- completion: 'promise.reject',
201
- error: error?.message,
202
- 'error.type': error?.name || 'Error'
203
- });
204
- throw error;
205
- }
206
- );
207
- }
208
-
209
- if (callbackIndex < 0 && invokeOptions.responseEndsSpan === false) {
210
- endSpan(statusFrom(info), { completion: 'sync.return' });
211
- }
212
-
213
- return result;
214
- } catch (error: any) {
215
- endSpan(500, {
216
- completion: 'throw',
217
- error: error?.message,
218
- 'error.type': error?.name || 'Error'
219
- });
220
- throw error;
221
- }
222
- });
223
- };
224
-
225
- export const wrapFrameworkHandler = <T extends Function>(
226
- handler: T,
227
- getInfo: (thisArg: unknown, args: any[]) => FrameworkSpanInfo,
228
- options?: SenzorOptions,
229
- invokeOptions: InvokeOptions = {}
230
- ): T => {
231
- if (typeof handler !== 'function') return handler;
232
-
233
- const wrapped = function wrappedFrameworkHandler(
234
- this: unknown,
235
- ...args: any[]
236
- ) {
237
- return invokeWithFrameworkSpan(
238
- handler,
239
- this,
240
- args,
241
- getInfo(this, args),
242
- options,
243
- invokeOptions
244
- );
245
- };
246
-
247
- copyFunctionProperties(handler, wrapped);
248
- return wrapped as unknown as T;
249
- };
250
-
251
- export const wrapFrameworkHandlerWithArity = <T extends Function>(
252
- handler: T,
253
- getInfo: (thisArg: unknown, args: any[]) => FrameworkSpanInfo,
254
- options?: SenzorOptions,
255
- invokeOptions: InvokeOptions = {}
256
- ): T => {
257
- if (typeof handler !== 'function') return handler;
258
-
259
- const invoke = (thisArg: unknown, args: any[]) =>
260
- invokeWithFrameworkSpan(
261
- handler,
262
- thisArg,
263
- args,
264
- getInfo(thisArg, args),
265
- options,
266
- invokeOptions
267
- );
268
-
269
- let wrapped: Function;
270
-
271
- switch (handler.length) {
272
- case 4:
273
- wrapped = function wrapped4(this: unknown, a: any, b: any, c: any, d: any) {
274
- return invoke(this, [a, b, c, d]);
275
- };
276
- break;
277
- case 3:
278
- wrapped = function wrapped3(this: unknown, a: any, b: any, c: any) {
279
- return invoke(this, [a, b, c]);
280
- };
281
- break;
282
- case 2:
283
- wrapped = function wrapped2(this: unknown, a: any, b: any) {
284
- return invoke(this, [a, b]);
285
- };
286
- break;
287
- case 1:
288
- wrapped = function wrapped1(this: unknown, a: any) {
289
- return invoke(this, [a]);
290
- };
291
- break;
292
- default:
293
- wrapped = function wrapped0(this: unknown) {
294
- return invoke(this, Array.from(arguments));
295
- };
296
- break;
297
- }
298
-
299
- copyFunctionProperties(handler, wrapped);
300
- return wrapped as unknown as T;
301
- };