@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.cjs
CHANGED
|
@@ -273,7 +273,7 @@ var TdInstrumentationAbstract = class {
|
|
|
273
273
|
|
|
274
274
|
//#endregion
|
|
275
275
|
//#region package.json
|
|
276
|
-
var version = "0.1.
|
|
276
|
+
var version = "0.1.7";
|
|
277
277
|
|
|
278
278
|
//#endregion
|
|
279
279
|
//#region src/version.ts
|
|
@@ -1471,7 +1471,7 @@ var JsonSchemaHelper = class JsonSchemaHelper {
|
|
|
1471
1471
|
if (schema.decodedType === __use_tusk_drift_schemas_core_json_schema.DecodedType.JSON && typeof decodedValue === "string") decodedValue = JSON.parse(decodedValue);
|
|
1472
1472
|
decodedData[key] = decodedValue;
|
|
1473
1473
|
} catch (error) {
|
|
1474
|
-
logger.
|
|
1474
|
+
logger.debug(`[JsonSchemaHelper] Failed to decode ${key}:`, error);
|
|
1475
1475
|
decodedData[key] = data[key];
|
|
1476
1476
|
}
|
|
1477
1477
|
return decodedData;
|
|
@@ -1559,7 +1559,8 @@ function convertMockRequestDataToCleanSpanData(mockRequestData, tuskDrift, input
|
|
|
1559
1559
|
status: {
|
|
1560
1560
|
code: __use_tusk_drift_schemas_core_span.StatusCode.OK,
|
|
1561
1561
|
message: "OK"
|
|
1562
|
-
}
|
|
1562
|
+
},
|
|
1563
|
+
stackTrace: mockRequestData.stackTrace
|
|
1563
1564
|
};
|
|
1564
1565
|
}
|
|
1565
1566
|
/**
|
|
@@ -1604,7 +1605,7 @@ let ClientRequest;
|
|
|
1604
1605
|
* Mock ClientRequest implementation for Tusk Drift HTTP replay
|
|
1605
1606
|
*/
|
|
1606
1607
|
var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter {
|
|
1607
|
-
constructor(options, spanInfo, callback) {
|
|
1608
|
+
constructor(options, spanInfo, callback, stackTrace) {
|
|
1608
1609
|
super();
|
|
1609
1610
|
this.INSTRUMENTATION_NAME = "HttpInstrumentation";
|
|
1610
1611
|
this.finished = false;
|
|
@@ -1615,6 +1616,7 @@ var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter
|
|
|
1615
1616
|
TdMockClientRequest._setupPrototype();
|
|
1616
1617
|
this.tuskDrift = TuskDriftCore.getInstance();
|
|
1617
1618
|
this.spanInfo = spanInfo;
|
|
1619
|
+
this.stackTrace = stackTrace;
|
|
1618
1620
|
if (!options || Object.keys(options).length === 0) throw new Error("Making a request with empty `options` is not supported in TdMockClientRequest");
|
|
1619
1621
|
this.options = {
|
|
1620
1622
|
...options,
|
|
@@ -1750,7 +1752,8 @@ var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter
|
|
|
1750
1752
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
1751
1753
|
submoduleName: rawInputValue.method,
|
|
1752
1754
|
inputValue,
|
|
1753
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
1755
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
1756
|
+
stackTrace: this.stackTrace
|
|
1754
1757
|
},
|
|
1755
1758
|
tuskDrift: this.tuskDrift,
|
|
1756
1759
|
inputValueSchemaMerges: {
|
|
@@ -1894,7 +1897,7 @@ var HttpReplayHooks = class {
|
|
|
1894
1897
|
* Handle outbound HTTP requests in replay mode
|
|
1895
1898
|
* Uses TdMockClientRequest for simplified mocking approach
|
|
1896
1899
|
*/
|
|
1897
|
-
handleOutboundReplayRequest({ method, requestOptions, protocol, args, spanInfo }) {
|
|
1900
|
+
handleOutboundReplayRequest({ method, requestOptions, protocol, args, spanInfo, stackTrace }) {
|
|
1898
1901
|
logger.debug(`[HttpReplayHooks] Handling outbound ${protocol.toUpperCase()} ${method} request in replay mode`);
|
|
1899
1902
|
let callback;
|
|
1900
1903
|
if (args.length > 1 && typeof args[1] === "function") callback = args[1];
|
|
@@ -1911,7 +1914,7 @@ var HttpReplayHooks = class {
|
|
|
1911
1914
|
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
1912
1915
|
method
|
|
1913
1916
|
};
|
|
1914
|
-
const mockRequest = new TdMockClientRequest(mockOptions, spanInfo, callback);
|
|
1917
|
+
const mockRequest = new TdMockClientRequest(mockOptions, spanInfo, callback, stackTrace);
|
|
1915
1918
|
if (method === "GET" || method === "HEAD") process.nextTick(() => {
|
|
1916
1919
|
mockRequest.end();
|
|
1917
1920
|
});
|
|
@@ -1980,17 +1983,17 @@ function isWrapped$1(func) {
|
|
|
1980
1983
|
*/
|
|
1981
1984
|
function wrap(target, propertyName, wrapper) {
|
|
1982
1985
|
if (typeof target[propertyName] !== "function") {
|
|
1983
|
-
logger.
|
|
1986
|
+
logger.debug(`Cannot wrap non-function property: ${propertyName}`);
|
|
1984
1987
|
return;
|
|
1985
1988
|
}
|
|
1986
1989
|
if (isWrapped$1(target[propertyName])) {
|
|
1987
|
-
logger.
|
|
1990
|
+
logger.debug(`Property ${propertyName} is already wrapped`);
|
|
1988
1991
|
return;
|
|
1989
1992
|
}
|
|
1990
1993
|
const original = target[propertyName];
|
|
1991
1994
|
const wrapped = wrapper(original);
|
|
1992
1995
|
if (typeof wrapped !== "function") {
|
|
1993
|
-
logger.
|
|
1996
|
+
logger.debug(`Wrapper must return a function for property: ${propertyName}`);
|
|
1994
1997
|
return;
|
|
1995
1998
|
}
|
|
1996
1999
|
wrapped._isWrapped = true;
|
|
@@ -2000,6 +2003,45 @@ function wrap(target, propertyName, wrapper) {
|
|
|
2000
2003
|
return wrapped;
|
|
2001
2004
|
}
|
|
2002
2005
|
|
|
2006
|
+
//#endregion
|
|
2007
|
+
//#region src/instrumentation/core/utils/stackTraceUtils.ts
|
|
2008
|
+
/**
|
|
2009
|
+
* Helper functions for capturing stack traces in replay mode
|
|
2010
|
+
*
|
|
2011
|
+
* TODO: Consider using a structured format for stack frames:
|
|
2012
|
+
*
|
|
2013
|
+
* {
|
|
2014
|
+
* "frames": [
|
|
2015
|
+
* {
|
|
2016
|
+
* "fileName": "file.js",
|
|
2017
|
+
* "lineNumber": 10,
|
|
2018
|
+
* "columnNumber": 20,
|
|
2019
|
+
* "functionName": "functionName"
|
|
2020
|
+
* }
|
|
2021
|
+
* ]
|
|
2022
|
+
* }
|
|
2023
|
+
*
|
|
2024
|
+
* This would allow for more efficient matching and filtering of stack frames.
|
|
2025
|
+
* It would also allow for more accurate stack trace reconstruction in replay mode.
|
|
2026
|
+
*/
|
|
2027
|
+
/**
|
|
2028
|
+
*
|
|
2029
|
+
* @param excludeClassNames - Class names to exclude from the stack trace
|
|
2030
|
+
* @returns The stack trace as a string
|
|
2031
|
+
*/
|
|
2032
|
+
function captureStackTrace(excludeClassNames = []) {
|
|
2033
|
+
const originalStackTraceLimit = Error.stackTraceLimit;
|
|
2034
|
+
Error.stackTraceLimit = 100;
|
|
2035
|
+
const s = (/* @__PURE__ */ new Error()).stack || "";
|
|
2036
|
+
Error.stackTraceLimit = originalStackTraceLimit;
|
|
2037
|
+
const allExcludes = [...[
|
|
2038
|
+
"drift-node-sdk/src/instrumentation",
|
|
2039
|
+
"drift-node-sdk/src/core",
|
|
2040
|
+
"node_modules/@use-tusk"
|
|
2041
|
+
], ...excludeClassNames];
|
|
2042
|
+
return s.split("\n").slice(2).filter((l) => !allExcludes.some((exclude) => l.includes(exclude))).join("\n");
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2003
2045
|
//#endregion
|
|
2004
2046
|
//#region src/instrumentation/libraries/http/HttpTransformEngine.ts
|
|
2005
2047
|
/**
|
|
@@ -2948,37 +2990,40 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2948
2990
|
} else requestOptions = args[0] || {};
|
|
2949
2991
|
const method = requestOptions.method || "GET";
|
|
2950
2992
|
const requestProtocol = self._normalizeProtocol(requestOptions.protocol || void 0, protocol);
|
|
2951
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
2952
|
-
const
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
headers,
|
|
2957
|
-
protocol: requestProtocol,
|
|
2958
|
-
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
2959
|
-
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
2960
|
-
timeout: requestOptions.timeout || void 0
|
|
2961
|
-
};
|
|
2962
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
|
|
2963
|
-
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
2964
|
-
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
2965
|
-
packageName: requestProtocol,
|
|
2966
|
-
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
2967
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
2968
|
-
submodule: method,
|
|
2969
|
-
inputValue,
|
|
2970
|
-
isPreAppStart: false
|
|
2971
|
-
}, (spanInfo) => {
|
|
2972
|
-
return self.replayHooks.handleOutboundReplayRequest({
|
|
2993
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
2994
|
+
const stackTrace = captureStackTrace(["HttpInstrumentation"]);
|
|
2995
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
2996
|
+
const headers = normalizeHeaders(requestOptions.headers || {});
|
|
2997
|
+
const inputValue = {
|
|
2973
2998
|
method,
|
|
2974
|
-
requestOptions,
|
|
2999
|
+
path: requestOptions.path || void 0,
|
|
3000
|
+
headers,
|
|
2975
3001
|
protocol: requestProtocol,
|
|
2976
|
-
|
|
2977
|
-
|
|
3002
|
+
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
3003
|
+
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
3004
|
+
timeout: requestOptions.timeout || void 0
|
|
3005
|
+
};
|
|
3006
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
|
|
3007
|
+
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
3008
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3009
|
+
packageName: requestProtocol,
|
|
3010
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
3011
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3012
|
+
submodule: method,
|
|
3013
|
+
inputValue,
|
|
3014
|
+
isPreAppStart: false
|
|
3015
|
+
}, (spanInfo) => {
|
|
3016
|
+
return self.replayHooks.handleOutboundReplayRequest({
|
|
3017
|
+
method,
|
|
3018
|
+
requestOptions,
|
|
3019
|
+
protocol: requestProtocol,
|
|
3020
|
+
args,
|
|
3021
|
+
spanInfo,
|
|
3022
|
+
stackTrace
|
|
3023
|
+
});
|
|
2978
3024
|
});
|
|
2979
|
-
});
|
|
2980
|
-
}
|
|
2981
|
-
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3025
|
+
} });
|
|
3026
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
2982
3027
|
originalFunctionCall: () => originalRequest.apply(this, args),
|
|
2983
3028
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
2984
3029
|
const headers = normalizeHeaders(requestOptions.headers || {});
|
|
@@ -3433,6 +3478,7 @@ var TdPgClientMock = class extends events.EventEmitter {
|
|
|
3433
3478
|
}
|
|
3434
3479
|
query(...args) {
|
|
3435
3480
|
logger.debug(`[TdPgClientMock] Mock pool client query intercepted in REPLAY mode`);
|
|
3481
|
+
const stackTrace = captureStackTrace(["TdPgClientMock"]);
|
|
3436
3482
|
const queryConfig = this.pgInstrumentation.parseQueryArgs(args);
|
|
3437
3483
|
if (!queryConfig || !queryConfig.text) {
|
|
3438
3484
|
logger.debug(`[TdPgClientMock] Could not parse mock client query, returning empty result`);
|
|
@@ -3447,7 +3493,7 @@ var TdPgClientMock = class extends events.EventEmitter {
|
|
|
3447
3493
|
clientType: "client"
|
|
3448
3494
|
};
|
|
3449
3495
|
const inputValue = createMockInputValue(rawInputValue);
|
|
3450
|
-
return this.pgInstrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo);
|
|
3496
|
+
return this.pgInstrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
3451
3497
|
}
|
|
3452
3498
|
release() {
|
|
3453
3499
|
this.emit("end");
|
|
@@ -3550,23 +3596,25 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3550
3596
|
values: queryConfig.values || [],
|
|
3551
3597
|
clientType
|
|
3552
3598
|
};
|
|
3553
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
3554
|
-
const
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3599
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
3600
|
+
const stackTrace = captureStackTrace(["PgInstrumentation"]);
|
|
3601
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
3602
|
+
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
3603
|
+
const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
|
|
3604
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
|
|
3605
|
+
name: spanName,
|
|
3606
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3607
|
+
submodule: "query",
|
|
3608
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
3609
|
+
packageName,
|
|
3610
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3611
|
+
inputValue,
|
|
3612
|
+
isPreAppStart: false
|
|
3613
|
+
}, (spanInfo) => {
|
|
3614
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, stackTrace);
|
|
3615
|
+
});
|
|
3616
|
+
} });
|
|
3617
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3570
3618
|
originalFunctionCall: () => originalQuery.apply(this, args),
|
|
3571
3619
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
3572
3620
|
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
@@ -3712,7 +3760,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3712
3760
|
throw error;
|
|
3713
3761
|
});
|
|
3714
3762
|
}
|
|
3715
|
-
async handleReplayQuery(queryConfig, inputValue, spanInfo) {
|
|
3763
|
+
async handleReplayQuery(queryConfig, inputValue, spanInfo, stackTrace) {
|
|
3716
3764
|
logger.debug(`[PgInstrumentation] Replaying PG query`);
|
|
3717
3765
|
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
3718
3766
|
const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
|
|
@@ -3725,7 +3773,8 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3725
3773
|
packageName,
|
|
3726
3774
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
3727
3775
|
submoduleName: "query",
|
|
3728
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
3776
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3777
|
+
stackTrace
|
|
3729
3778
|
},
|
|
3730
3779
|
tuskDrift: this.tuskDrift
|
|
3731
3780
|
});
|
|
@@ -4193,26 +4242,29 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4193
4242
|
query: query.trim(),
|
|
4194
4243
|
parameters: values
|
|
4195
4244
|
};
|
|
4196
|
-
if (this.mode === TuskDriftMode.REPLAY)
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
packageName: "postgres",
|
|
4203
|
-
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4204
|
-
inputValue,
|
|
4205
|
-
isPreAppStart: false
|
|
4206
|
-
}, (spanInfo) => {
|
|
4207
|
-
return this.handleReplaySqlQuery({
|
|
4208
|
-
inputValue,
|
|
4209
|
-
spanInfo,
|
|
4245
|
+
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4246
|
+
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4247
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
4248
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => originalSql.call(this, strings, ...values), {
|
|
4249
|
+
name: "postgres.query",
|
|
4250
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4210
4251
|
submodule: "query",
|
|
4211
|
-
|
|
4252
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4253
|
+
packageName: "postgres",
|
|
4254
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4255
|
+
inputValue,
|
|
4256
|
+
isPreAppStart: false
|
|
4257
|
+
}, (spanInfo) => {
|
|
4258
|
+
return this.handleReplaySqlQuery({
|
|
4259
|
+
inputValue,
|
|
4260
|
+
spanInfo,
|
|
4261
|
+
submodule: "query",
|
|
4262
|
+
name: "postgres.query",
|
|
4263
|
+
stackTrace
|
|
4264
|
+
});
|
|
4212
4265
|
});
|
|
4213
|
-
});
|
|
4214
|
-
}
|
|
4215
|
-
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4266
|
+
} });
|
|
4267
|
+
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4216
4268
|
originalFunctionCall: () => originalSql.call(this, strings, ...values),
|
|
4217
4269
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
4218
4270
|
return SpanUtils.createAndExecuteSpan(this.mode, () => originalSql.call(this, strings, ...values), {
|
|
@@ -4243,28 +4295,31 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4243
4295
|
parameters: parameters || [],
|
|
4244
4296
|
options: queryOptions
|
|
4245
4297
|
};
|
|
4246
|
-
if (this.mode === TuskDriftMode.REPLAY)
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
packageName: "postgres",
|
|
4254
|
-
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4255
|
-
inputValue,
|
|
4256
|
-
isPreAppStart: false
|
|
4257
|
-
}, (spanInfo) => {
|
|
4258
|
-
return this.handleReplayUnsafeQuery({
|
|
4259
|
-
inputValue,
|
|
4260
|
-
spanInfo,
|
|
4298
|
+
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4299
|
+
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4300
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
4301
|
+
return this._createPendingQueryWrapper(() => {
|
|
4302
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => executeUnsafe(), {
|
|
4303
|
+
name: "postgres.unsafe",
|
|
4304
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4261
4305
|
submodule: "unsafe",
|
|
4262
|
-
|
|
4306
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4307
|
+
packageName: "postgres",
|
|
4308
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4309
|
+
inputValue,
|
|
4310
|
+
isPreAppStart: false
|
|
4311
|
+
}, (spanInfo) => {
|
|
4312
|
+
return this.handleReplayUnsafeQuery({
|
|
4313
|
+
inputValue,
|
|
4314
|
+
spanInfo,
|
|
4315
|
+
submodule: "unsafe",
|
|
4316
|
+
name: "postgres.unsafe",
|
|
4317
|
+
stackTrace
|
|
4318
|
+
});
|
|
4263
4319
|
});
|
|
4264
4320
|
});
|
|
4265
|
-
});
|
|
4266
|
-
}
|
|
4267
|
-
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4321
|
+
} });
|
|
4322
|
+
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4268
4323
|
originalFunctionCall: executeUnsafe,
|
|
4269
4324
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
4270
4325
|
return SpanUtils.createAndExecuteSpan(this.mode, executeUnsafe, {
|
|
@@ -4294,21 +4349,23 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4294
4349
|
else if (transactionCallback) return originalBegin.call(sqlInstance, transactionCallback);
|
|
4295
4350
|
else return originalBegin.call(sqlInstance, options || void 0);
|
|
4296
4351
|
};
|
|
4297
|
-
if (this.mode === TuskDriftMode.REPLAY)
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4352
|
+
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4353
|
+
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4354
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
4355
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => executeBegin(), {
|
|
4356
|
+
name: "postgres.begin",
|
|
4357
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4358
|
+
submodule: "transaction",
|
|
4359
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4360
|
+
packageName: "postgres",
|
|
4361
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4362
|
+
inputValue,
|
|
4363
|
+
isPreAppStart: false
|
|
4364
|
+
}, (spanInfo) => {
|
|
4365
|
+
return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
|
|
4366
|
+
});
|
|
4367
|
+
} });
|
|
4368
|
+
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4312
4369
|
originalFunctionCall: executeBegin,
|
|
4313
4370
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
4314
4371
|
return SpanUtils.createAndExecuteSpan(this.mode, executeBegin, {
|
|
@@ -4402,7 +4459,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4402
4459
|
});
|
|
4403
4460
|
return promise;
|
|
4404
4461
|
}
|
|
4405
|
-
async _handleReplayBeginTransaction(spanInfo, options) {
|
|
4462
|
+
async _handleReplayBeginTransaction(spanInfo, options, stackTrace) {
|
|
4406
4463
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
|
|
4407
4464
|
const mockData = await findMockResponseAsync({
|
|
4408
4465
|
mockRequestData: {
|
|
@@ -4416,7 +4473,8 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4416
4473
|
packageName: "postgres",
|
|
4417
4474
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4418
4475
|
submoduleName: "transaction",
|
|
4419
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
4476
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4477
|
+
stackTrace
|
|
4420
4478
|
},
|
|
4421
4479
|
tuskDrift: this.tuskDrift
|
|
4422
4480
|
});
|
|
@@ -4471,7 +4529,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4471
4529
|
throw error;
|
|
4472
4530
|
}
|
|
4473
4531
|
}
|
|
4474
|
-
async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name }) {
|
|
4532
|
+
async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
|
|
4475
4533
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres sql query`);
|
|
4476
4534
|
const mockData = await findMockResponseAsync({
|
|
4477
4535
|
mockRequestData: {
|
|
@@ -4482,7 +4540,8 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4482
4540
|
packageName: "postgres",
|
|
4483
4541
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4484
4542
|
submoduleName: submodule,
|
|
4485
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
4543
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4544
|
+
stackTrace
|
|
4486
4545
|
},
|
|
4487
4546
|
tuskDrift: this.tuskDrift
|
|
4488
4547
|
});
|
|
@@ -4501,7 +4560,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4501
4560
|
count: isResultObject ? processedResult.count : void 0
|
|
4502
4561
|
});
|
|
4503
4562
|
}
|
|
4504
|
-
async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name }) {
|
|
4563
|
+
async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
|
|
4505
4564
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres unsafe query`);
|
|
4506
4565
|
const mockData = await findMockResponseAsync({
|
|
4507
4566
|
mockRequestData: {
|
|
@@ -4512,7 +4571,8 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4512
4571
|
packageName: "postgres",
|
|
4513
4572
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4514
4573
|
submoduleName: submodule,
|
|
4515
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
4574
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4575
|
+
stackTrace
|
|
4516
4576
|
},
|
|
4517
4577
|
tuskDrift: this.tuskDrift
|
|
4518
4578
|
});
|
|
@@ -4624,6 +4684,7 @@ var TdMysql2ConnectionMock = class extends events.EventEmitter {
|
|
|
4624
4684
|
}
|
|
4625
4685
|
query(...args) {
|
|
4626
4686
|
logger.debug(`[TdMysql2ConnectionMock] Mock connection query intercepted in REPLAY mode`);
|
|
4687
|
+
const stackTrace = captureStackTrace(["TdMysql2ConnectionMock"]);
|
|
4627
4688
|
const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args);
|
|
4628
4689
|
if (!queryConfig || !queryConfig.sql) {
|
|
4629
4690
|
logger.debug(`[TdMysql2ConnectionMock] Could not parse mock connection query, returning empty result`);
|
|
@@ -4643,10 +4704,11 @@ var TdMysql2ConnectionMock = class extends events.EventEmitter {
|
|
|
4643
4704
|
clientType: this.clientType
|
|
4644
4705
|
};
|
|
4645
4706
|
const inputValue = createMockInputValue(rawInputValue);
|
|
4646
|
-
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo);
|
|
4707
|
+
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4647
4708
|
}
|
|
4648
4709
|
execute(...args) {
|
|
4649
4710
|
logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`);
|
|
4711
|
+
const stackTrace = captureStackTrace(["TdMysql2ConnectionMock"]);
|
|
4650
4712
|
const queryConfig = this.mysql2Instrumentation.parseQueryArgs(args);
|
|
4651
4713
|
if (!queryConfig || !queryConfig.sql) {
|
|
4652
4714
|
logger.debug(`[TdMysql2ConnectionMock] Could not parse mock connection execute, returning empty result`);
|
|
@@ -4666,7 +4728,7 @@ var TdMysql2ConnectionMock = class extends events.EventEmitter {
|
|
|
4666
4728
|
clientType: this.clientType
|
|
4667
4729
|
};
|
|
4668
4730
|
const inputValue = createMockInputValue(rawInputValue);
|
|
4669
|
-
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo);
|
|
4731
|
+
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4670
4732
|
}
|
|
4671
4733
|
release() {
|
|
4672
4734
|
this.emit("end");
|
|
@@ -4760,20 +4822,33 @@ var TdMysql2QueryMock = class {
|
|
|
4760
4822
|
/**
|
|
4761
4823
|
* Handle replay of a MySQL2 query (query or execute)
|
|
4762
4824
|
*/
|
|
4763
|
-
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query") {
|
|
4825
|
+
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query", stackTrace) {
|
|
4764
4826
|
logger.debug(`[Mysql2Instrumentation] Replaying MySQL2 query`);
|
|
4765
4827
|
const spanName = `mysql2.${inputValue.clientType}.${submoduleName}`;
|
|
4766
|
-
return this._handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName);
|
|
4828
|
+
return this._handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName, stackTrace);
|
|
4767
4829
|
}
|
|
4768
4830
|
/**
|
|
4769
4831
|
* Handle query - always returns an EventEmitter (like mysql2 does)
|
|
4770
4832
|
* This handles both callback and streaming modes
|
|
4833
|
+
* The EventEmitter is also thenable (has a .then() method) to support await/Promise usage
|
|
4771
4834
|
*/
|
|
4772
|
-
_handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName) {
|
|
4835
|
+
_handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName, stackTrace) {
|
|
4773
4836
|
const emitter = new events.EventEmitter();
|
|
4837
|
+
let storedRows = null;
|
|
4838
|
+
let storedFields = null;
|
|
4839
|
+
emitter.then = function(onResolve, onReject) {
|
|
4840
|
+
return new Promise((resolve, reject) => {
|
|
4841
|
+
emitter.once("end", () => {
|
|
4842
|
+
resolve([storedRows, storedFields]);
|
|
4843
|
+
});
|
|
4844
|
+
emitter.once("error", (error) => {
|
|
4845
|
+
reject(error);
|
|
4846
|
+
});
|
|
4847
|
+
}).then(onResolve, onReject);
|
|
4848
|
+
};
|
|
4774
4849
|
(async () => {
|
|
4775
4850
|
try {
|
|
4776
|
-
const mockData = await this._fetchMockData(inputValue, spanInfo, spanName, submoduleName);
|
|
4851
|
+
const mockData = await this._fetchMockData(inputValue, spanInfo, spanName, submoduleName, stackTrace);
|
|
4777
4852
|
if (!mockData) {
|
|
4778
4853
|
const sql = queryConfig.sql || inputValue.sql || "UNKNOWN_QUERY";
|
|
4779
4854
|
logger.warn(`[Mysql2Instrumentation] No mock data found for MySQL2 query: ${sql}`);
|
|
@@ -4785,6 +4860,8 @@ var TdMysql2QueryMock = class {
|
|
|
4785
4860
|
return;
|
|
4786
4861
|
}
|
|
4787
4862
|
const processedResult = this._convertMysql2Types(mockData.result);
|
|
4863
|
+
storedRows = processedResult.rows;
|
|
4864
|
+
storedFields = processedResult.fields;
|
|
4788
4865
|
process.nextTick(() => {
|
|
4789
4866
|
if (processedResult.fields) emitter.emit("fields", processedResult.fields);
|
|
4790
4867
|
if (queryConfig.callback) queryConfig.callback(null, processedResult.rows, processedResult.fields);
|
|
@@ -4804,7 +4881,7 @@ var TdMysql2QueryMock = class {
|
|
|
4804
4881
|
/**
|
|
4805
4882
|
* Fetch mock data from CLI
|
|
4806
4883
|
*/
|
|
4807
|
-
async _fetchMockData(inputValue, spanInfo, spanName, submoduleName) {
|
|
4884
|
+
async _fetchMockData(inputValue, spanInfo, spanName, submoduleName, stackTrace) {
|
|
4808
4885
|
return await findMockResponseAsync({
|
|
4809
4886
|
mockRequestData: {
|
|
4810
4887
|
traceId: spanInfo.traceId,
|
|
@@ -4814,7 +4891,8 @@ var TdMysql2QueryMock = class {
|
|
|
4814
4891
|
packageName: "mysql2",
|
|
4815
4892
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4816
4893
|
submoduleName,
|
|
4817
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
4894
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4895
|
+
stackTrace
|
|
4818
4896
|
},
|
|
4819
4897
|
tuskDrift: this.tuskDrift
|
|
4820
4898
|
});
|
|
@@ -4838,6 +4916,52 @@ var TdMysql2QueryMock = class {
|
|
|
4838
4916
|
}
|
|
4839
4917
|
};
|
|
4840
4918
|
|
|
4919
|
+
//#endregion
|
|
4920
|
+
//#region src/instrumentation/libraries/mysql2/mocks/TdMysql2ConnectionEventMock.ts
|
|
4921
|
+
/**
|
|
4922
|
+
* Mock for MySQL2 connection events (connect/error)
|
|
4923
|
+
* Handles replay of recorded connection establishment events in REPLAY mode
|
|
4924
|
+
* Recording happens through normal SpanUtils flow in RECORD mode
|
|
4925
|
+
*/
|
|
4926
|
+
var TdMysql2ConnectionEventMock = class {
|
|
4927
|
+
constructor(spanInfo) {
|
|
4928
|
+
this.INSTRUMENTATION_NAME = "Mysql2Instrumentation";
|
|
4929
|
+
this.spanInfo = spanInfo;
|
|
4930
|
+
this.tuskDrift = TuskDriftCore.getInstance();
|
|
4931
|
+
}
|
|
4932
|
+
/**
|
|
4933
|
+
* Get recorded connection event for replay
|
|
4934
|
+
* Returns { output } for success, or throws error if connection failed
|
|
4935
|
+
* The connection events are recorded automatically via SpanUtils in record mode
|
|
4936
|
+
*/
|
|
4937
|
+
async getReplayedConnectionEvent(inputValue) {
|
|
4938
|
+
logger.debug(`[TdMysql2ConnectionEventMock] Retrieving recorded connection event`);
|
|
4939
|
+
try {
|
|
4940
|
+
const mockData = await findMockResponseAsync({
|
|
4941
|
+
mockRequestData: {
|
|
4942
|
+
traceId: this.spanInfo.traceId,
|
|
4943
|
+
spanId: this.spanInfo.spanId,
|
|
4944
|
+
name: "mysql2.connection.create",
|
|
4945
|
+
inputValue,
|
|
4946
|
+
packageName: "mysql2",
|
|
4947
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4948
|
+
submoduleName: "connectEvent",
|
|
4949
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
4950
|
+
},
|
|
4951
|
+
tuskDrift: this.tuskDrift
|
|
4952
|
+
});
|
|
4953
|
+
if (!mockData) {
|
|
4954
|
+
logger.warn(`[TdMysql2ConnectionEventMock] No mock data found, using default success`);
|
|
4955
|
+
return { output: {} };
|
|
4956
|
+
}
|
|
4957
|
+
return { output: mockData.result || {} };
|
|
4958
|
+
} catch (error) {
|
|
4959
|
+
logger.error(`[TdMysql2ConnectionEventMock] Error getting replay value:`, error);
|
|
4960
|
+
return { output: {} };
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
};
|
|
4964
|
+
|
|
4841
4965
|
//#endregion
|
|
4842
4966
|
//#region src/instrumentation/libraries/mysql2/Instrumentation.ts
|
|
4843
4967
|
const COMPLETE_SUPPORTED_VERSIONS = ">=2.3.3 <4.0.0";
|
|
@@ -4889,16 +5013,6 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
4889
5013
|
name: "mysql2/lib/pool_connection.js",
|
|
4890
5014
|
supportedVersions: [V3_11_5_TO_4_0],
|
|
4891
5015
|
patch: (moduleExports) => this._patchPoolConnectionV3(moduleExports)
|
|
4892
|
-
}),
|
|
4893
|
-
new TdInstrumentationNodeModuleFile({
|
|
4894
|
-
name: "mysql2/lib/create_connection.js",
|
|
4895
|
-
supportedVersions: [COMPLETE_SUPPORTED_VERSIONS],
|
|
4896
|
-
patch: (moduleExports) => this._patchCreateConnectionFile(moduleExports)
|
|
4897
|
-
}),
|
|
4898
|
-
new TdInstrumentationNodeModuleFile({
|
|
4899
|
-
name: "mysql2/lib/create_pool.js",
|
|
4900
|
-
supportedVersions: [COMPLETE_SUPPORTED_VERSIONS],
|
|
4901
|
-
patch: (moduleExports) => this._patchCreatePoolFile(moduleExports)
|
|
4902
5016
|
})
|
|
4903
5017
|
]
|
|
4904
5018
|
})];
|
|
@@ -4950,13 +5064,14 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
4950
5064
|
return ConnectionClass;
|
|
4951
5065
|
}
|
|
4952
5066
|
this._patchConnectionPrototypes(ConnectionClass);
|
|
5067
|
+
const patchedConnectionClass = this._getPatchedConnectionClass(ConnectionClass);
|
|
4953
5068
|
this.markModuleAsPatched(ConnectionClass);
|
|
4954
5069
|
logger.debug(`[Mysql2Instrumentation] Connection class (v2) patching complete`);
|
|
4955
|
-
return
|
|
5070
|
+
return patchedConnectionClass;
|
|
4956
5071
|
}
|
|
4957
5072
|
_patchConnectionV3(ConnectionClass) {
|
|
4958
|
-
logger.debug(`[Mysql2Instrumentation] Connection class (v3) -
|
|
4959
|
-
return ConnectionClass;
|
|
5073
|
+
logger.debug(`[Mysql2Instrumentation] Connection class (v3) - wrapping constructor only`);
|
|
5074
|
+
return this._getPatchedConnectionClass(ConnectionClass);
|
|
4960
5075
|
}
|
|
4961
5076
|
_patchConnectionPrototypes(ConnectionClass) {
|
|
4962
5077
|
if (ConnectionClass.prototype && ConnectionClass.prototype.query) {
|
|
@@ -5065,22 +5180,24 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5065
5180
|
values: queryConfig.values || [],
|
|
5066
5181
|
clientType
|
|
5067
5182
|
};
|
|
5068
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5069
|
-
const
|
|
5070
|
-
return
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5183
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5184
|
+
const stackTrace = captureStackTrace(["Mysql2Instrumentation"]);
|
|
5185
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5186
|
+
const spanName = `mysql2.${clientType}.query`;
|
|
5187
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
|
|
5188
|
+
name: spanName,
|
|
5189
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5190
|
+
submodule: "query",
|
|
5191
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5192
|
+
packageName: "mysql2",
|
|
5193
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5194
|
+
inputValue,
|
|
5195
|
+
isPreAppStart: false
|
|
5196
|
+
}, (spanInfo) => {
|
|
5197
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, "query", stackTrace);
|
|
5198
|
+
});
|
|
5199
|
+
} });
|
|
5200
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5084
5201
|
originalFunctionCall: () => originalQuery.apply(this, args),
|
|
5085
5202
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5086
5203
|
const spanName = `mysql2.${clientType}.query`;
|
|
@@ -5122,22 +5239,24 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5122
5239
|
values: queryConfig.values || [],
|
|
5123
5240
|
clientType
|
|
5124
5241
|
};
|
|
5125
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5126
|
-
const
|
|
5127
|
-
return
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5242
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5243
|
+
const stackTrace = captureStackTrace(["Mysql2Instrumentation"]);
|
|
5244
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5245
|
+
const spanName = `mysql2.${clientType}.execute`;
|
|
5246
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalExecute.apply(this, args), {
|
|
5247
|
+
name: spanName,
|
|
5248
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5249
|
+
submodule: "execute",
|
|
5250
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5251
|
+
packageName: "mysql2",
|
|
5252
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5253
|
+
inputValue,
|
|
5254
|
+
isPreAppStart: false
|
|
5255
|
+
}, (spanInfo) => {
|
|
5256
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, "execute", stackTrace);
|
|
5257
|
+
});
|
|
5258
|
+
} });
|
|
5259
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5141
5260
|
originalFunctionCall: () => originalExecute.apply(this, args),
|
|
5142
5261
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5143
5262
|
const spanName = `mysql2.${clientType}.execute`;
|
|
@@ -5485,8 +5604,8 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5485
5604
|
return result;
|
|
5486
5605
|
}
|
|
5487
5606
|
}
|
|
5488
|
-
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query") {
|
|
5489
|
-
return this.queryMock.handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName);
|
|
5607
|
+
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query", stackTrace) {
|
|
5608
|
+
return this.queryMock.handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName, stackTrace);
|
|
5490
5609
|
}
|
|
5491
5610
|
_handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$4) {
|
|
5492
5611
|
if (callback) {
|
|
@@ -5549,117 +5668,137 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5549
5668
|
return;
|
|
5550
5669
|
} else return Promise.resolve(mockConnection);
|
|
5551
5670
|
}
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
affectedRows: result.affectedRows,
|
|
5562
|
-
insertId: result.insertId,
|
|
5563
|
-
warningCount: result.warningCount
|
|
5564
|
-
};
|
|
5565
|
-
else outputValue = result;
|
|
5566
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
|
|
5567
|
-
}
|
|
5568
|
-
_patchCreateConnectionFile(createConnectionFn) {
|
|
5569
|
-
logger.debug(`[Mysql2Instrumentation] Patching create_connection.js file`);
|
|
5671
|
+
/**
|
|
5672
|
+
* Creates a patched Connection class that intercepts the constructor
|
|
5673
|
+
* to handle connection event recording/replay.
|
|
5674
|
+
*
|
|
5675
|
+
* Wrap the Connection constructor to:
|
|
5676
|
+
* - In RECORD mode: listen for 'connect'/'error' events and record them
|
|
5677
|
+
* - In REPLAY mode: create a MockConnection that fakes the connection and emits recorded events
|
|
5678
|
+
*/
|
|
5679
|
+
_getPatchedConnectionClass(OriginalConnection) {
|
|
5570
5680
|
const self = this;
|
|
5571
|
-
|
|
5681
|
+
function TdPatchedConnection(...args) {
|
|
5572
5682
|
const inputValue = { method: "createConnection" };
|
|
5573
|
-
if (self.mode === TuskDriftMode.
|
|
5574
|
-
|
|
5575
|
-
name: `mysql2.createConnection`,
|
|
5576
|
-
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5577
|
-
submodule: "createConnection",
|
|
5578
|
-
packageName: "mysql2",
|
|
5579
|
-
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5580
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5581
|
-
inputValue,
|
|
5582
|
-
isPreAppStart: false
|
|
5583
|
-
}, (spanInfo) => {
|
|
5584
|
-
const connection = createConnectionFn.apply(this, args);
|
|
5585
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { created: true } });
|
|
5586
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
5587
|
-
return connection;
|
|
5588
|
-
});
|
|
5589
|
-
} });
|
|
5590
|
-
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5591
|
-
originalFunctionCall: () => createConnectionFn.apply(this, args),
|
|
5683
|
+
if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5684
|
+
originalFunctionCall: () => new OriginalConnection(...args),
|
|
5592
5685
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5593
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () =>
|
|
5594
|
-
name: `mysql2.
|
|
5686
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => new OriginalConnection(...args), {
|
|
5687
|
+
name: `mysql2.connection.create`,
|
|
5595
5688
|
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5596
|
-
submodule: "
|
|
5597
|
-
packageName: "mysql2",
|
|
5689
|
+
submodule: "connectEvent",
|
|
5598
5690
|
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5691
|
+
packageName: "mysql2",
|
|
5599
5692
|
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5600
5693
|
inputValue,
|
|
5601
5694
|
isPreAppStart
|
|
5602
5695
|
}, (spanInfo) => {
|
|
5603
|
-
const connection =
|
|
5604
|
-
|
|
5605
|
-
|
|
5696
|
+
const connection = new OriginalConnection(...args);
|
|
5697
|
+
connection.on("connect", (connectionObj) => {
|
|
5698
|
+
try {
|
|
5699
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
|
|
5700
|
+
connected: true,
|
|
5701
|
+
connectionObj
|
|
5702
|
+
} });
|
|
5703
|
+
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
5704
|
+
} catch {
|
|
5705
|
+
logger.error(`[Mysql2Instrumentation] error adding span attributes:`);
|
|
5706
|
+
}
|
|
5707
|
+
});
|
|
5708
|
+
connection.on("error", (err) => {
|
|
5709
|
+
try {
|
|
5710
|
+
logger.debug(`[Mysql2Instrumentation] Connection error, recording: ${err.message}`);
|
|
5711
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
5712
|
+
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
5713
|
+
message: err.message
|
|
5714
|
+
});
|
|
5715
|
+
} catch {
|
|
5716
|
+
logger.error(`[Mysql2Instrumentation] error ending span`);
|
|
5717
|
+
}
|
|
5718
|
+
});
|
|
5606
5719
|
return connection;
|
|
5607
5720
|
});
|
|
5608
5721
|
},
|
|
5609
5722
|
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
5610
5723
|
});
|
|
5611
|
-
else return createConnectionFn.apply(this, args);
|
|
5612
|
-
};
|
|
5613
|
-
logger.debug(`[Mysql2Instrumentation] Patched create_connection.js file`);
|
|
5614
|
-
return wrappedFn;
|
|
5615
|
-
}
|
|
5616
|
-
_patchCreatePoolFile(createPoolFn) {
|
|
5617
|
-
logger.debug(`[Mysql2Instrumentation] Patching create_pool.js file`);
|
|
5618
|
-
const self = this;
|
|
5619
|
-
const wrappedFn = function(...args) {
|
|
5620
|
-
const inputValue = { method: "createPool" };
|
|
5621
5724
|
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({ replayModeHandler: () => {
|
|
5622
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () =>
|
|
5623
|
-
name: `mysql2.
|
|
5725
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => new OriginalConnection(...args), {
|
|
5726
|
+
name: `mysql2.connection.create`,
|
|
5624
5727
|
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5625
|
-
submodule: "
|
|
5626
|
-
packageName: "mysql2",
|
|
5728
|
+
submodule: "connectEvent",
|
|
5627
5729
|
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5730
|
+
packageName: "mysql2",
|
|
5628
5731
|
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5629
5732
|
inputValue,
|
|
5630
5733
|
isPreAppStart: false
|
|
5631
5734
|
}, (spanInfo) => {
|
|
5632
|
-
|
|
5633
|
-
|
|
5735
|
+
class MockConnection extends OriginalConnection {
|
|
5736
|
+
constructor(...mockConnectionArgs) {
|
|
5737
|
+
const clonedArgs = JSON.parse(JSON.stringify(mockConnectionArgs));
|
|
5738
|
+
if (clonedArgs[0] && clonedArgs[0].config) {
|
|
5739
|
+
clonedArgs[0].config.host = "127.0.0.1";
|
|
5740
|
+
clonedArgs[0].config.port = 127;
|
|
5741
|
+
} else if (clonedArgs[0]) {
|
|
5742
|
+
clonedArgs[0].host = "127.0.0.1";
|
|
5743
|
+
clonedArgs[0].port = 127;
|
|
5744
|
+
}
|
|
5745
|
+
super(...clonedArgs);
|
|
5746
|
+
this._isConnectOrErrorEmitted = false;
|
|
5747
|
+
this._connectEventMock = new TdMysql2ConnectionEventMock(spanInfo);
|
|
5748
|
+
}
|
|
5749
|
+
on(event, listener) {
|
|
5750
|
+
if (!this._connectEventMock) return super.on(event, listener);
|
|
5751
|
+
if (event === "connect" && !this._isConnectOrErrorEmitted) {
|
|
5752
|
+
this._connectEventMock.getReplayedConnectionEvent(inputValue).then(({ output }) => {
|
|
5753
|
+
if (output !== void 0) process.nextTick(() => {
|
|
5754
|
+
listener.call(this, output);
|
|
5755
|
+
this._isConnectOrErrorEmitted = true;
|
|
5756
|
+
});
|
|
5757
|
+
}).catch((err) => {
|
|
5758
|
+
logger.error(`[Mysql2Instrumentation] Error replaying connection event:`, err);
|
|
5759
|
+
});
|
|
5760
|
+
return this;
|
|
5761
|
+
}
|
|
5762
|
+
if (event === "error" && !this._isConnectOrErrorEmitted) return this;
|
|
5763
|
+
return super.on(event, listener);
|
|
5764
|
+
}
|
|
5765
|
+
}
|
|
5766
|
+
const mockConnection = new MockConnection(...args);
|
|
5767
|
+
mockConnection.addListener("error", (_err) => {});
|
|
5768
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
|
|
5769
|
+
connected: true,
|
|
5770
|
+
mock: true
|
|
5771
|
+
} });
|
|
5634
5772
|
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
5635
|
-
return
|
|
5773
|
+
return mockConnection;
|
|
5636
5774
|
});
|
|
5637
5775
|
} });
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5776
|
+
return new OriginalConnection(...args);
|
|
5777
|
+
}
|
|
5778
|
+
const staticProps = Object.getOwnPropertyNames(OriginalConnection).filter((key) => ![
|
|
5779
|
+
"length",
|
|
5780
|
+
"name",
|
|
5781
|
+
"prototype"
|
|
5782
|
+
].includes(key));
|
|
5783
|
+
for (const staticProp of staticProps) TdPatchedConnection[staticProp] = OriginalConnection[staticProp];
|
|
5784
|
+
Object.setPrototypeOf(TdPatchedConnection.prototype, OriginalConnection.prototype);
|
|
5785
|
+
return TdPatchedConnection;
|
|
5786
|
+
}
|
|
5787
|
+
_addOutputAttributesToSpan(spanInfo, result, fields) {
|
|
5788
|
+
if (!result) return;
|
|
5789
|
+
let outputValue = {};
|
|
5790
|
+
if (Array.isArray(result)) outputValue = {
|
|
5791
|
+
rowCount: result.length,
|
|
5792
|
+
rows: result,
|
|
5793
|
+
fields: fields || []
|
|
5794
|
+
};
|
|
5795
|
+
else if (result.affectedRows !== void 0) outputValue = {
|
|
5796
|
+
affectedRows: result.affectedRows,
|
|
5797
|
+
insertId: result.insertId,
|
|
5798
|
+
warningCount: result.warningCount
|
|
5660
5799
|
};
|
|
5661
|
-
|
|
5662
|
-
|
|
5800
|
+
else outputValue = result;
|
|
5801
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
|
|
5663
5802
|
}
|
|
5664
5803
|
_wrap(target, propertyName, wrapper) {
|
|
5665
5804
|
wrap(target, propertyName, wrapper);
|
|
@@ -5817,20 +5956,22 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
5817
5956
|
logger.error(`[JsonwebtokenInstrumentation] error creating mock input value:`, error);
|
|
5818
5957
|
return originalVerify.apply(this, args);
|
|
5819
5958
|
}
|
|
5820
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5959
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5960
|
+
const stackTrace = captureStackTrace(["JsonwebtokenInstrumentation"]);
|
|
5961
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
5962
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalVerify.apply(this, args), {
|
|
5963
|
+
name: "jsonwebtoken.verify",
|
|
5964
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5965
|
+
submodule: "verify",
|
|
5966
|
+
packageName: "jsonwebtoken",
|
|
5967
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5968
|
+
inputValue,
|
|
5969
|
+
isPreAppStart: false
|
|
5970
|
+
}, (spanInfo) => {
|
|
5971
|
+
return self.handleReplayVerify(verifyConfig, inputValue, spanInfo, stackTrace);
|
|
5972
|
+
});
|
|
5973
|
+
} });
|
|
5974
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5834
5975
|
originalFunctionCall: () => originalVerify.apply(this, args),
|
|
5835
5976
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5836
5977
|
return SpanUtils.createAndExecuteSpan(self.mode, () => originalVerify.apply(this, args), {
|
|
@@ -5870,20 +6011,22 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
5870
6011
|
secretOrPrivateKey: signConfig.secretOrPrivateKey,
|
|
5871
6012
|
options: signConfig.options
|
|
5872
6013
|
};
|
|
5873
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
|
|
6014
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
6015
|
+
const stackTrace = captureStackTrace(["JsonwebtokenInstrumentation"]);
|
|
6016
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
6017
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSign.apply(this, args), {
|
|
6018
|
+
name: "jsonwebtoken.sign",
|
|
6019
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6020
|
+
submodule: "sign",
|
|
6021
|
+
packageName: "jsonwebtoken",
|
|
6022
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
6023
|
+
inputValue,
|
|
6024
|
+
isPreAppStart: false
|
|
6025
|
+
}, (spanInfo) => {
|
|
6026
|
+
return self.handleReplaySign(signConfig, inputValue, spanInfo, stackTrace);
|
|
6027
|
+
});
|
|
6028
|
+
} });
|
|
6029
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5887
6030
|
originalFunctionCall: () => originalSign.apply(this, args),
|
|
5888
6031
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
5889
6032
|
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSign.apply(this, args), {
|
|
@@ -6051,18 +6194,19 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6051
6194
|
throw error;
|
|
6052
6195
|
}
|
|
6053
6196
|
}
|
|
6054
|
-
async handleReplayVerify(verifyConfig, inputValue, spanInfo) {
|
|
6197
|
+
async handleReplayVerify(verifyConfig, inputValue, spanInfo, stackTrace) {
|
|
6055
6198
|
logger.debug(`[JsonwebtokenInstrumentation] Replaying JWT verify`);
|
|
6056
6199
|
const mockData = await findMockResponseAsync({
|
|
6057
6200
|
mockRequestData: {
|
|
6058
6201
|
traceId: spanInfo.traceId,
|
|
6059
6202
|
spanId: spanInfo.spanId,
|
|
6060
|
-
name:
|
|
6203
|
+
name: "jsonwebtoken.verify",
|
|
6061
6204
|
packageName: "jsonwebtoken",
|
|
6062
6205
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
6063
6206
|
submoduleName: "verify",
|
|
6064
6207
|
inputValue,
|
|
6065
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
6208
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6209
|
+
stackTrace
|
|
6066
6210
|
},
|
|
6067
6211
|
tuskDrift: this.tuskDrift
|
|
6068
6212
|
});
|
|
@@ -6097,18 +6241,19 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6097
6241
|
return;
|
|
6098
6242
|
} else return result;
|
|
6099
6243
|
}
|
|
6100
|
-
async handleReplaySign(signConfig, inputValue, spanInfo) {
|
|
6244
|
+
async handleReplaySign(signConfig, inputValue, spanInfo, stackTrace) {
|
|
6101
6245
|
logger.debug(`[JsonwebtokenInstrumentation] Replaying JWT sign`);
|
|
6102
6246
|
const mockData = await findMockResponseAsync({
|
|
6103
6247
|
mockRequestData: {
|
|
6104
6248
|
traceId: spanInfo?.traceId,
|
|
6105
6249
|
spanId: spanInfo?.spanId,
|
|
6106
|
-
name:
|
|
6250
|
+
name: "jsonwebtoken.sign",
|
|
6107
6251
|
packageName: "jsonwebtoken",
|
|
6108
6252
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
6109
6253
|
submoduleName: "sign",
|
|
6110
6254
|
inputValue,
|
|
6111
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
6255
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6256
|
+
stackTrace
|
|
6112
6257
|
},
|
|
6113
6258
|
tuskDrift: this.tuskDrift
|
|
6114
6259
|
});
|
|
@@ -6512,11 +6657,12 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6512
6657
|
this.originalFetch = globalThis.fetch;
|
|
6513
6658
|
const self = this;
|
|
6514
6659
|
globalThis.fetch = function(input, init) {
|
|
6515
|
-
|
|
6660
|
+
const stackTrace = captureStackTrace(["FetchInstrumentation"]);
|
|
6661
|
+
return self._handleFetchRequest(input, init, stackTrace);
|
|
6516
6662
|
};
|
|
6517
6663
|
logger.debug("Global fetch patching complete");
|
|
6518
6664
|
}
|
|
6519
|
-
async _handleFetchRequest(input, init) {
|
|
6665
|
+
async _handleFetchRequest(input, init, stackTrace) {
|
|
6520
6666
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
6521
6667
|
const method = init?.method || "GET";
|
|
6522
6668
|
const headers = init?.headers || {};
|
|
@@ -6546,7 +6692,7 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6546
6692
|
inputValue,
|
|
6547
6693
|
isPreAppStart: false
|
|
6548
6694
|
}, (spanInfo) => {
|
|
6549
|
-
return this._handleReplayFetch(inputValue, spanInfo);
|
|
6695
|
+
return this._handleReplayFetch(inputValue, spanInfo, stackTrace);
|
|
6550
6696
|
});
|
|
6551
6697
|
} });
|
|
6552
6698
|
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
@@ -6627,7 +6773,7 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6627
6773
|
});
|
|
6628
6774
|
});
|
|
6629
6775
|
}
|
|
6630
|
-
async _handleReplayFetch(inputValue, spanInfo) {
|
|
6776
|
+
async _handleReplayFetch(inputValue, spanInfo, stackTrace) {
|
|
6631
6777
|
const mockData = await findMockResponseAsync({
|
|
6632
6778
|
mockRequestData: {
|
|
6633
6779
|
traceId: spanInfo.traceId,
|
|
@@ -6638,7 +6784,8 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6638
6784
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
6639
6785
|
submoduleName: inputValue.method,
|
|
6640
6786
|
inputValue,
|
|
6641
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
6787
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6788
|
+
stackTrace
|
|
6642
6789
|
},
|
|
6643
6790
|
tuskDrift: this.tuskDrift,
|
|
6644
6791
|
inputValueSchemaMerges: {
|
|
@@ -6913,21 +7060,23 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
6913
7060
|
port: this.options?.port
|
|
6914
7061
|
}
|
|
6915
7062
|
};
|
|
6916
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
7063
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
7064
|
+
const stackTrace = captureStackTrace(["IORedisInstrumentation"]);
|
|
7065
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
7066
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSendCommand.apply(this, arguments), {
|
|
7067
|
+
name: `ioredis.${commandName}`,
|
|
7068
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7069
|
+
submodule: commandName,
|
|
7070
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.REDIS,
|
|
7071
|
+
packageName: "ioredis",
|
|
7072
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7073
|
+
inputValue,
|
|
7074
|
+
isPreAppStart: false
|
|
7075
|
+
}, (spanInfo) => {
|
|
7076
|
+
return self._handleReplaySendCommand(spanInfo, cmd, inputValue, commandName, stackTrace);
|
|
7077
|
+
});
|
|
7078
|
+
} });
|
|
7079
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
6931
7080
|
originalFunctionCall: () => originalSendCommand.apply(this, arguments),
|
|
6932
7081
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
6933
7082
|
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSendCommand.apply(this, arguments), {
|
|
@@ -7089,7 +7238,7 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7089
7238
|
});
|
|
7090
7239
|
return promise;
|
|
7091
7240
|
}
|
|
7092
|
-
async _handleReplaySendCommand(spanInfo, cmd, inputValue, commandName) {
|
|
7241
|
+
async _handleReplaySendCommand(spanInfo, cmd, inputValue, commandName, stackTrace) {
|
|
7093
7242
|
logger.debug(`[IORedisInstrumentation] Replaying IORedis command ${cmd.name}`);
|
|
7094
7243
|
const mockData = await findMockResponseAsync({
|
|
7095
7244
|
mockRequestData: {
|
|
@@ -7100,7 +7249,8 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7100
7249
|
packageName: "ioredis",
|
|
7101
7250
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
7102
7251
|
submoduleName: cmd.name,
|
|
7103
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
7252
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7253
|
+
stackTrace
|
|
7104
7254
|
},
|
|
7105
7255
|
tuskDrift: this.tuskDrift
|
|
7106
7256
|
});
|
|
@@ -7549,21 +7699,23 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7549
7699
|
jsonableStringMap
|
|
7550
7700
|
}
|
|
7551
7701
|
};
|
|
7552
|
-
if (self.mode === TuskDriftMode.REPLAY)
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7702
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
7703
|
+
const stackTrace = captureStackTrace(["GrpcInstrumentation"]);
|
|
7704
|
+
return handleReplayMode({ replayModeHandler: () => {
|
|
7705
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
7706
|
+
name: "grpc.client.unary",
|
|
7707
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7708
|
+
submodule: "client",
|
|
7709
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.GRPC,
|
|
7710
|
+
packageName: GRPC_MODULE_NAME,
|
|
7711
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7712
|
+
inputValue,
|
|
7713
|
+
isPreAppStart: false
|
|
7714
|
+
}, (spanInfo) => {
|
|
7715
|
+
return self._handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor, stackTrace);
|
|
7716
|
+
});
|
|
7717
|
+
} });
|
|
7718
|
+
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
7567
7719
|
originalFunctionCall: () => original.apply(this, args),
|
|
7568
7720
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
7569
7721
|
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
@@ -7695,7 +7847,7 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7695
7847
|
isGrpcErrorOutput(result) {
|
|
7696
7848
|
return "error" in result;
|
|
7697
7849
|
}
|
|
7698
|
-
async _handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor) {
|
|
7850
|
+
async _handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor, stackTrace) {
|
|
7699
7851
|
logger.debug(`[GrpcInstrumentation] Replaying gRPC unary request`);
|
|
7700
7852
|
const mockData = await findMockResponseAsync({
|
|
7701
7853
|
mockRequestData: {
|
|
@@ -7706,7 +7858,8 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7706
7858
|
packageName: GRPC_MODULE_NAME,
|
|
7707
7859
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
7708
7860
|
submoduleName: "client",
|
|
7709
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
7861
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7862
|
+
stackTrace
|
|
7710
7863
|
},
|
|
7711
7864
|
tuskDrift: this.tuskDrift
|
|
7712
7865
|
});
|
|
@@ -10336,7 +10489,7 @@ var SpanTransformer = class SpanTransformer {
|
|
|
10336
10489
|
if (transformMetadataString) try {
|
|
10337
10490
|
transformMetadata = JSON.parse(transformMetadataString);
|
|
10338
10491
|
} catch (error) {
|
|
10339
|
-
logger.warn("Failed to parse transform metadata", error);
|
|
10492
|
+
logger.warn("[SpanTransformer] Failed to parse transform metadata", error);
|
|
10340
10493
|
}
|
|
10341
10494
|
const originalDate = OriginalGlobalUtils.getOriginalDate();
|
|
10342
10495
|
return {
|
|
@@ -10722,7 +10875,7 @@ var ProtobufCommunicator = class {
|
|
|
10722
10875
|
requestId,
|
|
10723
10876
|
tags: {},
|
|
10724
10877
|
outboundSpan: cleanSpan,
|
|
10725
|
-
stackTrace:
|
|
10878
|
+
stackTrace: cleanSpan?.stackTrace
|
|
10726
10879
|
});
|
|
10727
10880
|
const sdkMessage = __use_tusk_drift_schemas_core_communication.SDKMessage.create({
|
|
10728
10881
|
type: __use_tusk_drift_schemas_core_communication.MessageType.MOCK_REQUEST,
|
|
@@ -10763,7 +10916,7 @@ var ProtobufCommunicator = class {
|
|
|
10763
10916
|
requestId,
|
|
10764
10917
|
tags: {},
|
|
10765
10918
|
outboundSpan: cleanSpan,
|
|
10766
|
-
stackTrace:
|
|
10919
|
+
stackTrace: cleanSpan?.stackTrace
|
|
10767
10920
|
});
|
|
10768
10921
|
const sdkMessage = __use_tusk_drift_schemas_core_communication.SDKMessage.create({
|
|
10769
10922
|
type: __use_tusk_drift_schemas_core_communication.MessageType.MOCK_REQUEST,
|
|
@@ -11055,7 +11208,7 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11055
11208
|
const packageName = this.getPackageName(modulePath);
|
|
11056
11209
|
if (packageName && TuskDriftInstrumentationModuleNames.includes(packageName)) alreadyRequiredModuleNames.add(packageName);
|
|
11057
11210
|
}
|
|
11058
|
-
} else logger.
|
|
11211
|
+
} else logger.debug("Running in ES Module mode. Cannot detect pre-loaded instrumentation modules.");
|
|
11059
11212
|
return alreadyRequiredModuleNames;
|
|
11060
11213
|
}
|
|
11061
11214
|
static getInstance() {
|
|
@@ -11161,13 +11314,13 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11161
11314
|
}
|
|
11162
11315
|
initialize(initParams) {
|
|
11163
11316
|
initializeGlobalLogger({
|
|
11164
|
-
logLevel: initParams.logLevel || "
|
|
11317
|
+
logLevel: initParams.logLevel || "info",
|
|
11165
11318
|
prefix: "TuskDrift"
|
|
11166
11319
|
});
|
|
11167
11320
|
this.samplingRate = this.config.recording?.sampling_rate ?? 1;
|
|
11168
11321
|
this.initParams = initParams;
|
|
11169
11322
|
if (!this.initParams.env) {
|
|
11170
|
-
const nodeEnv = OriginalGlobalUtils.getOriginalProcessEnvVar("NODE_ENV") || "
|
|
11323
|
+
const nodeEnv = OriginalGlobalUtils.getOriginalProcessEnvVar("NODE_ENV") || "development";
|
|
11171
11324
|
logger.warn(`Environment not provided in initialization parameters. Using '${nodeEnv}' as the environment.`);
|
|
11172
11325
|
this.initParams.env = nodeEnv;
|
|
11173
11326
|
}
|
|
@@ -11245,8 +11398,8 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11245
11398
|
}
|
|
11246
11399
|
this.appReady = true;
|
|
11247
11400
|
logger.debug("Application marked as ready");
|
|
11248
|
-
if (this.mode === TuskDriftMode.REPLAY) logger.
|
|
11249
|
-
else if (this.mode === TuskDriftMode.RECORD) logger.
|
|
11401
|
+
if (this.mode === TuskDriftMode.REPLAY) logger.debug("Replay mode active - ready to serve mocked responses");
|
|
11402
|
+
else if (this.mode === TuskDriftMode.RECORD) logger.debug("Record mode active - capturing inbound requests and responses");
|
|
11250
11403
|
}
|
|
11251
11404
|
async sendInboundSpanForReplay(span) {
|
|
11252
11405
|
try {
|