@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,173 +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 { wrapFrameworkHandlerWithArity } from './framework';
|
|
6
|
-
|
|
7
|
-
const routerMethods = [
|
|
8
|
-
'all',
|
|
9
|
-
'del',
|
|
10
|
-
'delete',
|
|
11
|
-
'get',
|
|
12
|
-
'head',
|
|
13
|
-
'options',
|
|
14
|
-
'patch',
|
|
15
|
-
'post',
|
|
16
|
-
'put'
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
const stringifyPath = (value: unknown): string | undefined => {
|
|
20
|
-
if (typeof value === 'string') return value;
|
|
21
|
-
if (value instanceof RegExp) return value.toString();
|
|
22
|
-
if (Array.isArray(value)) {
|
|
23
|
-
return value.map(stringifyPath).filter(Boolean).join(',');
|
|
24
|
-
}
|
|
25
|
-
return undefined;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const getPathFromArgs = (args: any[]): string | undefined => {
|
|
29
|
-
for (const arg of args) {
|
|
30
|
-
if (typeof arg === 'function') return undefined;
|
|
31
|
-
const path = stringifyPath(arg);
|
|
32
|
-
if (path) return path;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return undefined;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const wrapKoaMiddleware = (
|
|
39
|
-
middleware: any,
|
|
40
|
-
options?: SenzorOptions,
|
|
41
|
-
layerPath?: string,
|
|
42
|
-
layerType: 'middleware' | 'router' | 'route_handler' = 'middleware',
|
|
43
|
-
method?: string
|
|
44
|
-
) => {
|
|
45
|
-
if (typeof middleware !== 'function') return middleware;
|
|
46
|
-
|
|
47
|
-
return wrapFrameworkHandlerWithArity(
|
|
48
|
-
middleware,
|
|
49
|
-
(_thisArg, args) => {
|
|
50
|
-
const ctx = args[0];
|
|
51
|
-
const route =
|
|
52
|
-
ctx?._matchedRoute ||
|
|
53
|
-
ctx?.matched?.[0]?.path ||
|
|
54
|
-
layerPath ||
|
|
55
|
-
normalizePath(ctx?.path || ctx?.request?.path || '/');
|
|
56
|
-
const actualMethod = method || ctx?.method || ctx?.request?.method;
|
|
57
|
-
const handlerName = middleware.name || layerType;
|
|
58
|
-
|
|
59
|
-
return {
|
|
60
|
-
framework: 'koa',
|
|
61
|
-
type: layerType,
|
|
62
|
-
name:
|
|
63
|
-
layerType === 'route_handler'
|
|
64
|
-
? `koa.request_handler ${actualMethod || ''} ${route}`.trim()
|
|
65
|
-
: `koa.${layerType} ${route || handlerName}`,
|
|
66
|
-
route,
|
|
67
|
-
method: actualMethod,
|
|
68
|
-
layerPath,
|
|
69
|
-
handlerName,
|
|
70
|
-
request: ctx?.req || ctx?.request,
|
|
71
|
-
response: ctx?.res || ctx?.response,
|
|
72
|
-
attributes: {
|
|
73
|
-
'koa.type': layerType,
|
|
74
|
-
'http.route': route,
|
|
75
|
-
path: ctx?.path || ctx?.request?.path
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
},
|
|
79
|
-
options,
|
|
80
|
-
{
|
|
81
|
-
callbackCompletesSpan: false,
|
|
82
|
-
responseEndsSpan: false
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
const patchKoaApplication = (
|
|
88
|
-
koa: any,
|
|
89
|
-
options?: SenzorOptions
|
|
90
|
-
) => {
|
|
91
|
-
const proto = koa?.prototype || koa?.default?.prototype;
|
|
92
|
-
if (!proto) return;
|
|
93
|
-
|
|
94
|
-
patchMethod(
|
|
95
|
-
proto,
|
|
96
|
-
'use',
|
|
97
|
-
'senzor.koa.application.use',
|
|
98
|
-
(original) =>
|
|
99
|
-
function patchedKoaUse(this: any, middleware: any) {
|
|
100
|
-
return original.call(
|
|
101
|
-
this,
|
|
102
|
-
wrapKoaMiddleware(middleware, options, undefined, 'middleware')
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
);
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const patchKoaRouter = (
|
|
109
|
-
routerModule: any,
|
|
110
|
-
options?: SenzorOptions
|
|
111
|
-
) => {
|
|
112
|
-
const Router =
|
|
113
|
-
routerModule?.Router ||
|
|
114
|
-
routerModule?.default ||
|
|
115
|
-
routerModule;
|
|
116
|
-
const proto = Router?.prototype;
|
|
117
|
-
if (!proto) return;
|
|
118
|
-
|
|
119
|
-
patchMethod(
|
|
120
|
-
proto,
|
|
121
|
-
'use',
|
|
122
|
-
'senzor.koa.router.use',
|
|
123
|
-
(original) =>
|
|
124
|
-
function patchedKoaRouterUse(this: any, ...args: any[]) {
|
|
125
|
-
const layerPath = getPathFromArgs(args);
|
|
126
|
-
const nextArgs = args.map((arg) =>
|
|
127
|
-
typeof arg === 'function'
|
|
128
|
-
? wrapKoaMiddleware(arg, options, layerPath, 'router')
|
|
129
|
-
: arg
|
|
130
|
-
);
|
|
131
|
-
return original.apply(this, nextArgs);
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
for (const method of routerMethods) {
|
|
136
|
-
patchMethod(
|
|
137
|
-
proto,
|
|
138
|
-
method,
|
|
139
|
-
`senzor.koa.router.${method}`,
|
|
140
|
-
(original) =>
|
|
141
|
-
function patchedKoaRouterMethod(this: any, ...args: any[]) {
|
|
142
|
-
const layerPath = getPathFromArgs(args);
|
|
143
|
-
const nextArgs = args.map((arg) =>
|
|
144
|
-
typeof arg === 'function'
|
|
145
|
-
? wrapKoaMiddleware(
|
|
146
|
-
arg,
|
|
147
|
-
options,
|
|
148
|
-
layerPath,
|
|
149
|
-
'route_handler',
|
|
150
|
-
method.toUpperCase()
|
|
151
|
-
)
|
|
152
|
-
: arg
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
return original.apply(this, nextArgs);
|
|
156
|
-
}
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
export const instrumentKoa = (options?: SenzorOptions) => {
|
|
162
|
-
hookRequire('koa', (exports: any) => {
|
|
163
|
-
patchKoaApplication(exports, options);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
hookRequire('@koa/router', (exports: any) => {
|
|
167
|
-
patchKoaRouter(exports, options);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
hookRequire('koa-router', (exports: any) => {
|
|
171
|
-
patchKoaRouter(exports, options);
|
|
172
|
-
});
|
|
173
|
-
};
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { SenzorOptions } from '../core/types';
|
|
2
|
-
import { hookRequire } from './hook';
|
|
3
|
-
import { patchMethod } from './patch';
|
|
4
|
-
import { runWithCapturedSpan, startCapturedSpan } from './span';
|
|
5
|
-
|
|
6
|
-
const collectionName = (collection: any): string =>
|
|
7
|
-
collection?.collectionName ||
|
|
8
|
-
collection?.s?.namespace?.collection ||
|
|
9
|
-
collection?.namespace?.collection ||
|
|
10
|
-
'unknown';
|
|
11
|
-
|
|
12
|
-
const databaseName = (collection: any): string | undefined =>
|
|
13
|
-
collection?.dbName ||
|
|
14
|
-
collection?.s?.namespace?.db ||
|
|
15
|
-
collection?.namespace?.db;
|
|
16
|
-
|
|
17
|
-
const cursorCollectionName = (cursor: any): string =>
|
|
18
|
-
cursor?.namespace?.collection ||
|
|
19
|
-
cursor?.ns?.collection ||
|
|
20
|
-
cursor?.cursorNamespace?.collection ||
|
|
21
|
-
'unknown';
|
|
22
|
-
|
|
23
|
-
const patchCollectionMethod = (
|
|
24
|
-
proto: any,
|
|
25
|
-
method: string,
|
|
26
|
-
options?: SenzorOptions
|
|
27
|
-
) => {
|
|
28
|
-
patchMethod(
|
|
29
|
-
proto,
|
|
30
|
-
method,
|
|
31
|
-
`senzor.mongodb.collection.${method}`,
|
|
32
|
-
(original) =>
|
|
33
|
-
function patchedMongoCollection(this: any, ...args: any[]) {
|
|
34
|
-
const collection = collectionName(this);
|
|
35
|
-
const span = startCapturedSpan(
|
|
36
|
-
`MongoDB ${method}`,
|
|
37
|
-
'db',
|
|
38
|
-
{
|
|
39
|
-
collection,
|
|
40
|
-
operation: method,
|
|
41
|
-
'db.system.name': 'mongodb',
|
|
42
|
-
'db.collection.name': collection,
|
|
43
|
-
'db.namespace': databaseName(this)
|
|
44
|
-
? `${databaseName(this)}.${collection}`
|
|
45
|
-
: collection,
|
|
46
|
-
'db.operation.name': method,
|
|
47
|
-
library: 'mongodb'
|
|
48
|
-
},
|
|
49
|
-
options
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
if (!span) return original.apply(this, args);
|
|
53
|
-
|
|
54
|
-
return runWithCapturedSpan(span, () => {
|
|
55
|
-
try {
|
|
56
|
-
const result = original.apply(this, args);
|
|
57
|
-
if (result && typeof result.then === 'function') {
|
|
58
|
-
return result.then(
|
|
59
|
-
(value: any) => {
|
|
60
|
-
span.end(0, {
|
|
61
|
-
matchedCount: value?.matchedCount,
|
|
62
|
-
modifiedCount: value?.modifiedCount,
|
|
63
|
-
deletedCount: value?.deletedCount,
|
|
64
|
-
insertedCount: value?.insertedCount
|
|
65
|
-
});
|
|
66
|
-
return value;
|
|
67
|
-
},
|
|
68
|
-
(error: any) => {
|
|
69
|
-
span.end(500, {
|
|
70
|
-
error: error?.message,
|
|
71
|
-
'error.type': error?.name || 'Error'
|
|
72
|
-
});
|
|
73
|
-
throw error;
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
span.end(0);
|
|
79
|
-
return result;
|
|
80
|
-
} catch (error: any) {
|
|
81
|
-
span.end(500, {
|
|
82
|
-
error: error?.message,
|
|
83
|
-
'error.type': error?.name || 'Error'
|
|
84
|
-
});
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const patchCursorMethod = (
|
|
93
|
-
proto: any,
|
|
94
|
-
method: string,
|
|
95
|
-
operation: string,
|
|
96
|
-
options?: SenzorOptions
|
|
97
|
-
) => {
|
|
98
|
-
patchMethod(
|
|
99
|
-
proto,
|
|
100
|
-
method,
|
|
101
|
-
`senzor.mongodb.cursor.${operation}.${method}`,
|
|
102
|
-
(original) =>
|
|
103
|
-
function patchedMongoCursor(this: any, ...args: any[]) {
|
|
104
|
-
const collection = cursorCollectionName(this);
|
|
105
|
-
const span = startCapturedSpan(
|
|
106
|
-
`MongoDB ${operation}`,
|
|
107
|
-
'db',
|
|
108
|
-
{
|
|
109
|
-
collection,
|
|
110
|
-
operation,
|
|
111
|
-
'db.system.name': 'mongodb',
|
|
112
|
-
'db.collection.name': collection,
|
|
113
|
-
'db.operation.name': operation,
|
|
114
|
-
library: 'mongodb'
|
|
115
|
-
},
|
|
116
|
-
options
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
if (!span) return original.apply(this, args);
|
|
120
|
-
|
|
121
|
-
return runWithCapturedSpan(span, () => {
|
|
122
|
-
try {
|
|
123
|
-
const result = original.apply(this, args);
|
|
124
|
-
if (result && typeof result.then === 'function') {
|
|
125
|
-
return result.then(
|
|
126
|
-
(value: any) => {
|
|
127
|
-
span.end(0, {
|
|
128
|
-
resultCount: Array.isArray(value) ? value.length : undefined
|
|
129
|
-
});
|
|
130
|
-
return value;
|
|
131
|
-
},
|
|
132
|
-
(error: any) => {
|
|
133
|
-
span.end(500, {
|
|
134
|
-
error: error?.message,
|
|
135
|
-
'error.type': error?.name || 'Error'
|
|
136
|
-
});
|
|
137
|
-
throw error;
|
|
138
|
-
}
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
span.end(0);
|
|
143
|
-
return result;
|
|
144
|
-
} catch (error: any) {
|
|
145
|
-
span.end(500, {
|
|
146
|
-
error: error?.message,
|
|
147
|
-
'error.type': error?.name || 'Error'
|
|
148
|
-
});
|
|
149
|
-
throw error;
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const patchMongo = (mongodb: any, options?: SenzorOptions) => {
|
|
157
|
-
const Collection = mongodb?.Collection || mongodb?.default?.Collection;
|
|
158
|
-
const collectionProto = Collection?.prototype;
|
|
159
|
-
|
|
160
|
-
[
|
|
161
|
-
'insertOne',
|
|
162
|
-
'insertMany',
|
|
163
|
-
'updateOne',
|
|
164
|
-
'updateMany',
|
|
165
|
-
'replaceOne',
|
|
166
|
-
'deleteOne',
|
|
167
|
-
'deleteMany',
|
|
168
|
-
'findOne',
|
|
169
|
-
'findOneAndUpdate',
|
|
170
|
-
'findOneAndDelete',
|
|
171
|
-
'findOneAndReplace',
|
|
172
|
-
'countDocuments',
|
|
173
|
-
'estimatedDocumentCount',
|
|
174
|
-
'distinct',
|
|
175
|
-
'bulkWrite',
|
|
176
|
-
'createIndex',
|
|
177
|
-
'dropIndex'
|
|
178
|
-
].forEach((method) =>
|
|
179
|
-
patchCollectionMethod(collectionProto, method, options)
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
const FindCursor =
|
|
183
|
-
mongodb?.FindCursor || mongodb?.default?.FindCursor;
|
|
184
|
-
const AggregationCursor =
|
|
185
|
-
mongodb?.AggregationCursor || mongodb?.default?.AggregationCursor;
|
|
186
|
-
|
|
187
|
-
['toArray', 'next', 'forEach'].forEach((method) =>
|
|
188
|
-
patchCursorMethod(FindCursor?.prototype, method, 'find', options)
|
|
189
|
-
);
|
|
190
|
-
['toArray', 'next', 'forEach'].forEach((method) =>
|
|
191
|
-
patchCursorMethod(
|
|
192
|
-
AggregationCursor?.prototype,
|
|
193
|
-
method,
|
|
194
|
-
'aggregate',
|
|
195
|
-
options
|
|
196
|
-
)
|
|
197
|
-
);
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
export const instrumentMongo = (options?: SenzorOptions) => {
|
|
201
|
-
hookRequire('mongodb', (exports: any) => patchMongo(exports, options));
|
|
202
|
-
};
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { SenzorOptions } from '../core/types';
|
|
2
|
-
import { hookRequire } from './hook';
|
|
3
|
-
import { patchMethod } from './patch';
|
|
4
|
-
import { runWithCapturedSpan, startCapturedSpan } from './span';
|
|
5
|
-
|
|
6
|
-
const modelName = (target: any): string =>
|
|
7
|
-
target?.model?.modelName ||
|
|
8
|
-
target?.constructor?.modelName ||
|
|
9
|
-
target?.modelName ||
|
|
10
|
-
'unknown';
|
|
11
|
-
|
|
12
|
-
const collectionName = (target: any): string =>
|
|
13
|
-
target?.mongooseCollection?.name ||
|
|
14
|
-
target?.collection?.name ||
|
|
15
|
-
target?.model?.collection?.name ||
|
|
16
|
-
'unknown';
|
|
17
|
-
|
|
18
|
-
const patchExec = (
|
|
19
|
-
proto: any,
|
|
20
|
-
label: 'query' | 'aggregate',
|
|
21
|
-
options?: SenzorOptions
|
|
22
|
-
) => {
|
|
23
|
-
patchMethod(
|
|
24
|
-
proto,
|
|
25
|
-
'exec',
|
|
26
|
-
`senzor.mongoose.${label}.exec`,
|
|
27
|
-
(original) =>
|
|
28
|
-
function patchedMongooseExec(this: any, ...args: any[]) {
|
|
29
|
-
const operation =
|
|
30
|
-
String(this?.op || this?._op || label).toUpperCase();
|
|
31
|
-
const collection = collectionName(this);
|
|
32
|
-
const span = startCapturedSpan(
|
|
33
|
-
`Mongoose ${operation}`,
|
|
34
|
-
'db',
|
|
35
|
-
{
|
|
36
|
-
collection,
|
|
37
|
-
model: modelName(this),
|
|
38
|
-
operation,
|
|
39
|
-
'db.system.name': 'mongodb',
|
|
40
|
-
'db.collection.name': collection,
|
|
41
|
-
'db.operation.name': operation,
|
|
42
|
-
library: 'mongoose'
|
|
43
|
-
},
|
|
44
|
-
options
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
if (!span) return original.apply(this, args);
|
|
48
|
-
|
|
49
|
-
return runWithCapturedSpan(span, () => {
|
|
50
|
-
try {
|
|
51
|
-
const result = original.apply(this, args);
|
|
52
|
-
if (result && typeof result.then === 'function') {
|
|
53
|
-
return result.then(
|
|
54
|
-
(value: any) => {
|
|
55
|
-
span.end(0, {
|
|
56
|
-
resultCount: Array.isArray(value) ? value.length : undefined
|
|
57
|
-
});
|
|
58
|
-
return value;
|
|
59
|
-
},
|
|
60
|
-
(error: any) => {
|
|
61
|
-
span.end(500, {
|
|
62
|
-
error: error?.message,
|
|
63
|
-
'error.type': error?.name || 'Error'
|
|
64
|
-
});
|
|
65
|
-
throw error;
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
span.end(0);
|
|
71
|
-
return result;
|
|
72
|
-
} catch (error: any) {
|
|
73
|
-
span.end(500, {
|
|
74
|
-
error: error?.message,
|
|
75
|
-
'error.type': error?.name || 'Error'
|
|
76
|
-
});
|
|
77
|
-
throw error;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const patchSave = (modelProto: any, options?: SenzorOptions) => {
|
|
85
|
-
patchMethod(
|
|
86
|
-
modelProto,
|
|
87
|
-
'save',
|
|
88
|
-
'senzor.mongoose.model.save',
|
|
89
|
-
(original) =>
|
|
90
|
-
function patchedMongooseSave(this: any, ...args: any[]) {
|
|
91
|
-
const collection = collectionName(this);
|
|
92
|
-
const span = startCapturedSpan(
|
|
93
|
-
'Mongoose SAVE',
|
|
94
|
-
'db',
|
|
95
|
-
{
|
|
96
|
-
collection,
|
|
97
|
-
model: modelName(this),
|
|
98
|
-
operation: 'SAVE',
|
|
99
|
-
'db.system.name': 'mongodb',
|
|
100
|
-
'db.collection.name': collection,
|
|
101
|
-
'db.operation.name': 'SAVE',
|
|
102
|
-
library: 'mongoose'
|
|
103
|
-
},
|
|
104
|
-
options
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
if (!span) return original.apply(this, args);
|
|
108
|
-
|
|
109
|
-
return runWithCapturedSpan(span, () => {
|
|
110
|
-
try {
|
|
111
|
-
const result = original.apply(this, args);
|
|
112
|
-
if (result && typeof result.then === 'function') {
|
|
113
|
-
return result.then(
|
|
114
|
-
(value: any) => {
|
|
115
|
-
span.end(0);
|
|
116
|
-
return value;
|
|
117
|
-
},
|
|
118
|
-
(error: any) => {
|
|
119
|
-
span.end(500, {
|
|
120
|
-
error: error?.message,
|
|
121
|
-
'error.type': error?.name || 'Error'
|
|
122
|
-
});
|
|
123
|
-
throw error;
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
span.end(0);
|
|
129
|
-
return result;
|
|
130
|
-
} catch (error: any) {
|
|
131
|
-
span.end(500, {
|
|
132
|
-
error: error?.message,
|
|
133
|
-
'error.type': error?.name || 'Error'
|
|
134
|
-
});
|
|
135
|
-
throw error;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
);
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
const patchMongoose = (mongoose: any, options?: SenzorOptions) => {
|
|
143
|
-
patchExec(mongoose?.Query?.prototype, 'query', options);
|
|
144
|
-
patchExec(mongoose?.Aggregate?.prototype, 'aggregate', options);
|
|
145
|
-
patchSave(mongoose?.Model?.prototype, options);
|
|
146
|
-
|
|
147
|
-
if (mongoose?.default) {
|
|
148
|
-
patchExec(mongoose.default?.Query?.prototype, 'query', options);
|
|
149
|
-
patchExec(mongoose.default?.Aggregate?.prototype, 'aggregate', options);
|
|
150
|
-
patchSave(mongoose.default?.Model?.prototype, options);
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
export const instrumentMongoose = (options?: SenzorOptions) => {
|
|
155
|
-
hookRequire('mongoose', (exports: any) => patchMongoose(exports, options));
|
|
156
|
-
};
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { getSqlOperation, normalizeSql } from '../core/sanitizer';
|
|
2
|
-
import { SenzorOptions } from '../core/types';
|
|
3
|
-
import { hookRequire } from './hook';
|
|
4
|
-
import { patchMethod } from './patch';
|
|
5
|
-
import { runWithCapturedSpan, startCapturedSpan } from './span';
|
|
6
|
-
|
|
7
|
-
const extractSql = (args: any[]): string | undefined => {
|
|
8
|
-
const first = args[0];
|
|
9
|
-
if (typeof first === 'string') return first;
|
|
10
|
-
if (first && typeof first.sql === 'string') return first.sql;
|
|
11
|
-
return undefined;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const patchSqlMethod = (
|
|
15
|
-
proto: any,
|
|
16
|
-
method: 'query' | 'execute',
|
|
17
|
-
library: string,
|
|
18
|
-
options?: SenzorOptions
|
|
19
|
-
) => {
|
|
20
|
-
patchMethod(
|
|
21
|
-
proto,
|
|
22
|
-
method,
|
|
23
|
-
`senzor.${library}.${method}`,
|
|
24
|
-
(original) =>
|
|
25
|
-
function patchedMysqlMethod(this: any, ...args: any[]) {
|
|
26
|
-
const sql = extractSql(args);
|
|
27
|
-
const operation = getSqlOperation(sql) || method.toUpperCase();
|
|
28
|
-
const span = startCapturedSpan(
|
|
29
|
-
`MySQL ${operation}`,
|
|
30
|
-
'db',
|
|
31
|
-
{
|
|
32
|
-
query: normalizeSql(sql, options),
|
|
33
|
-
operation,
|
|
34
|
-
'db.system.name': 'mysql',
|
|
35
|
-
'db.operation.name': operation,
|
|
36
|
-
'db.query.text': normalizeSql(sql, options),
|
|
37
|
-
library
|
|
38
|
-
},
|
|
39
|
-
options
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
if (!span) return original.apply(this, args);
|
|
43
|
-
|
|
44
|
-
const callbackIndex = args.findIndex(
|
|
45
|
-
(arg) => typeof arg === 'function'
|
|
46
|
-
);
|
|
47
|
-
if (callbackIndex >= 0) {
|
|
48
|
-
const originalCallback = args[callbackIndex];
|
|
49
|
-
args[callbackIndex] = function wrappedMysqlCallback(
|
|
50
|
-
this: unknown,
|
|
51
|
-
err: any,
|
|
52
|
-
rows: any
|
|
53
|
-
) {
|
|
54
|
-
span.end(err ? 500 : 0, {
|
|
55
|
-
error: err?.message,
|
|
56
|
-
'error.type': err?.name,
|
|
57
|
-
rowCount: Array.isArray(rows) ? rows.length : undefined
|
|
58
|
-
});
|
|
59
|
-
return originalCallback.apply(this, arguments as any);
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return runWithCapturedSpan(span, () => {
|
|
64
|
-
try {
|
|
65
|
-
const result = original.apply(this, args);
|
|
66
|
-
|
|
67
|
-
if (result && typeof result.then === 'function') {
|
|
68
|
-
return result.then(
|
|
69
|
-
(value: any) => {
|
|
70
|
-
const rows = Array.isArray(value) ? value[0] : value;
|
|
71
|
-
span.end(0, {
|
|
72
|
-
rowCount: Array.isArray(rows) ? rows.length : undefined
|
|
73
|
-
});
|
|
74
|
-
return value;
|
|
75
|
-
},
|
|
76
|
-
(error: any) => {
|
|
77
|
-
span.end(500, {
|
|
78
|
-
error: error?.message,
|
|
79
|
-
'error.type': error?.name || 'Error'
|
|
80
|
-
});
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (
|
|
87
|
-
callbackIndex < 0 &&
|
|
88
|
-
result &&
|
|
89
|
-
typeof result.once === 'function'
|
|
90
|
-
) {
|
|
91
|
-
result.once('end', () => span.end(0));
|
|
92
|
-
result.once('error', (error: Error) =>
|
|
93
|
-
span.end(500, {
|
|
94
|
-
error: error.message,
|
|
95
|
-
'error.type': error.name
|
|
96
|
-
})
|
|
97
|
-
);
|
|
98
|
-
} else if (callbackIndex < 0) {
|
|
99
|
-
span.end(0);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return result;
|
|
103
|
-
} catch (error: any) {
|
|
104
|
-
span.end(500, {
|
|
105
|
-
error: error?.message,
|
|
106
|
-
'error.type': error?.name || 'Error'
|
|
107
|
-
});
|
|
108
|
-
throw error;
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const patchKnownPrototypes = (
|
|
116
|
-
mysql: any,
|
|
117
|
-
library: string,
|
|
118
|
-
options?: SenzorOptions
|
|
119
|
-
) => {
|
|
120
|
-
[
|
|
121
|
-
mysql?.Connection?.prototype,
|
|
122
|
-
mysql?.Pool?.prototype,
|
|
123
|
-
mysql?.PoolConnection?.prototype,
|
|
124
|
-
mysql?.PromiseConnection?.prototype,
|
|
125
|
-
mysql?.PromisePool?.prototype,
|
|
126
|
-
mysql?.default?.Connection?.prototype,
|
|
127
|
-
mysql?.default?.Pool?.prototype
|
|
128
|
-
].forEach((proto) => {
|
|
129
|
-
patchSqlMethod(proto, 'query', library, options);
|
|
130
|
-
patchSqlMethod(proto, 'execute', library, options);
|
|
131
|
-
});
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const patchFactories = (
|
|
135
|
-
mysql: any,
|
|
136
|
-
library: string,
|
|
137
|
-
options?: SenzorOptions
|
|
138
|
-
) => {
|
|
139
|
-
['createConnection', 'createPool'].forEach((factory) => {
|
|
140
|
-
patchMethod(
|
|
141
|
-
mysql,
|
|
142
|
-
factory,
|
|
143
|
-
`senzor.${library}.${factory}`,
|
|
144
|
-
(original) =>
|
|
145
|
-
function patchedMysqlFactory(this: any, ...args: any[]) {
|
|
146
|
-
const client = original.apply(this, args);
|
|
147
|
-
patchSqlMethod(client, 'query', library, options);
|
|
148
|
-
patchSqlMethod(client, 'execute', library, options);
|
|
149
|
-
patchSqlMethod(Object.getPrototypeOf(client), 'query', library, options);
|
|
150
|
-
patchSqlMethod(Object.getPrototypeOf(client), 'execute', library, options);
|
|
151
|
-
return client;
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const patchMysql = (
|
|
158
|
-
mysql: any,
|
|
159
|
-
library: string,
|
|
160
|
-
options?: SenzorOptions
|
|
161
|
-
) => {
|
|
162
|
-
patchKnownPrototypes(mysql, library, options);
|
|
163
|
-
patchFactories(mysql, library, options);
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
export const instrumentMysql = (options?: SenzorOptions) => {
|
|
167
|
-
hookRequire('mysql', (exports: any) => patchMysql(exports, 'mysql', options));
|
|
168
|
-
hookRequire('mysql2', (exports: any) => patchMysql(exports, 'mysql2', options));
|
|
169
|
-
};
|