@senzops/apm-node 1.2.2 → 1.2.4
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.
- package/dist/index.global.js +1 -1
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/register.js +1 -1
- package/dist/register.js.map +1 -1
- package/dist/register.mjs +1 -1
- package/dist/register.mjs.map +1 -1
- package/package.json +1 -1
- package/src/core/client.ts +172 -167
- package/src/core/context.ts +2 -2
- package/src/core/types.ts +48 -43
- package/src/instrumentation/express.ts +12 -2
- package/src/instrumentation/http.ts +1 -1
- package/.claude/worktrees/infallible-chatelet-f3fb36/.claude/settings.local.json +0 -9
- package/.claude/worktrees/infallible-chatelet-f3fb36/CHANGELOG.md +0 -49
- package/.claude/worktrees/infallible-chatelet-f3fb36/README.md +0 -398
- package/.claude/worktrees/infallible-chatelet-f3fb36/package-lock.json +0 -1494
- package/.claude/worktrees/infallible-chatelet-f3fb36/package.json +0 -42
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/client.ts +0 -451
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/context.ts +0 -48
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/normalizer.ts +0 -44
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/sanitizer.ts +0 -203
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/transport.ts +0 -273
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/core/types.ts +0 -106
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/index.ts +0 -36
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/bullmq.ts +0 -195
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/cron.ts +0 -204
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/express.ts +0 -338
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/fastify.ts +0 -296
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/framework.ts +0 -301
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/hook.ts +0 -134
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/http.ts +0 -530
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/koa.ts +0 -173
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongo.ts +0 -202
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mongoose.ts +0 -156
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/mysql.ts +0 -169
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/patch.ts +0 -56
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/pg.ts +0 -131
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/redis.ts +0 -109
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/span.ts +0 -73
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/instrumentation/undici.ts +0 -189
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/middleware/express.ts +0 -48
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/register.ts +0 -58
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/getClientIp.ts +0 -175
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/ids.ts +0 -7
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/internal.ts +0 -1
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/sdkMeta.ts +0 -6
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/utils/traceContext.ts +0 -44
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/fastify.ts +0 -35
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/h3.ts +0 -59
- package/.claude/worktrees/infallible-chatelet-f3fb36/src/wrappers/next.ts +0 -131
- package/.claude/worktrees/infallible-chatelet-f3fb36/tsconfig.json +0 -15
- package/.claude/worktrees/infallible-chatelet-f3fb36/tsup.config.ts +0 -21
- package/.claude/worktrees/infallible-chatelet-f3fb36/wiki.md +0 -852
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import type { SenzorClient } from '../core/client';
|
|
2
|
-
import { hookRequire } from './hook';
|
|
3
|
-
import { Context } from '../core/context';
|
|
4
|
-
|
|
5
|
-
const PATCHED =
|
|
6
|
-
Symbol.for(
|
|
7
|
-
'senzor.bullmq.patched'
|
|
8
|
-
);
|
|
9
|
-
|
|
10
|
-
function patchWorker(
|
|
11
|
-
target: any,
|
|
12
|
-
client: SenzorClient,
|
|
13
|
-
debug: boolean
|
|
14
|
-
) {
|
|
15
|
-
|
|
16
|
-
if (
|
|
17
|
-
!target?.Worker?.prototype
|
|
18
|
-
) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const proto =
|
|
23
|
-
target.Worker.prototype;
|
|
24
|
-
|
|
25
|
-
const original =
|
|
26
|
-
proto.processJob;
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
typeof original !==
|
|
30
|
-
'function' ||
|
|
31
|
-
original[PATCHED]
|
|
32
|
-
) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
proto.processJob =
|
|
37
|
-
async function (
|
|
38
|
-
job: any
|
|
39
|
-
) {
|
|
40
|
-
|
|
41
|
-
const queueDelay =
|
|
42
|
-
job.timestamp
|
|
43
|
-
? Date.now() -
|
|
44
|
-
job.timestamp
|
|
45
|
-
: 0;
|
|
46
|
-
|
|
47
|
-
const currentAttempt =
|
|
48
|
-
(job.attemptsMade || 0)
|
|
49
|
-
+ 1;
|
|
50
|
-
|
|
51
|
-
const maxAttempts =
|
|
52
|
-
job.opts?.attempts
|
|
53
|
-
?? 1;
|
|
54
|
-
|
|
55
|
-
const isFinal =
|
|
56
|
-
currentAttempt >=
|
|
57
|
-
maxAttempts;
|
|
58
|
-
|
|
59
|
-
const taskName =
|
|
60
|
-
job.name ===
|
|
61
|
-
'__default__'
|
|
62
|
-
? job.queueName
|
|
63
|
-
: `${job.queueName}:${job.name}`;
|
|
64
|
-
|
|
65
|
-
return client.startTask(
|
|
66
|
-
|
|
67
|
-
taskName,
|
|
68
|
-
|
|
69
|
-
'queue',
|
|
70
|
-
|
|
71
|
-
{
|
|
72
|
-
queueDelay,
|
|
73
|
-
attempts:
|
|
74
|
-
currentAttempt,
|
|
75
|
-
isDeadLetter: false,
|
|
76
|
-
metadata: {
|
|
77
|
-
jobId: job.id,
|
|
78
|
-
queueName:
|
|
79
|
-
job.queueName,
|
|
80
|
-
maxAttempts
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
async () => {
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
|
|
88
|
-
const result =
|
|
89
|
-
await original.call(
|
|
90
|
-
this,
|
|
91
|
-
job
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
client.endTask(
|
|
95
|
-
'success'
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
return result;
|
|
99
|
-
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
|
|
105
|
-
const ctx =
|
|
106
|
-
Context.current();
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
ctx &&
|
|
110
|
-
ctx.contextType === 'task' &&
|
|
111
|
-
isFinal
|
|
112
|
-
) {
|
|
113
|
-
|
|
114
|
-
ctx.data
|
|
115
|
-
.isDeadLetter =
|
|
116
|
-
true;
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
catch { }
|
|
122
|
-
|
|
123
|
-
client.captureError(
|
|
124
|
-
error,
|
|
125
|
-
{
|
|
126
|
-
queueName:
|
|
127
|
-
job.queueName,
|
|
128
|
-
jobId: job.id,
|
|
129
|
-
isDeadLetter:
|
|
130
|
-
isFinal
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
client.endTask(
|
|
135
|
-
'failed'
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
throw error;
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
);
|
|
145
|
-
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
Object.defineProperty(
|
|
149
|
-
proto.processJob,
|
|
150
|
-
PATCHED,
|
|
151
|
-
{
|
|
152
|
-
value: true
|
|
153
|
-
}
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
if (debug) {
|
|
157
|
-
|
|
158
|
-
console.log(
|
|
159
|
-
'[Senzor] BullMQ instrumented'
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export const instrumentBullMQ =
|
|
167
|
-
(
|
|
168
|
-
client: SenzorClient,
|
|
169
|
-
debug: boolean
|
|
170
|
-
) => {
|
|
171
|
-
|
|
172
|
-
hookRequire(
|
|
173
|
-
'bullmq',
|
|
174
|
-
(exports: any) => {
|
|
175
|
-
|
|
176
|
-
patchWorker(
|
|
177
|
-
exports,
|
|
178
|
-
client,
|
|
179
|
-
debug
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
if (exports?.default) {
|
|
183
|
-
|
|
184
|
-
patchWorker(
|
|
185
|
-
exports.default,
|
|
186
|
-
client,
|
|
187
|
-
debug
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
};
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import type { SenzorClient } from '../core/client';
|
|
2
|
-
import { hookRequire } from './hook';
|
|
3
|
-
|
|
4
|
-
const PATCHED =
|
|
5
|
-
Symbol.for('senzor.cron.patched');
|
|
6
|
-
|
|
7
|
-
type CronHandler =
|
|
8
|
-
(...args: unknown[]) => unknown;
|
|
9
|
-
|
|
10
|
-
type CronSchedule =
|
|
11
|
-
(
|
|
12
|
-
expression: string,
|
|
13
|
-
handler: CronHandler,
|
|
14
|
-
options?: unknown
|
|
15
|
-
) => unknown;
|
|
16
|
-
|
|
17
|
-
function normalizeOptions(
|
|
18
|
-
options: unknown
|
|
19
|
-
): Record<string, unknown> {
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
typeof options === 'object' &&
|
|
23
|
-
options !== null
|
|
24
|
-
) {
|
|
25
|
-
return options as Record<
|
|
26
|
-
string,
|
|
27
|
-
unknown
|
|
28
|
-
>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// backward compatibility with:
|
|
32
|
-
// cron.schedule(expr, fn, "UTC")
|
|
33
|
-
if (options) {
|
|
34
|
-
return { timezone: options };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return {};
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function patchTarget(
|
|
42
|
-
target: Record<string, unknown>,
|
|
43
|
-
client: SenzorClient,
|
|
44
|
-
debug: boolean
|
|
45
|
-
): void {
|
|
46
|
-
|
|
47
|
-
const schedule =
|
|
48
|
-
target.schedule as
|
|
49
|
-
CronSchedule | undefined;
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
typeof schedule !== 'function' ||
|
|
53
|
-
(schedule as any)[PATCHED]
|
|
54
|
-
) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const original =
|
|
59
|
-
schedule;
|
|
60
|
-
|
|
61
|
-
const wrapped: CronSchedule =
|
|
62
|
-
function (
|
|
63
|
-
this: unknown,
|
|
64
|
-
expression,
|
|
65
|
-
handler,
|
|
66
|
-
options
|
|
67
|
-
) {
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
typeof handler !==
|
|
71
|
-
'function'
|
|
72
|
-
) {
|
|
73
|
-
|
|
74
|
-
return original.call(
|
|
75
|
-
this,
|
|
76
|
-
expression,
|
|
77
|
-
handler,
|
|
78
|
-
options
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
|
|
85
|
-
const opts =
|
|
86
|
-
normalizeOptions(
|
|
87
|
-
options
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const taskName =
|
|
91
|
-
(opts as any)?.name ??
|
|
92
|
-
`cron: ${expression}`;
|
|
93
|
-
|
|
94
|
-
const wrappedHandler =
|
|
95
|
-
client.wrapTask(
|
|
96
|
-
taskName,
|
|
97
|
-
'cron',
|
|
98
|
-
{
|
|
99
|
-
expression,
|
|
100
|
-
metadata: opts
|
|
101
|
-
},
|
|
102
|
-
handler
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
return original.call(
|
|
106
|
-
this,
|
|
107
|
-
expression,
|
|
108
|
-
wrappedHandler,
|
|
109
|
-
options
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
catch (err) {
|
|
114
|
-
|
|
115
|
-
if (debug) {
|
|
116
|
-
|
|
117
|
-
console.error(
|
|
118
|
-
'[Senzor] cron wrap failed',
|
|
119
|
-
err
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return original.call(
|
|
125
|
-
this,
|
|
126
|
-
expression,
|
|
127
|
-
handler,
|
|
128
|
-
options
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
Object.defineProperty(
|
|
136
|
-
wrapped,
|
|
137
|
-
PATCHED,
|
|
138
|
-
{
|
|
139
|
-
value: true,
|
|
140
|
-
enumerable: false
|
|
141
|
-
}
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
// Some ESM namespace exports are frozen
|
|
145
|
-
try {
|
|
146
|
-
|
|
147
|
-
target.schedule =
|
|
148
|
-
wrapped;
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
|
|
153
|
-
if (debug) {
|
|
154
|
-
|
|
155
|
-
console.warn(
|
|
156
|
-
'[Senzor] unable to patch cron schedule (readonly export)'
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
if (debug) {
|
|
164
|
-
|
|
165
|
-
console.log(
|
|
166
|
-
'[Senzor] node-cron instrumented'
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export const instrumentNodeCron =
|
|
174
|
-
(
|
|
175
|
-
client: SenzorClient,
|
|
176
|
-
debug: boolean
|
|
177
|
-
): void => {
|
|
178
|
-
|
|
179
|
-
hookRequire(
|
|
180
|
-
'node-cron',
|
|
181
|
-
(exports: any) => {
|
|
182
|
-
|
|
183
|
-
if (!exports) return;
|
|
184
|
-
|
|
185
|
-
patchTarget(
|
|
186
|
-
exports,
|
|
187
|
-
client,
|
|
188
|
-
debug
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
if (exports.default) {
|
|
192
|
-
|
|
193
|
-
patchTarget(
|
|
194
|
-
exports.default,
|
|
195
|
-
client,
|
|
196
|
-
debug
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
};
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import { normalizePath } from '../core/normalizer';
|
|
2
|
-
import { SenzorOptions } from '../core/types';
|
|
3
|
-
import { hookRequire } from './hook';
|
|
4
|
-
import { patchMethod } from './patch';
|
|
5
|
-
import { invokeWithFrameworkSpan } from './framework';
|
|
6
|
-
|
|
7
|
-
const LAYER_PATCHED = Symbol.for('senzor.express.layer.patched');
|
|
8
|
-
|
|
9
|
-
const routeMethods = new Set([
|
|
10
|
-
'checkout',
|
|
11
|
-
'copy',
|
|
12
|
-
'delete',
|
|
13
|
-
'get',
|
|
14
|
-
'head',
|
|
15
|
-
'lock',
|
|
16
|
-
'merge',
|
|
17
|
-
'mkactivity',
|
|
18
|
-
'mkcol',
|
|
19
|
-
'move',
|
|
20
|
-
'm-search',
|
|
21
|
-
'notify',
|
|
22
|
-
'options',
|
|
23
|
-
'patch',
|
|
24
|
-
'post',
|
|
25
|
-
'purge',
|
|
26
|
-
'put',
|
|
27
|
-
'report',
|
|
28
|
-
'search',
|
|
29
|
-
'subscribe',
|
|
30
|
-
'trace',
|
|
31
|
-
'unlock',
|
|
32
|
-
'unsubscribe'
|
|
33
|
-
]);
|
|
34
|
-
|
|
35
|
-
const stringifyPath = (value: unknown): string | undefined => {
|
|
36
|
-
if (typeof value === 'string') return value;
|
|
37
|
-
if (value instanceof RegExp) return value.toString();
|
|
38
|
-
if (Array.isArray(value)) {
|
|
39
|
-
return value.map(stringifyPath).filter(Boolean).join(',');
|
|
40
|
-
}
|
|
41
|
-
if (typeof value === 'number') return String(value);
|
|
42
|
-
return undefined;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const getLayerPath = (args: any[]): string | undefined => {
|
|
46
|
-
for (const arg of args) {
|
|
47
|
-
if (typeof arg === 'function') return undefined;
|
|
48
|
-
const path = stringifyPath(arg);
|
|
49
|
-
if (path) return path;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return undefined;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const getRequestRoute = (
|
|
56
|
-
req: any,
|
|
57
|
-
layer: any,
|
|
58
|
-
layerPath?: string
|
|
59
|
-
): string | undefined => {
|
|
60
|
-
const routePath = stringifyPath(layer?.route?.path);
|
|
61
|
-
if (routePath) {
|
|
62
|
-
const baseUrl = req?.baseUrl || '';
|
|
63
|
-
return `${baseUrl}${routePath}` || routePath;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (req?.route?.path) {
|
|
67
|
-
return `${req.baseUrl || ''}${req.route.path}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (layerPath) {
|
|
71
|
-
const baseUrl = req?.baseUrl || '';
|
|
72
|
-
return `${baseUrl}${layerPath}` || layerPath;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const path = req?.originalUrl || req?.url || req?.path;
|
|
76
|
-
return path ? normalizePath(String(path).split('?')[0]) : undefined;
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
const getLayerType = (
|
|
80
|
-
layer: any,
|
|
81
|
-
original: Function,
|
|
82
|
-
forcedType?: 'middleware' | 'router' | 'request_handler' | 'error_handler'
|
|
83
|
-
) => {
|
|
84
|
-
if (forcedType) return forcedType;
|
|
85
|
-
if (original.length === 4) return 'error_handler' as const;
|
|
86
|
-
if (layer?.route) return 'request_handler' as const;
|
|
87
|
-
if (layer?.name === 'router' || layer?.handle?.stack || layer?.handle?.name === 'router') {
|
|
88
|
-
return 'router' as const;
|
|
89
|
-
}
|
|
90
|
-
return 'middleware' as const;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const getRouteMethod = (layer: any, req: any): string | undefined => {
|
|
94
|
-
if (layer?.route?.methods) {
|
|
95
|
-
const method = Object.keys(layer.route.methods).find(
|
|
96
|
-
(candidate) => layer.route.methods[candidate]
|
|
97
|
-
);
|
|
98
|
-
if (method) return method.toUpperCase();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return req?.method;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const copyEnumerableProperties = (
|
|
105
|
-
source: Function,
|
|
106
|
-
target: Function
|
|
107
|
-
) => {
|
|
108
|
-
for (const key in source as any) {
|
|
109
|
-
try {
|
|
110
|
-
Object.defineProperty(target, key, {
|
|
111
|
-
configurable: true,
|
|
112
|
-
enumerable: true,
|
|
113
|
-
get() {
|
|
114
|
-
return (source as any)[key];
|
|
115
|
-
},
|
|
116
|
-
set(value) {
|
|
117
|
-
(source as any)[key] = value;
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
} catch { }
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const patchLayer = (
|
|
125
|
-
layer: any,
|
|
126
|
-
layerPath: string | undefined,
|
|
127
|
-
options?: SenzorOptions,
|
|
128
|
-
forcedType?: 'middleware' | 'router' | 'request_handler' | 'error_handler'
|
|
129
|
-
) => {
|
|
130
|
-
if (!layer || layer[LAYER_PATCHED] || typeof layer.handle !== 'function') {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
Object.defineProperty(layer, LAYER_PATCHED, {
|
|
135
|
-
value: true,
|
|
136
|
-
enumerable: false
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
patchMethod(
|
|
140
|
-
layer,
|
|
141
|
-
'handle',
|
|
142
|
-
'senzor.express.layer.handle',
|
|
143
|
-
(original) => {
|
|
144
|
-
const layerType = getLayerType(layer, original, forcedType);
|
|
145
|
-
const handlerName =
|
|
146
|
-
original.name ||
|
|
147
|
-
layer.name ||
|
|
148
|
-
layerType;
|
|
149
|
-
|
|
150
|
-
if (original.length === 4) {
|
|
151
|
-
const wrapped = function senzorExpressErrorHandler(
|
|
152
|
-
this: unknown,
|
|
153
|
-
err: any,
|
|
154
|
-
req: any,
|
|
155
|
-
res: any,
|
|
156
|
-
next: Function
|
|
157
|
-
) {
|
|
158
|
-
const route = getRequestRoute(req, layer, layerPath);
|
|
159
|
-
return invokeWithFrameworkSpan(
|
|
160
|
-
original,
|
|
161
|
-
this,
|
|
162
|
-
[err, req, res, next],
|
|
163
|
-
{
|
|
164
|
-
framework: 'express',
|
|
165
|
-
type: 'error_handler',
|
|
166
|
-
name: `express.error_handler ${route || handlerName}`,
|
|
167
|
-
route,
|
|
168
|
-
method: getRouteMethod(layer, req),
|
|
169
|
-
layerPath,
|
|
170
|
-
handlerName,
|
|
171
|
-
request: req,
|
|
172
|
-
response: res,
|
|
173
|
-
attributes: {
|
|
174
|
-
'express.type': 'error_handler',
|
|
175
|
-
'express.layer.name': layer.name,
|
|
176
|
-
error: err?.message,
|
|
177
|
-
'error.type': err?.name || typeof err
|
|
178
|
-
}
|
|
179
|
-
},
|
|
180
|
-
options,
|
|
181
|
-
{
|
|
182
|
-
callbackIndex: 3,
|
|
183
|
-
callbackCompletesSpan: true,
|
|
184
|
-
responseEndsSpan: true
|
|
185
|
-
}
|
|
186
|
-
);
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
copyEnumerableProperties(original, wrapped);
|
|
190
|
-
return wrapped;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const wrapped = function senzorExpressLayer(
|
|
194
|
-
this: unknown,
|
|
195
|
-
req: any,
|
|
196
|
-
res: any,
|
|
197
|
-
next: Function
|
|
198
|
-
) {
|
|
199
|
-
const route = getRequestRoute(req, layer, layerPath);
|
|
200
|
-
const method = getRouteMethod(layer, req);
|
|
201
|
-
const displayRoute = route || layerPath || handlerName;
|
|
202
|
-
const name =
|
|
203
|
-
layerType === 'request_handler'
|
|
204
|
-
? `express.request_handler ${method || ''} ${displayRoute}`.trim()
|
|
205
|
-
: `express.${layerType} ${displayRoute}`;
|
|
206
|
-
|
|
207
|
-
return invokeWithFrameworkSpan(
|
|
208
|
-
original,
|
|
209
|
-
this,
|
|
210
|
-
[req, res, next],
|
|
211
|
-
{
|
|
212
|
-
framework: 'express',
|
|
213
|
-
type: layerType,
|
|
214
|
-
name,
|
|
215
|
-
route,
|
|
216
|
-
method,
|
|
217
|
-
layerPath,
|
|
218
|
-
handlerName,
|
|
219
|
-
request: req,
|
|
220
|
-
response: res,
|
|
221
|
-
attributes: {
|
|
222
|
-
'express.type': layerType,
|
|
223
|
-
'express.layer.name': layer.name,
|
|
224
|
-
'http.route': route
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
options,
|
|
228
|
-
{
|
|
229
|
-
callbackIndex: 2,
|
|
230
|
-
callbackCompletesSpan: true,
|
|
231
|
-
responseEndsSpan: true
|
|
232
|
-
}
|
|
233
|
-
);
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
copyEnumerableProperties(original, wrapped);
|
|
237
|
-
return wrapped;
|
|
238
|
-
}
|
|
239
|
-
);
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const patchRouteMethodHandlers = (
|
|
243
|
-
route: any,
|
|
244
|
-
routePath: string | undefined,
|
|
245
|
-
options?: SenzorOptions
|
|
246
|
-
) => {
|
|
247
|
-
if (!route || route.__senzorRouteMethodsPatched) return;
|
|
248
|
-
|
|
249
|
-
Object.defineProperty(route, '__senzorRouteMethodsPatched', {
|
|
250
|
-
value: true,
|
|
251
|
-
enumerable: false
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
for (const method of routeMethods) {
|
|
255
|
-
if (typeof route[method] !== 'function') continue;
|
|
256
|
-
|
|
257
|
-
patchMethod(
|
|
258
|
-
route,
|
|
259
|
-
method,
|
|
260
|
-
`senzor.express.route.${method}`,
|
|
261
|
-
(original) =>
|
|
262
|
-
function patchedExpressRouteMethod(this: any, ...args: any[]) {
|
|
263
|
-
const result = original.apply(this, args);
|
|
264
|
-
const stack = this?.stack || [];
|
|
265
|
-
|
|
266
|
-
for (const layer of stack) {
|
|
267
|
-
patchLayer(layer, routePath, options, 'request_handler');
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return result;
|
|
271
|
-
}
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const patchExpress = (
|
|
277
|
-
expressModule: any,
|
|
278
|
-
options?: SenzorOptions
|
|
279
|
-
) => {
|
|
280
|
-
if (!expressModule) return;
|
|
281
|
-
|
|
282
|
-
const routerProto =
|
|
283
|
-
typeof expressModule?.Router?.prototype?.route === 'function'
|
|
284
|
-
? expressModule.Router.prototype
|
|
285
|
-
: expressModule.Router;
|
|
286
|
-
|
|
287
|
-
patchMethod(
|
|
288
|
-
routerProto,
|
|
289
|
-
'route',
|
|
290
|
-
'senzor.express.router.route',
|
|
291
|
-
(original) =>
|
|
292
|
-
function patchedExpressRoute(this: any, ...args: any[]) {
|
|
293
|
-
const route = original.apply(this, args);
|
|
294
|
-
const routePath = getLayerPath(args);
|
|
295
|
-
const layer = this?.stack?.[this.stack.length - 1];
|
|
296
|
-
|
|
297
|
-
patchLayer(layer, routePath, options, 'router');
|
|
298
|
-
patchRouteMethodHandlers(route, routePath, options);
|
|
299
|
-
|
|
300
|
-
return route;
|
|
301
|
-
}
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
patchMethod(
|
|
305
|
-
routerProto,
|
|
306
|
-
'use',
|
|
307
|
-
'senzor.express.router.use',
|
|
308
|
-
(original) =>
|
|
309
|
-
function patchedExpressRouterUse(this: any, ...args: any[]) {
|
|
310
|
-
const result = original.apply(this, args);
|
|
311
|
-
const layer = this?.stack?.[this.stack.length - 1];
|
|
312
|
-
patchLayer(layer, getLayerPath(args), options);
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
315
|
-
);
|
|
316
|
-
|
|
317
|
-
patchMethod(
|
|
318
|
-
expressModule.application,
|
|
319
|
-
'use',
|
|
320
|
-
'senzor.express.application.use',
|
|
321
|
-
(original) =>
|
|
322
|
-
function patchedExpressApplicationUse(this: any, ...args: any[]) {
|
|
323
|
-
const router = this?.router || this?._router;
|
|
324
|
-
const result = original.apply(this, args);
|
|
325
|
-
const activeRouter = this?.router || this?._router || router;
|
|
326
|
-
const layer = activeRouter?.stack?.[activeRouter.stack.length - 1];
|
|
327
|
-
patchLayer(layer, getLayerPath(args), options);
|
|
328
|
-
return result;
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
export const instrumentExpress = (options?: SenzorOptions) => {
|
|
334
|
-
hookRequire('express', (exports: any) => {
|
|
335
|
-
patchExpress(exports, options);
|
|
336
|
-
if (exports?.default) patchExpress(exports.default, options);
|
|
337
|
-
});
|
|
338
|
-
};
|