autotel-mongoose 0.0.1
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/README.md +150 -0
- package/dist/index.cjs +596 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +594 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
- package/src/config-custom.integration.test.ts +91 -0
- package/src/config-disabled.integration.test.ts +79 -0
- package/src/constants.ts +11 -0
- package/src/index.ts +3 -0
- package/src/instrumentation.integration.test.ts +202 -0
- package/src/instrumentation.ts +880 -0
- package/src/statement.test.ts +78 -0
- package/src/statement.ts +58 -0
- package/src/test-support.ts +32 -0
- package/src/types.ts +74 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var autotel = require('autotel');
|
|
4
|
+
var traceHelpers = require('autotel/trace-helpers');
|
|
5
|
+
|
|
6
|
+
// src/instrumentation.ts
|
|
7
|
+
|
|
8
|
+
// src/constants.ts
|
|
9
|
+
var ATTR_DB_QUERY_TEXT = "db.query.text";
|
|
10
|
+
var ATTR_DB_OPERATION_NAME = "db.operation.name";
|
|
11
|
+
var ATTR_DB_SYSTEM_NAME = "db.system.name";
|
|
12
|
+
var ATTR_DB_COLLECTION_NAME = "db.collection.name";
|
|
13
|
+
var ATTR_DB_NAMESPACE = "db.namespace";
|
|
14
|
+
var ATTR_SERVER_ADDRESS = "server.address";
|
|
15
|
+
var ATTR_SERVER_PORT = "server.port";
|
|
16
|
+
var DB_SYSTEM_NAME_VALUE_MONGODB = "mongodb";
|
|
17
|
+
|
|
18
|
+
// src/types.ts
|
|
19
|
+
var DEFAULT_TRACER_NAME = "autotel-mongoose";
|
|
20
|
+
function defaultSerializer(_operation, payload) {
|
|
21
|
+
return JSON.stringify(payload);
|
|
22
|
+
}
|
|
23
|
+
function createStatementCapture(config) {
|
|
24
|
+
if (config.dbStatementSerializer === false) {
|
|
25
|
+
return () => {
|
|
26
|
+
return;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const serializer = typeof config.dbStatementSerializer === "function" ? config.dbStatementSerializer : defaultSerializer;
|
|
30
|
+
let redact;
|
|
31
|
+
if (config.statementRedactor !== false && config.statementRedactor !== void 0) {
|
|
32
|
+
redact = autotel.createStringRedactor(config.statementRedactor);
|
|
33
|
+
}
|
|
34
|
+
return (operation, payload) => {
|
|
35
|
+
const raw = serializer(operation, payload);
|
|
36
|
+
if (raw === void 0) {
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
39
|
+
return redact ? redact(raw) : raw;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/instrumentation.ts
|
|
44
|
+
var INSTRUMENTED_FLAG = "__autotelMongooseInstrumented";
|
|
45
|
+
var WRAPPED_HOOK_FLAG = "__autotelWrappedHook";
|
|
46
|
+
var _STORED_PARENT_SPAN = /* @__PURE__ */ Symbol("stored-parent-span");
|
|
47
|
+
function createSpan(tracer, operation, modelName, collectionName, config) {
|
|
48
|
+
const spanName = collectionName ? `${operation} ${collectionName}` : modelName ? `${operation} ${modelName}` : `mongoose.${operation}`;
|
|
49
|
+
const attributes = {
|
|
50
|
+
[ATTR_DB_SYSTEM_NAME]: DB_SYSTEM_NAME_VALUE_MONGODB,
|
|
51
|
+
[ATTR_DB_OPERATION_NAME]: operation
|
|
52
|
+
};
|
|
53
|
+
if (collectionName && config.captureCollectionName) {
|
|
54
|
+
attributes[ATTR_DB_COLLECTION_NAME] = collectionName;
|
|
55
|
+
}
|
|
56
|
+
if (config.dbName) {
|
|
57
|
+
attributes[ATTR_DB_NAMESPACE] = config.dbName;
|
|
58
|
+
}
|
|
59
|
+
if (config.peerName) {
|
|
60
|
+
attributes[ATTR_SERVER_ADDRESS] = config.peerName;
|
|
61
|
+
}
|
|
62
|
+
if (config.peerPort) {
|
|
63
|
+
attributes[ATTR_SERVER_PORT] = config.peerPort;
|
|
64
|
+
}
|
|
65
|
+
return tracer.startSpan(spanName, { kind: autotel.SpanKind.CLIENT, attributes });
|
|
66
|
+
}
|
|
67
|
+
function wrapQueryReturningMethod(target, methodName, operation, getCollectionName, getModelName, tracer, config, captureStatement) {
|
|
68
|
+
const original = target[methodName];
|
|
69
|
+
if (typeof original !== "function") {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
target[methodName] = function instrumented(...args) {
|
|
73
|
+
const collectionName = getCollectionName(this);
|
|
74
|
+
const modelName = getModelName(this);
|
|
75
|
+
const span = createSpan(
|
|
76
|
+
tracer,
|
|
77
|
+
operation,
|
|
78
|
+
modelName,
|
|
79
|
+
collectionName,
|
|
80
|
+
config
|
|
81
|
+
);
|
|
82
|
+
return traceHelpers.runWithSpan(span, () => {
|
|
83
|
+
try {
|
|
84
|
+
const result = original.apply(this, args);
|
|
85
|
+
if (result && typeof result.exec === "function") {
|
|
86
|
+
try {
|
|
87
|
+
const payload = {};
|
|
88
|
+
if (typeof result.getFilter === "function") {
|
|
89
|
+
payload.condition = result.getFilter();
|
|
90
|
+
}
|
|
91
|
+
if (result._update !== void 0) {
|
|
92
|
+
payload.updates = result._update;
|
|
93
|
+
}
|
|
94
|
+
if (typeof result.getOptions === "function") {
|
|
95
|
+
payload.options = result.getOptions();
|
|
96
|
+
}
|
|
97
|
+
if (result._fields !== void 0) {
|
|
98
|
+
payload.fields = result._fields;
|
|
99
|
+
}
|
|
100
|
+
const statementText = captureStatement(operation, payload);
|
|
101
|
+
if (statementText) {
|
|
102
|
+
span.setAttribute(ATTR_DB_QUERY_TEXT, statementText);
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
}
|
|
106
|
+
const originalExec = result.exec.bind(result);
|
|
107
|
+
result.exec = function wrappedExec() {
|
|
108
|
+
try {
|
|
109
|
+
const execPromise = originalExec();
|
|
110
|
+
return Promise.resolve(execPromise).then((value) => {
|
|
111
|
+
traceHelpers.finalizeSpan(span);
|
|
112
|
+
return value;
|
|
113
|
+
}).catch((error) => {
|
|
114
|
+
traceHelpers.finalizeSpan(
|
|
115
|
+
span,
|
|
116
|
+
error instanceof Error ? error : new Error(String(error))
|
|
117
|
+
);
|
|
118
|
+
throw error;
|
|
119
|
+
});
|
|
120
|
+
} catch (error) {
|
|
121
|
+
traceHelpers.finalizeSpan(
|
|
122
|
+
span,
|
|
123
|
+
error instanceof Error ? error : new Error(String(error))
|
|
124
|
+
);
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
traceHelpers.finalizeSpan(span);
|
|
131
|
+
return result;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
traceHelpers.finalizeSpan(
|
|
134
|
+
span,
|
|
135
|
+
error instanceof Error ? error : new Error(String(error))
|
|
136
|
+
);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function wrapStaticMethod(target, methodName, operation, getCollectionName, getModelName, tracer, config, captureStatement) {
|
|
143
|
+
const original = target[methodName];
|
|
144
|
+
if (typeof original !== "function") {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
target[methodName] = function instrumented(...args) {
|
|
148
|
+
const collectionName = getCollectionName(this);
|
|
149
|
+
const modelName = getModelName(this);
|
|
150
|
+
const payload = {};
|
|
151
|
+
try {
|
|
152
|
+
switch (operation) {
|
|
153
|
+
case "create": {
|
|
154
|
+
payload.document = args[0];
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
case "insertMany": {
|
|
158
|
+
payload.documents = args[0];
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case "aggregate": {
|
|
162
|
+
payload.aggregatePipeline = args[0];
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case "bulkWrite": {
|
|
166
|
+
payload.operations = args[0];
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
default: {
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} catch {
|
|
174
|
+
}
|
|
175
|
+
const span = createSpan(
|
|
176
|
+
tracer,
|
|
177
|
+
operation,
|
|
178
|
+
modelName,
|
|
179
|
+
collectionName,
|
|
180
|
+
config
|
|
181
|
+
);
|
|
182
|
+
try {
|
|
183
|
+
const statementText = captureStatement(operation, payload);
|
|
184
|
+
if (statementText) {
|
|
185
|
+
span.setAttribute(ATTR_DB_QUERY_TEXT, statementText);
|
|
186
|
+
}
|
|
187
|
+
} catch {
|
|
188
|
+
}
|
|
189
|
+
return traceHelpers.runWithSpan(span, () => {
|
|
190
|
+
try {
|
|
191
|
+
const result = original.apply(this, args);
|
|
192
|
+
if (result && typeof result.exec === "function") {
|
|
193
|
+
const originalExec = result.exec.bind(result);
|
|
194
|
+
result.exec = function wrappedExec() {
|
|
195
|
+
try {
|
|
196
|
+
const execPromise = originalExec();
|
|
197
|
+
return Promise.resolve(execPromise).then((value) => {
|
|
198
|
+
traceHelpers.finalizeSpan(span);
|
|
199
|
+
return value;
|
|
200
|
+
}).catch((error) => {
|
|
201
|
+
traceHelpers.finalizeSpan(
|
|
202
|
+
span,
|
|
203
|
+
error instanceof Error ? error : new Error(String(error))
|
|
204
|
+
);
|
|
205
|
+
throw error;
|
|
206
|
+
});
|
|
207
|
+
} catch (error) {
|
|
208
|
+
traceHelpers.finalizeSpan(
|
|
209
|
+
span,
|
|
210
|
+
error instanceof Error ? error : new Error(String(error))
|
|
211
|
+
);
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
if (result && typeof result.then === "function") {
|
|
218
|
+
return Promise.resolve(result).then((value) => {
|
|
219
|
+
traceHelpers.finalizeSpan(span);
|
|
220
|
+
return value;
|
|
221
|
+
}).catch((error) => {
|
|
222
|
+
traceHelpers.finalizeSpan(
|
|
223
|
+
span,
|
|
224
|
+
error instanceof Error ? error : new Error(String(error))
|
|
225
|
+
);
|
|
226
|
+
throw error;
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
traceHelpers.finalizeSpan(span);
|
|
230
|
+
return result;
|
|
231
|
+
} catch (error) {
|
|
232
|
+
traceHelpers.finalizeSpan(
|
|
233
|
+
span,
|
|
234
|
+
error instanceof Error ? error : new Error(String(error))
|
|
235
|
+
);
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function wrapInstanceMethod(target, methodName, operation, getCollectionName, getModelName, tracer, config, captureStatement) {
|
|
242
|
+
const original = target[methodName];
|
|
243
|
+
if (typeof original !== "function") {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
target[methodName] = function instrumented(...args) {
|
|
247
|
+
const collectionName = getCollectionName(this);
|
|
248
|
+
const modelName = getModelName(this);
|
|
249
|
+
const payload = {};
|
|
250
|
+
try {
|
|
251
|
+
if (typeof this.toObject === "function") {
|
|
252
|
+
payload.document = this.toObject();
|
|
253
|
+
}
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
256
|
+
const span = createSpan(
|
|
257
|
+
tracer,
|
|
258
|
+
operation,
|
|
259
|
+
modelName,
|
|
260
|
+
collectionName,
|
|
261
|
+
config
|
|
262
|
+
);
|
|
263
|
+
try {
|
|
264
|
+
const statementText = captureStatement(operation, payload);
|
|
265
|
+
if (statementText) {
|
|
266
|
+
span.setAttribute(ATTR_DB_QUERY_TEXT, statementText);
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
return traceHelpers.runWithSpan(span, () => {
|
|
271
|
+
try {
|
|
272
|
+
const result = original.apply(this, args);
|
|
273
|
+
if (result && typeof result.then === "function") {
|
|
274
|
+
return Promise.resolve(result).then((value) => {
|
|
275
|
+
traceHelpers.finalizeSpan(span);
|
|
276
|
+
return value;
|
|
277
|
+
}).catch((error) => {
|
|
278
|
+
traceHelpers.finalizeSpan(
|
|
279
|
+
span,
|
|
280
|
+
error instanceof Error ? error : new Error(String(error))
|
|
281
|
+
);
|
|
282
|
+
throw error;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
traceHelpers.finalizeSpan(span);
|
|
286
|
+
return result;
|
|
287
|
+
} catch (error) {
|
|
288
|
+
traceHelpers.finalizeSpan(
|
|
289
|
+
span,
|
|
290
|
+
error instanceof Error ? error : new Error(String(error))
|
|
291
|
+
);
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
function wrapChainableMethod(target, methodName) {
|
|
298
|
+
const original = target[methodName];
|
|
299
|
+
if (typeof original !== "function") {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
target[methodName] = function captureContext(...args) {
|
|
303
|
+
const currentSpan = traceHelpers.getActiveSpan();
|
|
304
|
+
const result = original.apply(this, args);
|
|
305
|
+
if (result && typeof result.exec === "function") {
|
|
306
|
+
result[_STORED_PARENT_SPAN] = currentSpan;
|
|
307
|
+
}
|
|
308
|
+
return result;
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function patchSchemaHooks(Schema, tracer, config) {
|
|
312
|
+
if (!Schema?.prototype) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
const HOOK_FLAG = "__autotelHookInstrumented";
|
|
316
|
+
if (Schema.prototype[HOOK_FLAG]) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const originalPre = Schema.prototype.pre;
|
|
320
|
+
if (typeof originalPre === "function") {
|
|
321
|
+
Schema.prototype.pre = function(hookName, ...args) {
|
|
322
|
+
const handler = typeof args[0] === "function" ? args[0] : typeof args[1] === "function" ? args[1] : null;
|
|
323
|
+
if (handler && !isMongooseInternalHook(handler)) {
|
|
324
|
+
const wrapped = wrapHookHandler(
|
|
325
|
+
handler,
|
|
326
|
+
hookName,
|
|
327
|
+
"pre",
|
|
328
|
+
tracer,
|
|
329
|
+
config
|
|
330
|
+
);
|
|
331
|
+
if (typeof args[0] === "function") {
|
|
332
|
+
args[0] = wrapped;
|
|
333
|
+
} else if (typeof args[1] === "function") {
|
|
334
|
+
args[1] = wrapped;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return Reflect.apply(originalPre, this, [hookName, ...args]);
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
const originalPost = Schema.prototype.post;
|
|
341
|
+
if (typeof originalPost === "function") {
|
|
342
|
+
Schema.prototype.post = function(hookName, ...args) {
|
|
343
|
+
const handler = typeof args[0] === "function" ? args[0] : typeof args[1] === "function" ? args[1] : null;
|
|
344
|
+
if (handler && !isMongooseInternalHook(handler)) {
|
|
345
|
+
const wrapped = wrapHookHandler(
|
|
346
|
+
handler,
|
|
347
|
+
hookName,
|
|
348
|
+
"post",
|
|
349
|
+
tracer,
|
|
350
|
+
config
|
|
351
|
+
);
|
|
352
|
+
if (typeof args[0] === "function") {
|
|
353
|
+
args[0] = wrapped;
|
|
354
|
+
} else if (typeof args[1] === "function") {
|
|
355
|
+
args[1] = wrapped;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return Reflect.apply(originalPost, this, [hookName, ...args]);
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
Schema.prototype[HOOK_FLAG] = true;
|
|
362
|
+
}
|
|
363
|
+
function isMongooseInternalHook(handler) {
|
|
364
|
+
if (typeof handler !== "function") {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
const funcName = handler.name || "";
|
|
368
|
+
if (funcName.startsWith("_") || funcName.startsWith("$")) {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
const mongooseInternalNamePatterns = [
|
|
372
|
+
"shardingPlugin",
|
|
373
|
+
"mongooseInternalHook",
|
|
374
|
+
"noop",
|
|
375
|
+
"wrapped",
|
|
376
|
+
"bound "
|
|
377
|
+
];
|
|
378
|
+
if (mongooseInternalNamePatterns.some((pattern) => funcName.includes(pattern))) {
|
|
379
|
+
return true;
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const source = handler.toString();
|
|
383
|
+
const mongooseInternalSourcePatterns = [
|
|
384
|
+
"this.$__",
|
|
385
|
+
// Mongoose internal document methods
|
|
386
|
+
"this.$isValid",
|
|
387
|
+
// Mongoose validation
|
|
388
|
+
"this.$locals",
|
|
389
|
+
// Mongoose local properties
|
|
390
|
+
"_this.$__",
|
|
391
|
+
// Mongoose internal with closure
|
|
392
|
+
"schema.s.hooks",
|
|
393
|
+
// Mongoose hooks system
|
|
394
|
+
"kareem"
|
|
395
|
+
// Mongoose's hooks library
|
|
396
|
+
];
|
|
397
|
+
if (mongooseInternalSourcePatterns.some((pattern) => source.includes(pattern))) {
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
function wrapHookHandler(handler, hookName, hookType, tracer, config) {
|
|
405
|
+
if (typeof handler !== "function") {
|
|
406
|
+
return handler;
|
|
407
|
+
}
|
|
408
|
+
if (handler[WRAPPED_HOOK_FLAG]) {
|
|
409
|
+
return handler;
|
|
410
|
+
}
|
|
411
|
+
const wrappedHook = function wrappedHook2(...args) {
|
|
412
|
+
let modelName;
|
|
413
|
+
let collectionName;
|
|
414
|
+
try {
|
|
415
|
+
if (this.constructor?.modelName) {
|
|
416
|
+
modelName = this.constructor.modelName;
|
|
417
|
+
collectionName = this.constructor.collection?.collectionName || modelName;
|
|
418
|
+
} else if (this.model?.modelName) {
|
|
419
|
+
modelName = this.model.modelName;
|
|
420
|
+
collectionName = this.model.collection?.collectionName || modelName;
|
|
421
|
+
}
|
|
422
|
+
} catch {
|
|
423
|
+
}
|
|
424
|
+
const spanName = collectionName ? `mongoose.${collectionName}.${hookType}.${hookName}` : `mongoose.hook.${hookType}.${hookName}`;
|
|
425
|
+
const span = tracer.startSpan(spanName, { kind: autotel.SpanKind.INTERNAL });
|
|
426
|
+
span.setAttribute("hook.type", hookType);
|
|
427
|
+
span.setAttribute("hook.operation", hookName);
|
|
428
|
+
if (modelName) {
|
|
429
|
+
span.setAttribute("hook.model", modelName);
|
|
430
|
+
}
|
|
431
|
+
if (collectionName && config.captureCollectionName) {
|
|
432
|
+
span.setAttribute(ATTR_DB_COLLECTION_NAME, collectionName);
|
|
433
|
+
}
|
|
434
|
+
span.setAttribute(ATTR_DB_SYSTEM_NAME, DB_SYSTEM_NAME_VALUE_MONGODB);
|
|
435
|
+
if (config.dbName) {
|
|
436
|
+
span.setAttribute(ATTR_DB_NAMESPACE, config.dbName);
|
|
437
|
+
}
|
|
438
|
+
return traceHelpers.runWithSpan(span, () => {
|
|
439
|
+
try {
|
|
440
|
+
const result = handler.apply(this, args);
|
|
441
|
+
if (result && typeof result.then === "function") {
|
|
442
|
+
return Promise.resolve(result).then((value) => {
|
|
443
|
+
traceHelpers.finalizeSpan(span);
|
|
444
|
+
return value;
|
|
445
|
+
}).catch((error) => {
|
|
446
|
+
traceHelpers.finalizeSpan(
|
|
447
|
+
span,
|
|
448
|
+
error instanceof Error ? error : new Error(String(error))
|
|
449
|
+
);
|
|
450
|
+
throw error;
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
traceHelpers.finalizeSpan(span);
|
|
454
|
+
return result;
|
|
455
|
+
} catch (error) {
|
|
456
|
+
traceHelpers.finalizeSpan(
|
|
457
|
+
span,
|
|
458
|
+
error instanceof Error ? error : new Error(String(error))
|
|
459
|
+
);
|
|
460
|
+
throw error;
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
};
|
|
464
|
+
wrappedHook[WRAPPED_HOOK_FLAG] = true;
|
|
465
|
+
return wrappedHook;
|
|
466
|
+
}
|
|
467
|
+
function instrumentMongoose(mongoose, config) {
|
|
468
|
+
if (!mongoose?.Model) {
|
|
469
|
+
return mongoose;
|
|
470
|
+
}
|
|
471
|
+
const m = mongoose;
|
|
472
|
+
if (m[INSTRUMENTED_FLAG]) {
|
|
473
|
+
return mongoose;
|
|
474
|
+
}
|
|
475
|
+
const resolvedSerializer = config?.dbStatementSerializer;
|
|
476
|
+
const resolvedRedactor = config?.statementRedactor ?? "default";
|
|
477
|
+
const finalConfig = {
|
|
478
|
+
dbName: config?.dbName || "",
|
|
479
|
+
peerName: config?.peerName || "",
|
|
480
|
+
peerPort: config?.peerPort || 27017,
|
|
481
|
+
tracerName: config?.tracerName || DEFAULT_TRACER_NAME,
|
|
482
|
+
captureCollectionName: config?.captureCollectionName ?? true,
|
|
483
|
+
instrumentHooks: config?.instrumentHooks ?? false};
|
|
484
|
+
const tracer = autotel.otelTrace.getTracer(finalConfig.tracerName);
|
|
485
|
+
const captureStatement = createStatementCapture({
|
|
486
|
+
dbStatementSerializer: resolvedSerializer,
|
|
487
|
+
statementRedactor: resolvedRedactor
|
|
488
|
+
});
|
|
489
|
+
if (m.Schema && finalConfig.instrumentHooks) {
|
|
490
|
+
patchSchemaHooks(m.Schema, tracer, finalConfig);
|
|
491
|
+
}
|
|
492
|
+
const getModelCollectionName = (model) => {
|
|
493
|
+
try {
|
|
494
|
+
return model.collection?.collectionName || model.modelName;
|
|
495
|
+
} catch {
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
const queryMethods = [
|
|
500
|
+
{ method: "find", operation: "find" },
|
|
501
|
+
{ method: "findOne", operation: "findOne" },
|
|
502
|
+
{ method: "findById", operation: "findById" },
|
|
503
|
+
{ method: "findOneAndUpdate", operation: "findOneAndUpdate" },
|
|
504
|
+
{ method: "findOneAndDelete", operation: "findOneAndDelete" },
|
|
505
|
+
{ method: "findOneAndReplace", operation: "findOneAndReplace" },
|
|
506
|
+
{ method: "deleteOne", operation: "deleteOne" },
|
|
507
|
+
{ method: "deleteMany", operation: "deleteMany" },
|
|
508
|
+
{ method: "updateOne", operation: "updateOne" },
|
|
509
|
+
{ method: "updateMany", operation: "updateMany" },
|
|
510
|
+
{ method: "countDocuments", operation: "countDocuments" },
|
|
511
|
+
{ method: "estimatedDocumentCount", operation: "estimatedDocumentCount" }
|
|
512
|
+
];
|
|
513
|
+
for (const { method, operation } of queryMethods) {
|
|
514
|
+
wrapQueryReturningMethod(
|
|
515
|
+
m.Model,
|
|
516
|
+
method,
|
|
517
|
+
operation,
|
|
518
|
+
getModelCollectionName,
|
|
519
|
+
(model) => model.modelName,
|
|
520
|
+
tracer,
|
|
521
|
+
finalConfig,
|
|
522
|
+
captureStatement
|
|
523
|
+
);
|
|
524
|
+
if (m.Query?.prototype?.[method]) {
|
|
525
|
+
wrapChainableMethod(m.Query.prototype, method);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
const instanceMethods = ["save", "deleteOne"];
|
|
529
|
+
for (const method of instanceMethods) {
|
|
530
|
+
if (m.Model.prototype[method]) {
|
|
531
|
+
wrapInstanceMethod(
|
|
532
|
+
m.Model.prototype,
|
|
533
|
+
method,
|
|
534
|
+
method,
|
|
535
|
+
(doc) => {
|
|
536
|
+
try {
|
|
537
|
+
return doc.constructor?.collection?.collectionName || doc.constructor?.modelName;
|
|
538
|
+
} catch {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
},
|
|
542
|
+
(doc) => {
|
|
543
|
+
try {
|
|
544
|
+
return doc.constructor?.modelName;
|
|
545
|
+
} catch {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
},
|
|
549
|
+
tracer,
|
|
550
|
+
finalConfig,
|
|
551
|
+
captureStatement
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const staticMethods = ["create", "insertMany", "aggregate", "bulkWrite"];
|
|
556
|
+
for (const method of staticMethods) {
|
|
557
|
+
if (m.Model[method]) {
|
|
558
|
+
wrapStaticMethod(
|
|
559
|
+
m.Model,
|
|
560
|
+
method,
|
|
561
|
+
method,
|
|
562
|
+
(model) => {
|
|
563
|
+
try {
|
|
564
|
+
return model.collection?.collectionName;
|
|
565
|
+
} catch {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
(model) => model.modelName,
|
|
570
|
+
tracer,
|
|
571
|
+
finalConfig,
|
|
572
|
+
captureStatement
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
const chainableMethods = [
|
|
577
|
+
"populate",
|
|
578
|
+
"select",
|
|
579
|
+
"lean",
|
|
580
|
+
"where",
|
|
581
|
+
"sort",
|
|
582
|
+
"limit",
|
|
583
|
+
"skip"
|
|
584
|
+
];
|
|
585
|
+
for (const method of chainableMethods) {
|
|
586
|
+
if (m.Query?.prototype?.[method]) {
|
|
587
|
+
wrapChainableMethod(m.Query.prototype, method);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
m[INSTRUMENTED_FLAG] = true;
|
|
591
|
+
return mongoose;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
exports.instrumentMongoose = instrumentMongoose;
|
|
595
|
+
//# sourceMappingURL=index.cjs.map
|
|
596
|
+
//# sourceMappingURL=index.cjs.map
|