@use-tusk/drift-node-sdk 0.1.6 → 0.1.7
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 +6 -0
- package/dist/index.cjs +491 -338
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +491 -338
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -252,7 +252,7 @@ var TdInstrumentationAbstract = class {
|
|
|
252
252
|
|
|
253
253
|
//#endregion
|
|
254
254
|
//#region package.json
|
|
255
|
-
var version = "0.1.
|
|
255
|
+
var version = "0.1.7";
|
|
256
256
|
|
|
257
257
|
//#endregion
|
|
258
258
|
//#region src/version.ts
|
|
@@ -1450,7 +1450,7 @@ var JsonSchemaHelper = class JsonSchemaHelper {
|
|
|
1450
1450
|
if (schema.decodedType === DecodedType$1.JSON && typeof decodedValue === "string") decodedValue = JSON.parse(decodedValue);
|
|
1451
1451
|
decodedData[key] = decodedValue;
|
|
1452
1452
|
} catch (error) {
|
|
1453
|
-
logger.
|
|
1453
|
+
logger.debug(`[JsonSchemaHelper] Failed to decode ${key}:`, error);
|
|
1454
1454
|
decodedData[key] = data[key];
|
|
1455
1455
|
}
|
|
1456
1456
|
return decodedData;
|
|
@@ -1538,7 +1538,8 @@ function convertMockRequestDataToCleanSpanData(mockRequestData, tuskDrift, input
|
|
|
1538
1538
|
status: {
|
|
1539
1539
|
code: StatusCode.OK,
|
|
1540
1540
|
message: "OK"
|
|
1541
|
-
}
|
|
1541
|
+
},
|
|
1542
|
+
stackTrace: mockRequestData.stackTrace
|
|
1542
1543
|
};
|
|
1543
1544
|
}
|
|
1544
1545
|
/**
|
|
@@ -1583,7 +1584,7 @@ let ClientRequest;
|
|
|
1583
1584
|
* Mock ClientRequest implementation for Tusk Drift HTTP replay
|
|
1584
1585
|
*/
|
|
1585
1586
|
var TdMockClientRequest = class TdMockClientRequest extends EventEmitter {
|
|
1586
|
-
constructor(options, spanInfo, callback) {
|
|
1587
|
+
constructor(options, spanInfo, callback, stackTrace) {
|
|
1587
1588
|
super();
|
|
1588
1589
|
this.INSTRUMENTATION_NAME = "HttpInstrumentation";
|
|
1589
1590
|
this.finished = false;
|
|
@@ -1594,6 +1595,7 @@ var TdMockClientRequest = class TdMockClientRequest extends EventEmitter {
|
|
|
1594
1595
|
TdMockClientRequest._setupPrototype();
|
|
1595
1596
|
this.tuskDrift = TuskDriftCore.getInstance();
|
|
1596
1597
|
this.spanInfo = spanInfo;
|
|
1598
|
+
this.stackTrace = stackTrace;
|
|
1597
1599
|
if (!options || Object.keys(options).length === 0) throw new Error("Making a request with empty `options` is not supported in TdMockClientRequest");
|
|
1598
1600
|
this.options = {
|
|
1599
1601
|
...options,
|
|
@@ -1729,7 +1731,8 @@ var TdMockClientRequest = class TdMockClientRequest extends EventEmitter {
|
|
|
1729
1731
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
1730
1732
|
submoduleName: rawInputValue.method,
|
|
1731
1733
|
inputValue,
|
|
1732
|
-
kind: SpanKind.CLIENT
|
|
1734
|
+
kind: SpanKind.CLIENT,
|
|
1735
|
+
stackTrace: this.stackTrace
|
|
1733
1736
|
},
|
|
1734
1737
|
tuskDrift: this.tuskDrift,
|
|
1735
1738
|
inputValueSchemaMerges: {
|
|
@@ -1873,7 +1876,7 @@ var HttpReplayHooks = class {
|
|
|
1873
1876
|
* Handle outbound HTTP requests in replay mode
|
|
1874
1877
|
* Uses TdMockClientRequest for simplified mocking approach
|
|
1875
1878
|
*/
|
|
1876
|
-
handleOutboundReplayRequest({ method, requestOptions, protocol, args, spanInfo }) {
|
|
1879
|
+
handleOutboundReplayRequest({ method, requestOptions, protocol, args, spanInfo, stackTrace }) {
|
|
1877
1880
|
logger.debug(`[HttpReplayHooks] Handling outbound ${protocol.toUpperCase()} ${method} request in replay mode`);
|
|
1878
1881
|
let callback;
|
|
1879
1882
|
if (args.length > 1 && typeof args[1] === "function") callback = args[1];
|
|
@@ -1890,7 +1893,7 @@ var HttpReplayHooks = class {
|
|
|
1890
1893
|
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
1891
1894
|
method
|
|
1892
1895
|
};
|
|
1893
|
-
const mockRequest = new TdMockClientRequest(mockOptions, spanInfo, callback);
|
|
1896
|
+
const mockRequest = new TdMockClientRequest(mockOptions, spanInfo, callback, stackTrace);
|
|
1894
1897
|
if (method === "GET" || method === "HEAD") process.nextTick(() => {
|
|
1895
1898
|
mockRequest.end();
|
|
1896
1899
|
});
|
|
@@ -1959,17 +1962,17 @@ function isWrapped$1(func) {
|
|
|
1959
1962
|
*/
|
|
1960
1963
|
function wrap(target, propertyName, wrapper) {
|
|
1961
1964
|
if (typeof target[propertyName] !== "function") {
|
|
1962
|
-
logger.
|
|
1965
|
+
logger.debug(`Cannot wrap non-function property: ${propertyName}`);
|
|
1963
1966
|
return;
|
|
1964
1967
|
}
|
|
1965
1968
|
if (isWrapped$1(target[propertyName])) {
|
|
1966
|
-
logger.
|
|
1969
|
+
logger.debug(`Property ${propertyName} is already wrapped`);
|
|
1967
1970
|
return;
|
|
1968
1971
|
}
|
|
1969
1972
|
const original = target[propertyName];
|
|
1970
1973
|
const wrapped = wrapper(original);
|
|
1971
1974
|
if (typeof wrapped !== "function") {
|
|
1972
|
-
logger.
|
|
1975
|
+
logger.debug(`Wrapper must return a function for property: ${propertyName}`);
|
|
1973
1976
|
return;
|
|
1974
1977
|
}
|
|
1975
1978
|
wrapped._isWrapped = true;
|
|
@@ -1979,6 +1982,45 @@ function wrap(target, propertyName, wrapper) {
|
|
|
1979
1982
|
return wrapped;
|
|
1980
1983
|
}
|
|
1981
1984
|
|
|
1985
|
+
//#endregion
|
|
1986
|
+
//#region src/instrumentation/core/utils/stackTraceUtils.ts
|
|
1987
|
+
/**
|
|
1988
|
+
* Helper functions for capturing stack traces in replay mode
|
|
1989
|
+
*
|
|
1990
|
+
* TODO: Consider using a structured format for stack frames:
|
|
1991
|
+
*
|
|
1992
|
+
* {
|
|
1993
|
+
* "frames": [
|
|
1994
|
+
* {
|
|
1995
|
+
* "fileName": "file.js",
|
|
1996
|
+
* "lineNumber": 10,
|
|
1997
|
+
* "columnNumber": 20,
|
|
1998
|
+
* "functionName": "functionName"
|
|
1999
|
+
* }
|
|
2000
|
+
* ]
|
|
2001
|
+
* }
|
|
2002
|
+
*
|
|
2003
|
+
* This would allow for more efficient matching and filtering of stack frames.
|
|
2004
|
+
* It would also allow for more accurate stack trace reconstruction in replay mode.
|
|
2005
|
+
*/
|
|
2006
|
+
/**
|
|
2007
|
+
*
|
|
2008
|
+
* @param excludeClassNames - Class names to exclude from the stack trace
|
|
2009
|
+
* @returns The stack trace as a string
|
|
2010
|
+
*/
|
|
2011
|
+
function captureStackTrace(excludeClassNames = []) {
|
|
2012
|
+
const originalStackTraceLimit = Error.stackTraceLimit;
|
|
2013
|
+
Error.stackTraceLimit = 100;
|
|
2014
|
+
const s = (/* @__PURE__ */ new Error()).stack || "";
|
|
2015
|
+
Error.stackTraceLimit = originalStackTraceLimit;
|
|
2016
|
+
const allExcludes = [...[
|
|
2017
|
+
"drift-node-sdk/src/instrumentation",
|
|
2018
|
+
"drift-node-sdk/src/core",
|
|
2019
|
+
"node_modules/@use-tusk"
|
|
2020
|
+
], ...excludeClassNames];
|
|
2021
|
+
return s.split("\n").slice(2).filter((l) => !allExcludes.some((exclude) => l.includes(exclude))).join("\n");
|
|
2022
|
+
}
|
|
2023
|
+
|
|
1982
2024
|
//#endregion
|
|
1983
2025
|
//#region src/instrumentation/libraries/http/HttpTransformEngine.ts
|
|
1984
2026
|
/**
|
|
@@ -2927,37 +2969,40 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2927
2969
|
} else requestOptions = args[0] || {};
|
|
2928
2970
|
const method = requestOptions.method || "GET";
|
|
2929
2971
|
const requestProtocol = self._normalizeProtocol(requestOptions.protocol || void 0, protocol);
|
|
2930
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
2931
|
-
const
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
headers,
|
|
2936
|
-
protocol: requestProtocol,
|
|
2937
|
-
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
2938
|
-
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
2939
|
-
timeout: requestOptions.timeout || void 0
|
|
2940
|
-
};
|
|
2941
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
|
|
2942
|
-
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
2943
|
-
kind: SpanKind.CLIENT,
|
|
2944
|
-
packageName: requestProtocol,
|
|
2945
|
-
packageType: PackageType.HTTP,
|
|
2946
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
2947
|
-
submodule: method,
|
|
2948
|
-
inputValue,
|
|
2949
|
-
isPreAppStart: false
|
|
2950
|
-
}, (spanInfo) => {
|
|
2951
|
-
return self.replayHooks.handleOutboundReplayRequest({
|
|
2972
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
2973
|
+
const stackTrace = captureStackTrace(["HttpInstrumentation"]);
|
|
2974
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
2975
|
+
const headers = normalizeHeaders(requestOptions.headers || {});
|
|
2976
|
+
const inputValue = {
|
|
2952
2977
|
method,
|
|
2953
|
-
requestOptions,
|
|
2978
|
+
path: requestOptions.path || void 0,
|
|
2979
|
+
headers,
|
|
2954
2980
|
protocol: requestProtocol,
|
|
2955
|
-
|
|
2956
|
-
|
|
2981
|
+
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
2982
|
+
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
2983
|
+
timeout: requestOptions.timeout || void 0
|
|
2984
|
+
};
|
|
2985
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
|
|
2986
|
+
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
2987
|
+
kind: SpanKind.CLIENT,
|
|
2988
|
+
packageName: requestProtocol,
|
|
2989
|
+
packageType: PackageType.HTTP,
|
|
2990
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
2991
|
+
submodule: method,
|
|
2992
|
+
inputValue,
|
|
2993
|
+
isPreAppStart: false
|
|
2994
|
+
}, (spanInfo) => {
|
|
2995
|
+
return self.replayHooks.handleOutboundReplayRequest({
|
|
2996
|
+
method,
|
|
2997
|
+
requestOptions,
|
|
2998
|
+
protocol: requestProtocol,
|
|
2999
|
+
args,
|
|
3000
|
+
spanInfo,
|
|
3001
|
+
stackTrace
|
|
3002
|
+
});
|
|
2957
3003
|
});
|
|
2958
|
-
});
|
|
2959
|
-
}
|
|
2960
|
-
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3004
|
+
} });
|
|
3005
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
2961
3006
|
originalFunctionCall: () => originalRequest.apply(this, args),
|
|
2962
3007
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
2963
3008
|
const headers = normalizeHeaders(requestOptions.headers || {});
|
|
@@ -3412,6 +3457,7 @@ var TdPgClientMock = class extends EventEmitter {
|
|
|
3412
3457
|
}
|
|
3413
3458
|
query(...args) {
|
|
3414
3459
|
logger.debug(`[TdPgClientMock] Mock pool client query intercepted in REPLAY mode`);
|
|
3460
|
+
const stackTrace = captureStackTrace(["TdPgClientMock"]);
|
|
3415
3461
|
const queryConfig = this.pgInstrumentation.parseQueryArgs(args);
|
|
3416
3462
|
if (!queryConfig || !queryConfig.text) {
|
|
3417
3463
|
logger.debug(`[TdPgClientMock] Could not parse mock client query, returning empty result`);
|
|
@@ -3426,7 +3472,7 @@ var TdPgClientMock = class extends EventEmitter {
|
|
|
3426
3472
|
clientType: "client"
|
|
3427
3473
|
};
|
|
3428
3474
|
const inputValue = createMockInputValue(rawInputValue);
|
|
3429
|
-
return this.pgInstrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo);
|
|
3475
|
+
return this.pgInstrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
3430
3476
|
}
|
|
3431
3477
|
release() {
|
|
3432
3478
|
this.emit("end");
|
|
@@ -3529,23 +3575,25 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3529
3575
|
values: queryConfig.values || [],
|
|
3530
3576
|
clientType
|
|
3531
3577
|
};
|
|
3532
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
3533
|
-
const
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3578
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
3579
|
+
const stackTrace = captureStackTrace(["PgInstrumentation"]);
|
|
3580
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
3581
|
+
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
3582
|
+
const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
|
|
3583
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
|
|
3584
|
+
name: spanName,
|
|
3585
|
+
kind: SpanKind.CLIENT,
|
|
3586
|
+
submodule: "query",
|
|
3587
|
+
packageType: PackageType.PG,
|
|
3588
|
+
packageName,
|
|
3589
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3590
|
+
inputValue,
|
|
3591
|
+
isPreAppStart: false
|
|
3592
|
+
}, (spanInfo) => {
|
|
3593
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, stackTrace);
|
|
3594
|
+
});
|
|
3595
|
+
} });
|
|
3596
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3549
3597
|
originalFunctionCall: () => originalQuery.apply(this, args),
|
|
3550
3598
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
3551
3599
|
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
@@ -3691,7 +3739,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3691
3739
|
throw error;
|
|
3692
3740
|
});
|
|
3693
3741
|
}
|
|
3694
|
-
async handleReplayQuery(queryConfig, inputValue, spanInfo) {
|
|
3742
|
+
async handleReplayQuery(queryConfig, inputValue, spanInfo, stackTrace) {
|
|
3695
3743
|
logger.debug(`[PgInstrumentation] Replaying PG query`);
|
|
3696
3744
|
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
3697
3745
|
const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
|
|
@@ -3704,7 +3752,8 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3704
3752
|
packageName,
|
|
3705
3753
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
3706
3754
|
submoduleName: "query",
|
|
3707
|
-
kind: SpanKind.CLIENT
|
|
3755
|
+
kind: SpanKind.CLIENT,
|
|
3756
|
+
stackTrace
|
|
3708
3757
|
},
|
|
3709
3758
|
tuskDrift: this.tuskDrift
|
|
3710
3759
|
});
|
|
@@ -4172,26 +4221,29 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4172
4221
|
query: query.trim(),
|
|
4173
4222
|
parameters: values
|
|
4174
4223
|
};
|
|
4175
|
-
if (this.mode === TuskDriftMode.REPLAY)
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
packageName: "postgres",
|
|
4182
|
-
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4183
|
-
inputValue,
|
|
4184
|
-
isPreAppStart: false
|
|
4185
|
-
}, (spanInfo) => {
|
|
4186
|
-
return this.handleReplaySqlQuery({
|
|
4187
|
-
inputValue,
|
|
4188
|
-
spanInfo,
|
|
4224
|
+
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4225
|
+
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4226
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
4227
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => originalSql.call(this, strings, ...values), {
|
|
4228
|
+
name: "postgres.query",
|
|
4229
|
+
kind: SpanKind.CLIENT,
|
|
4189
4230
|
submodule: "query",
|
|
4190
|
-
|
|
4231
|
+
packageType: PackageType.PG,
|
|
4232
|
+
packageName: "postgres",
|
|
4233
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4234
|
+
inputValue,
|
|
4235
|
+
isPreAppStart: false
|
|
4236
|
+
}, (spanInfo) => {
|
|
4237
|
+
return this.handleReplaySqlQuery({
|
|
4238
|
+
inputValue,
|
|
4239
|
+
spanInfo,
|
|
4240
|
+
submodule: "query",
|
|
4241
|
+
name: "postgres.query",
|
|
4242
|
+
stackTrace
|
|
4243
|
+
});
|
|
4191
4244
|
});
|
|
4192
|
-
});
|
|
4193
|
-
}
|
|
4194
|
-
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4245
|
+
} });
|
|
4246
|
+
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4195
4247
|
originalFunctionCall: () => originalSql.call(this, strings, ...values),
|
|
4196
4248
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
4197
4249
|
return SpanUtils.createAndExecuteSpan(this.mode, () => originalSql.call(this, strings, ...values), {
|
|
@@ -4222,28 +4274,31 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4222
4274
|
parameters: parameters || [],
|
|
4223
4275
|
options: queryOptions
|
|
4224
4276
|
};
|
|
4225
|
-
if (this.mode === TuskDriftMode.REPLAY)
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
packageName: "postgres",
|
|
4233
|
-
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4234
|
-
inputValue,
|
|
4235
|
-
isPreAppStart: false
|
|
4236
|
-
}, (spanInfo) => {
|
|
4237
|
-
return this.handleReplayUnsafeQuery({
|
|
4238
|
-
inputValue,
|
|
4239
|
-
spanInfo,
|
|
4277
|
+
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4278
|
+
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4279
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
4280
|
+
return this._createPendingQueryWrapper(() => {
|
|
4281
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => executeUnsafe(), {
|
|
4282
|
+
name: "postgres.unsafe",
|
|
4283
|
+
kind: SpanKind.CLIENT,
|
|
4240
4284
|
submodule: "unsafe",
|
|
4241
|
-
|
|
4285
|
+
packageType: PackageType.PG,
|
|
4286
|
+
packageName: "postgres",
|
|
4287
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4288
|
+
inputValue,
|
|
4289
|
+
isPreAppStart: false
|
|
4290
|
+
}, (spanInfo) => {
|
|
4291
|
+
return this.handleReplayUnsafeQuery({
|
|
4292
|
+
inputValue,
|
|
4293
|
+
spanInfo,
|
|
4294
|
+
submodule: "unsafe",
|
|
4295
|
+
name: "postgres.unsafe",
|
|
4296
|
+
stackTrace
|
|
4297
|
+
});
|
|
4242
4298
|
});
|
|
4243
4299
|
});
|
|
4244
|
-
});
|
|
4245
|
-
}
|
|
4246
|
-
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4300
|
+
} });
|
|
4301
|
+
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4247
4302
|
originalFunctionCall: executeUnsafe,
|
|
4248
4303
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
4249
4304
|
return SpanUtils.createAndExecuteSpan(this.mode, executeUnsafe, {
|
|
@@ -4273,21 +4328,23 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4273
4328
|
else if (transactionCallback) return originalBegin.call(sqlInstance, transactionCallback);
|
|
4274
4329
|
else return originalBegin.call(sqlInstance, options || void 0);
|
|
4275
4330
|
};
|
|
4276
|
-
if (this.mode === TuskDriftMode.REPLAY)
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4331
|
+
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4332
|
+
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4333
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
4334
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => executeBegin(), {
|
|
4335
|
+
name: "postgres.begin",
|
|
4336
|
+
kind: SpanKind.CLIENT,
|
|
4337
|
+
submodule: "transaction",
|
|
4338
|
+
packageType: PackageType.PG,
|
|
4339
|
+
packageName: "postgres",
|
|
4340
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4341
|
+
inputValue,
|
|
4342
|
+
isPreAppStart: false
|
|
4343
|
+
}, (spanInfo) => {
|
|
4344
|
+
return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
|
|
4345
|
+
});
|
|
4346
|
+
} });
|
|
4347
|
+
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4291
4348
|
originalFunctionCall: executeBegin,
|
|
4292
4349
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
4293
4350
|
return SpanUtils.createAndExecuteSpan(this.mode, executeBegin, {
|
|
@@ -4381,7 +4438,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4381
4438
|
});
|
|
4382
4439
|
return promise;
|
|
4383
4440
|
}
|
|
4384
|
-
async _handleReplayBeginTransaction(spanInfo, options) {
|
|
4441
|
+
async _handleReplayBeginTransaction(spanInfo, options, stackTrace) {
|
|
4385
4442
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
|
|
4386
4443
|
const mockData = await findMockResponseAsync({
|
|
4387
4444
|
mockRequestData: {
|
|
@@ -4395,7 +4452,8 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4395
4452
|
packageName: "postgres",
|
|
4396
4453
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4397
4454
|
submoduleName: "transaction",
|
|
4398
|
-
kind: SpanKind.CLIENT
|
|
4455
|
+
kind: SpanKind.CLIENT,
|
|
4456
|
+
stackTrace
|
|
4399
4457
|
},
|
|
4400
4458
|
tuskDrift: this.tuskDrift
|
|
4401
4459
|
});
|
|
@@ -4450,7 +4508,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4450
4508
|
throw error;
|
|
4451
4509
|
}
|
|
4452
4510
|
}
|
|
4453
|
-
async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name }) {
|
|
4511
|
+
async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
|
|
4454
4512
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres sql query`);
|
|
4455
4513
|
const mockData = await findMockResponseAsync({
|
|
4456
4514
|
mockRequestData: {
|
|
@@ -4461,7 +4519,8 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4461
4519
|
packageName: "postgres",
|
|
4462
4520
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4463
4521
|
submoduleName: submodule,
|
|
4464
|
-
kind: SpanKind.CLIENT
|
|
4522
|
+
kind: SpanKind.CLIENT,
|
|
4523
|
+
stackTrace
|
|
4465
4524
|
},
|
|
4466
4525
|
tuskDrift: this.tuskDrift
|
|
4467
4526
|
});
|
|
@@ -4480,7 +4539,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4480
4539
|
count: isResultObject ? processedResult.count : void 0
|
|
4481
4540
|
});
|
|
4482
4541
|
}
|
|
4483
|
-
async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name }) {
|
|
4542
|
+
async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
|
|
4484
4543
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres unsafe query`);
|
|
4485
4544
|
const mockData = await findMockResponseAsync({
|
|
4486
4545
|
mockRequestData: {
|
|
@@ -4491,7 +4550,8 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4491
4550
|
packageName: "postgres",
|
|
4492
4551
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4493
4552
|
submoduleName: submodule,
|
|
4494
|
-
kind: SpanKind.CLIENT
|
|
4553
|
+
kind: SpanKind.CLIENT,
|
|
4554
|
+
stackTrace
|
|
4495
4555
|
},
|
|
4496
4556
|
tuskDrift: this.tuskDrift
|
|
4497
4557
|
});
|
|
@@ -4603,6 +4663,7 @@ var TdMysql2ConnectionMock = class extends EventEmitter {
|
|
|
4603
4663
|
}
|
|
4604
4664
|
query(...args) {
|
|
4605
4665
|
logger.debug(`[TdMysql2ConnectionMock] Mock connection query intercepted in REPLAY mode`);
|
|
4666
|
+
const stackTrace = captureStackTrace(["TdMysql2ConnectionMock"]);
|
|
4606
4667
|
const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args);
|
|
4607
4668
|
if (!queryConfig || !queryConfig.sql) {
|
|
4608
4669
|
logger.debug(`[TdMysql2ConnectionMock] Could not parse mock connection query, returning empty result`);
|
|
@@ -4622,10 +4683,11 @@ var TdMysql2ConnectionMock = class extends EventEmitter {
|
|
|
4622
4683
|
clientType: this.clientType
|
|
4623
4684
|
};
|
|
4624
4685
|
const inputValue = createMockInputValue(rawInputValue);
|
|
4625
|
-
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo);
|
|
4686
|
+
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4626
4687
|
}
|
|
4627
4688
|
execute(...args) {
|
|
4628
4689
|
logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`);
|
|
4690
|
+
const stackTrace = captureStackTrace(["TdMysql2ConnectionMock"]);
|
|
4629
4691
|
const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args);
|
|
4630
4692
|
if (!queryConfig || !queryConfig.sql) {
|
|
4631
4693
|
logger.debug(`[TdMysql2ConnectionMock] Could not parse mock connection execute, returning empty result`);
|
|
@@ -4645,7 +4707,7 @@ var TdMysql2ConnectionMock = class extends EventEmitter {
|
|
|
4645
4707
|
clientType: this.clientType
|
|
4646
4708
|
};
|
|
4647
4709
|
const inputValue = createMockInputValue(rawInputValue);
|
|
4648
|
-
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo);
|
|
4710
|
+
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4649
4711
|
}
|
|
4650
4712
|
release() {
|
|
4651
4713
|
this.emit("end");
|
|
@@ -4739,20 +4801,33 @@ var TdMysql2QueryMock = class {
|
|
|
4739
4801
|
/**
|
|
4740
4802
|
* Handle replay of a MySQL2 query (query or execute)
|
|
4741
4803
|
*/
|
|
4742
|
-
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query") {
|
|
4804
|
+
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query", stackTrace) {
|
|
4743
4805
|
logger.debug(`[Mysql2Instrumentation] Replaying MySQL2 query`);
|
|
4744
4806
|
const spanName = `mysql2.${inputValue.clientType}.${submoduleName}`;
|
|
4745
|
-
return this._handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName);
|
|
4807
|
+
return this._handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName, stackTrace);
|
|
4746
4808
|
}
|
|
4747
4809
|
/**
|
|
4748
4810
|
* Handle query - always returns an EventEmitter (like mysql2 does)
|
|
4749
4811
|
* This handles both callback and streaming modes
|
|
4812
|
+
* The EventEmitter is also thenable (has a .then() method) to support await/Promise usage
|
|
4750
4813
|
*/
|
|
4751
|
-
_handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName) {
|
|
4814
|
+
_handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName, stackTrace) {
|
|
4752
4815
|
const emitter = new EventEmitter();
|
|
4816
|
+
let storedRows = null;
|
|
4817
|
+
let storedFields = null;
|
|
4818
|
+
emitter.then = function(onResolve, onReject) {
|
|
4819
|
+
return new Promise((resolve, reject) => {
|
|
4820
|
+
emitter.once("end", () => {
|
|
4821
|
+
resolve([storedRows, storedFields]);
|
|
4822
|
+
});
|
|
4823
|
+
emitter.once("error", (error) => {
|
|
4824
|
+
reject(error);
|
|
4825
|
+
});
|
|
4826
|
+
}).then(onResolve, onReject);
|
|
4827
|
+
};
|
|
4753
4828
|
(async () => {
|
|
4754
4829
|
try {
|
|
4755
|
-
const mockData = await this._fetchMockData(inputValue, spanInfo, spanName, submoduleName);
|
|
4830
|
+
const mockData = await this._fetchMockData(inputValue, spanInfo, spanName, submoduleName, stackTrace);
|
|
4756
4831
|
if (!mockData) {
|
|
4757
4832
|
const sql = queryConfig.sql || inputValue.sql || "UNKNOWN_QUERY";
|
|
4758
4833
|
logger.warn(`[Mysql2Instrumentation] No mock data found for MySQL2 query: ${sql}`);
|
|
@@ -4764,6 +4839,8 @@ var TdMysql2QueryMock = class {
|
|
|
4764
4839
|
return;
|
|
4765
4840
|
}
|
|
4766
4841
|
const processedResult = this._convertMysql2Types(mockData.result);
|
|
4842
|
+
storedRows = processedResult.rows;
|
|
4843
|
+
storedFields = processedResult.fields;
|
|
4767
4844
|
process.nextTick(() => {
|
|
4768
4845
|
if (processedResult.fields) emitter.emit("fields", processedResult.fields);
|
|
4769
4846
|
if (queryConfig.callback) queryConfig.callback(null, processedResult.rows, processedResult.fields);
|
|
@@ -4783,7 +4860,7 @@ var TdMysql2QueryMock = class {
|
|
|
4783
4860
|
/**
|
|
4784
4861
|
* Fetch mock data from CLI
|
|
4785
4862
|
*/
|
|
4786
|
-
async _fetchMockData(inputValue, spanInfo, spanName, submoduleName) {
|
|
4863
|
+
async _fetchMockData(inputValue, spanInfo, spanName, submoduleName, stackTrace) {
|
|
4787
4864
|
return await findMockResponseAsync({
|
|
4788
4865
|
mockRequestData: {
|
|
4789
4866
|
traceId: spanInfo.traceId,
|
|
@@ -4793,7 +4870,8 @@ var TdMysql2QueryMock = class {
|
|
|
4793
4870
|
packageName: "mysql2",
|
|
4794
4871
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4795
4872
|
submoduleName,
|
|
4796
|
-
kind: SpanKind.CLIENT
|
|
4873
|
+
kind: SpanKind.CLIENT,
|
|
4874
|
+
stackTrace
|
|
4797
4875
|
},
|
|
4798
4876
|
tuskDrift: this.tuskDrift
|
|
4799
4877
|
});
|
|
@@ -4817,6 +4895,52 @@ var TdMysql2QueryMock = class {
|
|
|
4817
4895
|
}
|
|
4818
4896
|
};
|
|
4819
4897
|
|
|
4898
|
+
//#endregion
|
|
4899
|
+
//#region src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionEventMock.ts
|
|
4900
|
+
/**
|
|
4901
|
+
* Mock for MySQL2 connection events (connect/error)
|
|
4902
|
+
* Handles replay of recorded connection establishment events in REPLAY mode
|
|
4903
|
+
* Recording happens through normal SpanUtils flow in RECORD mode
|
|
4904
|
+
*/
|
|
4905
|
+
var TdMysql2ConnectionEventMock = class {
|
|
4906
|
+
constructor(spanInfo) {
|
|
4907
|
+
this.INSTRUMENTATION_NAME = "Mysql2Instrumentation";
|
|
4908
|
+
this.spanInfo = spanInfo;
|
|
4909
|
+
this.tuskDrift = TuskDriftCore.getInstance();
|
|
4910
|
+
}
|
|
4911
|
+
/**
|
|
4912
|
+
* Get recorded connection event for replay
|
|
4913
|
+
* Returns { output } for success, or throws error if connection failed
|
|
4914
|
+
* The connection events are recorded automatically via SpanUtils in record mode
|
|
4915
|
+
*/
|
|
4916
|
+
async getReplayedConnectionEvent(inputValue) {
|
|
4917
|
+
logger.debug(`[TdMysql2ConnectionEventMock] Retrieving recorded connection event`);
|
|
4918
|
+
try {
|
|
4919
|
+
const mockData = await findMockResponseAsync({
|
|
4920
|
+
mockRequestData: {
|
|
4921
|
+
traceId: this.spanInfo.traceId,
|
|
4922
|
+
spanId: this.spanInfo.spanId,
|
|
4923
|
+
name: "mysql2.connection.create",
|
|
4924
|
+
inputValue,
|
|
4925
|
+
packageName: "mysql2",
|
|
4926
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4927
|
+
submoduleName: "connectEvent",
|
|
4928
|
+
kind: SpanKind.CLIENT
|
|
4929
|
+
},
|
|
4930
|
+
tuskDrift: this.tuskDrift
|
|
4931
|
+
});
|
|
4932
|
+
if (!mockData) {
|
|
4933
|
+
logger.warn(`[TdMysql2ConnectionEventMock] No mock data found, using default success`);
|
|
4934
|
+
return { output: {} };
|
|
4935
|
+
}
|
|
4936
|
+
return { output: mockData.result || {} };
|
|
4937
|
+
} catch (error) {
|
|
4938
|
+
logger.error(`[TdMysql2ConnectionEventMock] Error getting replay value:`, error);
|
|
4939
|
+
return { output: {} };
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
};
|
|
4943
|
+
|
|
4820
4944
|
//#endregion
|
|
4821
4945
|
//#region src/instrumentation/libraries/mysql2/Instrumentation.ts
|
|
4822
4946
|
const COMPLETE_SUPPORTED_VERSIONS = ">=2.3.3 <4.0.0";
|
|
@@ -4868,16 +4992,6 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
4868
4992
|
name: "mysql2/lib/pool_connection.js",
|
|
4869
4993
|
supportedVersions: [V3_11_5_TO_4_0],
|
|
4870
4994
|
patch: (moduleExports) => this._patchPoolConnectionV3(moduleExports)
|
|
4871
|
-
}),
|
|
4872
|
-
new TdInstrumentationNodeModuleFile({
|
|
4873
|
-
name: "mysql2/lib/create_connection.js",
|
|
4874
|
-
supportedVersions: [COMPLETE_SUPPORTED_VERSIONS],
|
|
4875
|
-
patch: (moduleExports) => this._patchCreateConnectionFile(moduleExports)
|
|
4876
|
-
}),
|
|
4877
|
-
new TdInstrumentationNodeModuleFile({
|
|
4878
|
-
name: "mysql2/lib/create_pool.js",
|
|
4879
|
-
supportedVersions: [COMPLETE_SUPPORTED_VERSIONS],
|
|
4880
|
-
patch: (moduleExports) => this._patchCreatePoolFile(moduleExports)
|
|
4881
4995
|
})
|
|
4882
4996
|
]
|
|
4883
4997
|
})];
|
|
@@ -4929,13 +5043,14 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
4929
5043
|
return ConnectionClass;
|
|
4930
5044
|
}
|
|
4931
5045
|
this._patchConnectionPrototypes(ConnectionClass);
|
|
5046
|
+
const patchedConnectionClass = this._getPatchedConnectionClass(ConnectionClass);
|
|
4932
5047
|
this.markModuleAsPatched(ConnectionClass);
|
|
4933
5048
|
logger.debug(`[Mysql2Instrumentation] Connection class (v2) patching complete`);
|
|
4934
|
-
return
|
|
5049
|
+
return patchedConnectionClass;
|
|
4935
5050
|
}
|
|
4936
5051
|
_patchConnectionV3(ConnectionClass) {
|
|
4937
|
-
logger.debug(`[Mysql2Instrumentation] Connection class (v3) -
|
|
4938
|
-
return ConnectionClass;
|
|
5052
|
+
logger.debug(`[Mysql2Instrumentation] Connection class (v3) - wrapping constructor only`);
|
|
5053
|
+
return this._getPatchedConnectionClass(ConnectionClass);
|
|
4939
5054
|
}
|
|
4940
5055
|
_patchConnectionPrototypes(ConnectionClass) {
|
|
4941
5056
|
if (ConnectionClass.prototype && ConnectionClass.prototype.query) {
|
|
@@ -5044,22 +5159,24 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5044
5159
|
values: queryConfig.values || [],
|
|
5045
5160
|
clientType
|
|
5046
5161
|
};
|
|
5047
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5048
|
-
const
|
|
5049
|
-
return
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5162
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5163
|
+
const stackTrace = captureStackTrace(["Mysql2Instrumentation"]);
|
|
5164
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5165
|
+
const spanName = `mysql2.${clientType}.query`;
|
|
5166
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
|
|
5167
|
+
name: spanName,
|
|
5168
|
+
kind: SpanKind.CLIENT,
|
|
5169
|
+
submodule: "query",
|
|
5170
|
+
packageType: PackageType.MYSQL,
|
|
5171
|
+
packageName: "mysql2",
|
|
5172
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5173
|
+
inputValue,
|
|
5174
|
+
isPreAppStart: false
|
|
5175
|
+
}, (spanInfo) => {
|
|
5176
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, "query", stackTrace);
|
|
5177
|
+
});
|
|
5178
|
+
} });
|
|
5179
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5063
5180
|
originalFunctionCall: () => originalQuery.apply(this, args),
|
|
5064
5181
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5065
5182
|
const spanName = `mysql2.${clientType}.query`;
|
|
@@ -5101,22 +5218,24 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5101
5218
|
values: queryConfig.values || [],
|
|
5102
5219
|
clientType
|
|
5103
5220
|
};
|
|
5104
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5105
|
-
const
|
|
5106
|
-
return
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5221
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5222
|
+
const stackTrace = captureStackTrace(["Mysql2Instrumentation"]);
|
|
5223
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5224
|
+
const spanName = `mysql2.${clientType}.execute`;
|
|
5225
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalExecute.apply(this, args), {
|
|
5226
|
+
name: spanName,
|
|
5227
|
+
kind: SpanKind.CLIENT,
|
|
5228
|
+
submodule: "execute",
|
|
5229
|
+
packageType: PackageType.MYSQL,
|
|
5230
|
+
packageName: "mysql2",
|
|
5231
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5232
|
+
inputValue,
|
|
5233
|
+
isPreAppStart: false
|
|
5234
|
+
}, (spanInfo) => {
|
|
5235
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, "execute", stackTrace);
|
|
5236
|
+
});
|
|
5237
|
+
} });
|
|
5238
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5120
5239
|
originalFunctionCall: () => originalExecute.apply(this, args),
|
|
5121
5240
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5122
5241
|
const spanName = `mysql2.${clientType}.execute`;
|
|
@@ -5464,8 +5583,8 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5464
5583
|
return result;
|
|
5465
5584
|
}
|
|
5466
5585
|
}
|
|
5467
|
-
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query") {
|
|
5468
|
-
return this.queryMock.handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName);
|
|
5586
|
+
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query", stackTrace) {
|
|
5587
|
+
return this.queryMock.handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName, stackTrace);
|
|
5469
5588
|
}
|
|
5470
5589
|
_handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$1) {
|
|
5471
5590
|
if (callback) {
|
|
@@ -5528,117 +5647,137 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5528
5647
|
return;
|
|
5529
5648
|
} else return Promise.resolve(mockConnection);
|
|
5530
5649
|
}
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
affectedRows: result.affectedRows,
|
|
5541
|
-
insertId: result.insertId,
|
|
5542
|
-
warningCount: result.warningCount
|
|
5543
|
-
};
|
|
5544
|
-
else outputValue = result;
|
|
5545
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
|
|
5546
|
-
}
|
|
5547
|
-
_patchCreateConnectionFile(createConnectionFn) {
|
|
5548
|
-
logger.debug(`[Mysql2Instrumentation] Patching create_connection.js file`);
|
|
5650
|
+
/**
|
|
5651
|
+
* Creates a patched Connection class that intercepts the constructor
|
|
5652
|
+
* to handle connection event recording/replay.
|
|
5653
|
+
*
|
|
5654
|
+
* Wrap the Connection constructor to:
|
|
5655
|
+
* - In RECORD mode: listen for 'connect'/'error' events and record them
|
|
5656
|
+
* - In REPLAY mode: create a MockConnection that fakes the connection and emits recorded events
|
|
5657
|
+
*/
|
|
5658
|
+
_getPatchedConnectionClass(OriginalConnection) {
|
|
5549
5659
|
const self = this;
|
|
5550
|
-
|
|
5660
|
+
function TdPatchedConnection(...args) {
|
|
5551
5661
|
const inputValue = { method: "createConnection" };
|
|
5552
|
-
if (self.mode === TuskDriftMode.
|
|
5553
|
-
|
|
5554
|
-
name: `mysql2.createConnection`,
|
|
5555
|
-
kind: SpanKind.CLIENT,
|
|
5556
|
-
submodule: "createConnection",
|
|
5557
|
-
packageName: "mysql2",
|
|
5558
|
-
packageType: PackageType.MYSQL,
|
|
5559
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5560
|
-
inputValue,
|
|
5561
|
-
isPreAppStart: false
|
|
5562
|
-
}, (spanInfo) => {
|
|
5563
|
-
const connection = createConnectionFn.apply(this, args);
|
|
5564
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { created: true } });
|
|
5565
|
-
SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK });
|
|
5566
|
-
return connection;
|
|
5567
|
-
});
|
|
5568
|
-
} });
|
|
5569
|
-
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5570
|
-
originalFunctionCall: () => createConnectionFn.apply(this, args),
|
|
5662
|
+
if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5663
|
+
originalFunctionCall: () => new OriginalConnection(...args),
|
|
5571
5664
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5572
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () =>
|
|
5573
|
-
name: `mysql2.
|
|
5665
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => new OriginalConnection(...args), {
|
|
5666
|
+
name: `mysql2.connection.create`,
|
|
5574
5667
|
kind: SpanKind.CLIENT,
|
|
5575
|
-
submodule: "
|
|
5576
|
-
packageName: "mysql2",
|
|
5668
|
+
submodule: "connectEvent",
|
|
5577
5669
|
packageType: PackageType.MYSQL,
|
|
5670
|
+
packageName: "mysql2",
|
|
5578
5671
|
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5579
5672
|
inputValue,
|
|
5580
5673
|
isPreAppStart
|
|
5581
5674
|
}, (spanInfo) => {
|
|
5582
|
-
const connection =
|
|
5583
|
-
|
|
5584
|
-
|
|
5675
|
+
const connection = new OriginalConnection(...args);
|
|
5676
|
+
connection.on("connect", (connectionObj) => {
|
|
5677
|
+
try {
|
|
5678
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
|
|
5679
|
+
connected: true,
|
|
5680
|
+
connectionObj
|
|
5681
|
+
} });
|
|
5682
|
+
SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK });
|
|
5683
|
+
} catch {
|
|
5684
|
+
logger.error(`[Mysql2Instrumentation] error adding span attributes:`);
|
|
5685
|
+
}
|
|
5686
|
+
});
|
|
5687
|
+
connection.on("error", (err) => {
|
|
5688
|
+
try {
|
|
5689
|
+
logger.debug(`[Mysql2Instrumentation] Connection error, recording: ${err.message}`);
|
|
5690
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
5691
|
+
code: SpanStatusCode.ERROR,
|
|
5692
|
+
message: err.message
|
|
5693
|
+
});
|
|
5694
|
+
} catch {
|
|
5695
|
+
logger.error(`[Mysql2Instrumentation] error ending span`);
|
|
5696
|
+
}
|
|
5697
|
+
});
|
|
5585
5698
|
return connection;
|
|
5586
5699
|
});
|
|
5587
5700
|
},
|
|
5588
5701
|
spanKind: SpanKind.CLIENT
|
|
5589
5702
|
});
|
|
5590
|
-
else return createConnectionFn.apply(this, args);
|
|
5591
|
-
};
|
|
5592
|
-
logger.debug(`[Mysql2Instrumentation] Patched create_connection.js file`);
|
|
5593
|
-
return wrappedFn;
|
|
5594
|
-
}
|
|
5595
|
-
_patchCreatePoolFile(createPoolFn) {
|
|
5596
|
-
logger.debug(`[Mysql2Instrumentation] Patching create_pool.js file`);
|
|
5597
|
-
const self = this;
|
|
5598
|
-
const wrappedFn = function(...args) {
|
|
5599
|
-
const inputValue = { method: "createPool" };
|
|
5600
5703
|
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({ replayModeHandler: () => {
|
|
5601
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () =>
|
|
5602
|
-
name: `mysql2.
|
|
5704
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => new OriginalConnection(...args), {
|
|
5705
|
+
name: `mysql2.connection.create`,
|
|
5603
5706
|
kind: SpanKind.CLIENT,
|
|
5604
|
-
submodule: "
|
|
5605
|
-
packageName: "mysql2",
|
|
5707
|
+
submodule: "connectEvent",
|
|
5606
5708
|
packageType: PackageType.MYSQL,
|
|
5709
|
+
packageName: "mysql2",
|
|
5607
5710
|
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5608
5711
|
inputValue,
|
|
5609
5712
|
isPreAppStart: false
|
|
5610
5713
|
}, (spanInfo) => {
|
|
5611
|
-
|
|
5612
|
-
|
|
5714
|
+
class MockConnection extends OriginalConnection {
|
|
5715
|
+
constructor(...mockConnectionArgs) {
|
|
5716
|
+
const clonedArgs = JSON.parse(JSON.stringify(mockConnectionArgs));
|
|
5717
|
+
if (clonedArgs[0] && clonedArgs[0].config) {
|
|
5718
|
+
clonedArgs[0].config.host = "127.0.0.1";
|
|
5719
|
+
clonedArgs[0].config.port = 127;
|
|
5720
|
+
} else if (clonedArgs[0]) {
|
|
5721
|
+
clonedArgs[0].host = "127.0.0.1";
|
|
5722
|
+
clonedArgs[0].port = 127;
|
|
5723
|
+
}
|
|
5724
|
+
super(...clonedArgs);
|
|
5725
|
+
this._isConnectOrErrorEmitted = false;
|
|
5726
|
+
this._connectEventMock = new TdMysql2ConnectionEventMock(spanInfo);
|
|
5727
|
+
}
|
|
5728
|
+
on(event, listener) {
|
|
5729
|
+
if (!this._connectEventMock) return super.on(event, listener);
|
|
5730
|
+
if (event === "connect" && !this._isConnectOrErrorEmitted) {
|
|
5731
|
+
this._connectEventMock.getReplayedConnectionEvent(inputValue).then(({ output }) => {
|
|
5732
|
+
if (output !== void 0) process.nextTick(() => {
|
|
5733
|
+
listener.call(this, output);
|
|
5734
|
+
this._isConnectOrErrorEmitted = true;
|
|
5735
|
+
});
|
|
5736
|
+
}).catch((err) => {
|
|
5737
|
+
logger.error(`[Mysql2Instrumentation] Error replaying connection event:`, err);
|
|
5738
|
+
});
|
|
5739
|
+
return this;
|
|
5740
|
+
}
|
|
5741
|
+
if (event === "error" && !this._isConnectOrErrorEmitted) return this;
|
|
5742
|
+
return super.on(event, listener);
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
const mockConnection = new MockConnection(...args);
|
|
5746
|
+
mockConnection.addListener("error", (_err) => {});
|
|
5747
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
|
|
5748
|
+
connected: true,
|
|
5749
|
+
mock: true
|
|
5750
|
+
} });
|
|
5613
5751
|
SpanUtils.endSpan(spanInfo.span, { code: SpanStatusCode.OK });
|
|
5614
|
-
return
|
|
5752
|
+
return mockConnection;
|
|
5615
5753
|
});
|
|
5616
5754
|
} });
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5755
|
+
return new OriginalConnection(...args);
|
|
5756
|
+
}
|
|
5757
|
+
const staticProps = Object.getOwnPropertyNames(OriginalConnection).filter((key) => ![
|
|
5758
|
+
"length",
|
|
5759
|
+
"name",
|
|
5760
|
+
"prototype"
|
|
5761
|
+
].includes(key));
|
|
5762
|
+
for (const staticProp of staticProps) TdPatchedConnection[staticProp] = OriginalConnection[staticProp];
|
|
5763
|
+
Object.setPrototypeOf(TdPatchedConnection.prototype, OriginalConnection.prototype);
|
|
5764
|
+
return TdPatchedConnection;
|
|
5765
|
+
}
|
|
5766
|
+
_addOutputAttributesToSpan(spanInfo, result, fields) {
|
|
5767
|
+
if (!result) return;
|
|
5768
|
+
let outputValue = {};
|
|
5769
|
+
if (Array.isArray(result)) outputValue = {
|
|
5770
|
+
rowCount: result.length,
|
|
5771
|
+
rows: result,
|
|
5772
|
+
fields: fields || []
|
|
5773
|
+
};
|
|
5774
|
+
else if (result.affectedRows !== void 0) outputValue = {
|
|
5775
|
+
affectedRows: result.affectedRows,
|
|
5776
|
+
insertId: result.insertId,
|
|
5777
|
+
warningCount: result.warningCount
|
|
5639
5778
|
};
|
|
5640
|
-
|
|
5641
|
-
|
|
5779
|
+
else outputValue = result;
|
|
5780
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
|
|
5642
5781
|
}
|
|
5643
5782
|
_wrap(target, propertyName, wrapper) {
|
|
5644
5783
|
wrap(target, propertyName, wrapper);
|
|
@@ -5796,20 +5935,22 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
5796
5935
|
logger.error(`[JsonwebtokenInstrumentation] error creating mock input value:`, error);
|
|
5797
5936
|
return originalVerify.apply(this, args);
|
|
5798
5937
|
}
|
|
5799
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5938
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5939
|
+
const stackTrace = captureStackTrace(["JsonwebtokenInstrumentation"]);
|
|
5940
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5941
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalVerify.apply(this, args), {
|
|
5942
|
+
name: "jsonwebtoken.verify",
|
|
5943
|
+
kind: SpanKind.CLIENT,
|
|
5944
|
+
submodule: "verify",
|
|
5945
|
+
packageName: "jsonwebtoken",
|
|
5946
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5947
|
+
inputValue,
|
|
5948
|
+
isPreAppStart: false
|
|
5949
|
+
}, (spanInfo) => {
|
|
5950
|
+
return self.handleReplayVerify(verifyConfig, inputValue, spanInfo, stackTrace);
|
|
5951
|
+
});
|
|
5952
|
+
} });
|
|
5953
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5813
5954
|
originalFunctionCall: () => originalVerify.apply(this, args),
|
|
5814
5955
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5815
5956
|
return SpanUtils.createAndExecuteSpan(self.mode, () => originalVerify.apply(this, args), {
|
|
@@ -5849,20 +5990,22 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
5849
5990
|
secretOrPrivateKey: signConfig.secretOrPrivateKey,
|
|
5850
5991
|
options: signConfig.options
|
|
5851
5992
|
};
|
|
5852
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
|
|
5865
|
-
|
|
5993
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5994
|
+
const stackTrace = captureStackTrace(["JsonwebtokenInstrumentation"]);
|
|
5995
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5996
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSign.apply(this, args), {
|
|
5997
|
+
name: "jsonwebtoken.sign",
|
|
5998
|
+
kind: SpanKind.CLIENT,
|
|
5999
|
+
submodule: "sign",
|
|
6000
|
+
packageName: "jsonwebtoken",
|
|
6001
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
6002
|
+
inputValue,
|
|
6003
|
+
isPreAppStart: false
|
|
6004
|
+
}, (spanInfo) => {
|
|
6005
|
+
return self.handleReplaySign(signConfig, inputValue, spanInfo, stackTrace);
|
|
6006
|
+
});
|
|
6007
|
+
} });
|
|
6008
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5866
6009
|
originalFunctionCall: () => originalSign.apply(this, args),
|
|
5867
6010
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5868
6011
|
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSign.apply(this, args), {
|
|
@@ -6030,18 +6173,19 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6030
6173
|
throw error;
|
|
6031
6174
|
}
|
|
6032
6175
|
}
|
|
6033
|
-
async handleReplayVerify(verifyConfig, inputValue, spanInfo) {
|
|
6176
|
+
async handleReplayVerify(verifyConfig, inputValue, spanInfo, stackTrace) {
|
|
6034
6177
|
logger.debug(`[JsonwebtokenInstrumentation] Replaying JWT verify`);
|
|
6035
6178
|
const mockData = await findMockResponseAsync({
|
|
6036
6179
|
mockRequestData: {
|
|
6037
6180
|
traceId: spanInfo.traceId,
|
|
6038
6181
|
spanId: spanInfo.spanId,
|
|
6039
|
-
name:
|
|
6182
|
+
name: "jsonwebtoken.verify",
|
|
6040
6183
|
packageName: "jsonwebtoken",
|
|
6041
6184
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
6042
6185
|
submoduleName: "verify",
|
|
6043
6186
|
inputValue,
|
|
6044
|
-
kind: SpanKind.CLIENT
|
|
6187
|
+
kind: SpanKind.CLIENT,
|
|
6188
|
+
stackTrace
|
|
6045
6189
|
},
|
|
6046
6190
|
tuskDrift: this.tuskDrift
|
|
6047
6191
|
});
|
|
@@ -6076,18 +6220,19 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6076
6220
|
return;
|
|
6077
6221
|
} else return result;
|
|
6078
6222
|
}
|
|
6079
|
-
async handleReplaySign(signConfig, inputValue, spanInfo) {
|
|
6223
|
+
async handleReplaySign(signConfig, inputValue, spanInfo, stackTrace) {
|
|
6080
6224
|
logger.debug(`[JsonwebtokenInstrumentation] Replaying JWT sign`);
|
|
6081
6225
|
const mockData = await findMockResponseAsync({
|
|
6082
6226
|
mockRequestData: {
|
|
6083
6227
|
traceId: spanInfo?.traceId,
|
|
6084
6228
|
spanId: spanInfo?.spanId,
|
|
6085
|
-
name:
|
|
6229
|
+
name: "jsonwebtoken.sign",
|
|
6086
6230
|
packageName: "jsonwebtoken",
|
|
6087
6231
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
6088
6232
|
submoduleName: "sign",
|
|
6089
6233
|
inputValue,
|
|
6090
|
-
kind: SpanKind.CLIENT
|
|
6234
|
+
kind: SpanKind.CLIENT,
|
|
6235
|
+
stackTrace
|
|
6091
6236
|
},
|
|
6092
6237
|
tuskDrift: this.tuskDrift
|
|
6093
6238
|
});
|
|
@@ -6491,11 +6636,12 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6491
6636
|
this.originalFetch = globalThis.fetch;
|
|
6492
6637
|
const self = this;
|
|
6493
6638
|
globalThis.fetch = function(input, init) {
|
|
6494
|
-
|
|
6639
|
+
const stackTrace = captureStackTrace(["FetchInstrumentation"]);
|
|
6640
|
+
return self._handleFetchRequest(input, init, stackTrace);
|
|
6495
6641
|
};
|
|
6496
6642
|
logger.debug("Global fetch patching complete");
|
|
6497
6643
|
}
|
|
6498
|
-
async _handleFetchRequest(input, init) {
|
|
6644
|
+
async _handleFetchRequest(input, init, stackTrace) {
|
|
6499
6645
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
6500
6646
|
const method = init?.method || "GET";
|
|
6501
6647
|
const headers = init?.headers || {};
|
|
@@ -6525,7 +6671,7 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6525
6671
|
inputValue,
|
|
6526
6672
|
isPreAppStart: false
|
|
6527
6673
|
}, (spanInfo) => {
|
|
6528
|
-
return this._handleReplayFetch(inputValue, spanInfo);
|
|
6674
|
+
return this._handleReplayFetch(inputValue, spanInfo, stackTrace);
|
|
6529
6675
|
});
|
|
6530
6676
|
} });
|
|
6531
6677
|
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
@@ -6606,7 +6752,7 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6606
6752
|
});
|
|
6607
6753
|
});
|
|
6608
6754
|
}
|
|
6609
|
-
async _handleReplayFetch(inputValue, spanInfo) {
|
|
6755
|
+
async _handleReplayFetch(inputValue, spanInfo, stackTrace) {
|
|
6610
6756
|
const mockData = await findMockResponseAsync({
|
|
6611
6757
|
mockRequestData: {
|
|
6612
6758
|
traceId: spanInfo.traceId,
|
|
@@ -6617,7 +6763,8 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6617
6763
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
6618
6764
|
submoduleName: inputValue.method,
|
|
6619
6765
|
inputValue,
|
|
6620
|
-
kind: SpanKind.CLIENT
|
|
6766
|
+
kind: SpanKind.CLIENT,
|
|
6767
|
+
stackTrace
|
|
6621
6768
|
},
|
|
6622
6769
|
tuskDrift: this.tuskDrift,
|
|
6623
6770
|
inputValueSchemaMerges: {
|
|
@@ -6892,21 +7039,23 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
6892
7039
|
port: this.options?.port
|
|
6893
7040
|
}
|
|
6894
7041
|
};
|
|
6895
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
7042
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
7043
|
+
const stackTrace = captureStackTrace(["IORedisInstrumentation"]);
|
|
7044
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
7045
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSendCommand.apply(this, arguments), {
|
|
7046
|
+
name: `ioredis.${commandName}`,
|
|
7047
|
+
kind: SpanKind.CLIENT,
|
|
7048
|
+
submodule: commandName,
|
|
7049
|
+
packageType: PackageType.REDIS,
|
|
7050
|
+
packageName: "ioredis",
|
|
7051
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7052
|
+
inputValue,
|
|
7053
|
+
isPreAppStart: false
|
|
7054
|
+
}, (spanInfo) => {
|
|
7055
|
+
return self._handleReplaySendCommand(spanInfo, cmd, inputValue, commandName, stackTrace);
|
|
7056
|
+
});
|
|
7057
|
+
} });
|
|
7058
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
6910
7059
|
originalFunctionCall: () => originalSendCommand.apply(this, arguments),
|
|
6911
7060
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
6912
7061
|
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSendCommand.apply(this, arguments), {
|
|
@@ -7068,7 +7217,7 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7068
7217
|
});
|
|
7069
7218
|
return promise;
|
|
7070
7219
|
}
|
|
7071
|
-
async _handleReplaySendCommand(spanInfo, cmd, inputValue, commandName) {
|
|
7220
|
+
async _handleReplaySendCommand(spanInfo, cmd, inputValue, commandName, stackTrace) {
|
|
7072
7221
|
logger.debug(`[IORedisInstrumentation] Replaying IORedis command ${cmd.name}`);
|
|
7073
7222
|
const mockData = await findMockResponseAsync({
|
|
7074
7223
|
mockRequestData: {
|
|
@@ -7079,7 +7228,8 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7079
7228
|
packageName: "ioredis",
|
|
7080
7229
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
7081
7230
|
submoduleName: cmd.name,
|
|
7082
|
-
kind: SpanKind.CLIENT
|
|
7231
|
+
kind: SpanKind.CLIENT,
|
|
7232
|
+
stackTrace
|
|
7083
7233
|
},
|
|
7084
7234
|
tuskDrift: this.tuskDrift
|
|
7085
7235
|
});
|
|
@@ -7528,21 +7678,23 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7528
7678
|
jsonableStringMap
|
|
7529
7679
|
}
|
|
7530
7680
|
};
|
|
7531
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7681
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
7682
|
+
const stackTrace = captureStackTrace(["GrpcInstrumentation"]);
|
|
7683
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
7684
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
7685
|
+
name: "grpc.client.unary",
|
|
7686
|
+
kind: SpanKind.CLIENT,
|
|
7687
|
+
submodule: "client",
|
|
7688
|
+
packageType: PackageType.GRPC,
|
|
7689
|
+
packageName: GRPC_MODULE_NAME,
|
|
7690
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7691
|
+
inputValue,
|
|
7692
|
+
isPreAppStart: false
|
|
7693
|
+
}, (spanInfo) => {
|
|
7694
|
+
return self._handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor, stackTrace);
|
|
7695
|
+
});
|
|
7696
|
+
} });
|
|
7697
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
7546
7698
|
originalFunctionCall: () => original.apply(this, args),
|
|
7547
7699
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
7548
7700
|
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
@@ -7674,7 +7826,7 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7674
7826
|
isGrpcErrorOutput(result) {
|
|
7675
7827
|
return "error" in result;
|
|
7676
7828
|
}
|
|
7677
|
-
async _handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor) {
|
|
7829
|
+
async _handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor, stackTrace) {
|
|
7678
7830
|
logger.debug(`[GrpcInstrumentation] Replaying gRPC unary request`);
|
|
7679
7831
|
const mockData = await findMockResponseAsync({
|
|
7680
7832
|
mockRequestData: {
|
|
@@ -7685,7 +7837,8 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7685
7837
|
packageName: GRPC_MODULE_NAME,
|
|
7686
7838
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
7687
7839
|
submoduleName: "client",
|
|
7688
|
-
kind: SpanKind.CLIENT
|
|
7840
|
+
kind: SpanKind.CLIENT,
|
|
7841
|
+
stackTrace
|
|
7689
7842
|
},
|
|
7690
7843
|
tuskDrift: this.tuskDrift
|
|
7691
7844
|
});
|
|
@@ -10315,7 +10468,7 @@ var SpanTransformer = class SpanTransformer {
|
|
|
10315
10468
|
if (transformMetadataString) try {
|
|
10316
10469
|
transformMetadata = JSON.parse(transformMetadataString);
|
|
10317
10470
|
} catch (error) {
|
|
10318
|
-
logger.warn("Failed to parse transform metadata", error);
|
|
10471
|
+
logger.warn("[SpanTransformer] Failed to parse transform metadata", error);
|
|
10319
10472
|
}
|
|
10320
10473
|
const originalDate = OriginalGlobalUtils.getOriginalDate();
|
|
10321
10474
|
return {
|
|
@@ -10701,7 +10854,7 @@ var ProtobufCommunicator = class {
|
|
|
10701
10854
|
requestId,
|
|
10702
10855
|
tags: {},
|
|
10703
10856
|
outboundSpan: cleanSpan,
|
|
10704
|
-
stackTrace:
|
|
10857
|
+
stackTrace: cleanSpan?.stackTrace
|
|
10705
10858
|
});
|
|
10706
10859
|
const sdkMessage = SDKMessage.create({
|
|
10707
10860
|
type: MessageType.MOCK_REQUEST,
|
|
@@ -10742,7 +10895,7 @@ var ProtobufCommunicator = class {
|
|
|
10742
10895
|
requestId,
|
|
10743
10896
|
tags: {},
|
|
10744
10897
|
outboundSpan: cleanSpan,
|
|
10745
|
-
stackTrace:
|
|
10898
|
+
stackTrace: cleanSpan?.stackTrace
|
|
10746
10899
|
});
|
|
10747
10900
|
const sdkMessage = SDKMessage.create({
|
|
10748
10901
|
type: MessageType.MOCK_REQUEST,
|
|
@@ -11034,7 +11187,7 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11034
11187
|
const packageName = this.getPackageName(modulePath);
|
|
11035
11188
|
if (packageName && TuskDriftInstrumentationModuleNames.includes(packageName)) alreadyRequiredModuleNames.add(packageName);
|
|
11036
11189
|
}
|
|
11037
|
-
} else logger.
|
|
11190
|
+
} else logger.debug("Running in ES Module mode. Cannot detect pre-loaded instrumentation modules.");
|
|
11038
11191
|
return alreadyRequiredModuleNames;
|
|
11039
11192
|
}
|
|
11040
11193
|
static getInstance() {
|
|
@@ -11140,13 +11293,13 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11140
11293
|
}
|
|
11141
11294
|
initialize(initParams) {
|
|
11142
11295
|
initializeGlobalLogger({
|
|
11143
|
-
logLevel: initParams.logLevel || "
|
|
11296
|
+
logLevel: initParams.logLevel || "info",
|
|
11144
11297
|
prefix: "TuskDrift"
|
|
11145
11298
|
});
|
|
11146
11299
|
this.samplingRate = this.config.recording?.sampling_rate ?? 1;
|
|
11147
11300
|
this.initParams = initParams;
|
|
11148
11301
|
if (!this.initParams.env) {
|
|
11149
|
-
const nodeEnv = OriginalGlobalUtils.getOriginalProcessEnvVar("NODE_ENV") || "
|
|
11302
|
+
const nodeEnv = OriginalGlobalUtils.getOriginalProcessEnvVar("NODE_ENV") || "development";
|
|
11150
11303
|
logger.warn(`Environment not provided in initialization parameters. Using '${nodeEnv}' as the environment.`);
|
|
11151
11304
|
this.initParams.env = nodeEnv;
|
|
11152
11305
|
}
|
|
@@ -11224,8 +11377,8 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11224
11377
|
}
|
|
11225
11378
|
this.appReady = true;
|
|
11226
11379
|
logger.debug("Application marked as ready");
|
|
11227
|
-
if (this.mode === TuskDriftMode.REPLAY) logger.
|
|
11228
|
-
else if (this.mode === TuskDriftMode.RECORD) logger.
|
|
11380
|
+
if (this.mode === TuskDriftMode.REPLAY) logger.debug("Replay mode active - ready to serve mocked responses");
|
|
11381
|
+
else if (this.mode === TuskDriftMode.RECORD) logger.debug("Record mode active - capturing inbound requests and responses");
|
|
11229
11382
|
}
|
|
11230
11383
|
async sendInboundSpanForReplay(span) {
|
|
11231
11384
|
try {
|