@use-tusk/drift-node-sdk 0.1.7 → 0.1.9
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 +1 -0
- package/dist/index.cjs +2515 -738
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2513 -737
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -58,6 +58,10 @@ let __use_tusk_drift_schemas_backend_span_export_service = require("@use-tusk/dr
|
|
|
58
58
|
__use_tusk_drift_schemas_backend_span_export_service = __toESM(__use_tusk_drift_schemas_backend_span_export_service);
|
|
59
59
|
let jsonpath = require("jsonpath");
|
|
60
60
|
jsonpath = __toESM(jsonpath);
|
|
61
|
+
let net = require("net");
|
|
62
|
+
net = __toESM(net);
|
|
63
|
+
let stream = require("stream");
|
|
64
|
+
stream = __toESM(stream);
|
|
61
65
|
let __opentelemetry_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
|
62
66
|
__opentelemetry_semantic_conventions = __toESM(__opentelemetry_semantic_conventions);
|
|
63
67
|
let __use_tusk_drift_schemas_backend_span_export_service_client = require("@use-tusk/drift-schemas/backend/span_export_service.client");
|
|
@@ -66,8 +70,6 @@ let __protobuf_ts_twirp_transport = require("@protobuf-ts/twirp-transport");
|
|
|
66
70
|
__protobuf_ts_twirp_transport = __toESM(__protobuf_ts_twirp_transport);
|
|
67
71
|
let __opentelemetry_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
|
|
68
72
|
__opentelemetry_sdk_trace_node = __toESM(__opentelemetry_sdk_trace_node);
|
|
69
|
-
let net = require("net");
|
|
70
|
-
net = __toESM(net);
|
|
71
73
|
let child_process = require("child_process");
|
|
72
74
|
child_process = __toESM(child_process);
|
|
73
75
|
let __use_tusk_drift_schemas_core_communication = require("@use-tusk/drift-schemas/core/communication");
|
|
@@ -227,17 +229,28 @@ function withTuskDrift(nextConfig = {}, options = {}) {
|
|
|
227
229
|
if (webpackOptions.isServer) {
|
|
228
230
|
const originalExternals = webpackConfig.externals;
|
|
229
231
|
const coreExternals = ["require-in-the-middle", "jsonpath"];
|
|
232
|
+
const externalsMapping = {};
|
|
233
|
+
try {
|
|
234
|
+
const sdkPath = require.resolve("@use-tusk/drift-node-sdk");
|
|
235
|
+
const sdkNodeModules = require("path").resolve(sdkPath, "../..", "node_modules");
|
|
236
|
+
for (const pkg of coreExternals) {
|
|
237
|
+
const pkgPath = require("path").join(sdkNodeModules, pkg);
|
|
238
|
+
externalsMapping[pkg] = `commonjs ${pkgPath}`;
|
|
239
|
+
debugLog(debug, `Mapped external ${pkg} -> ${pkgPath}`);
|
|
240
|
+
}
|
|
241
|
+
} catch (e) {
|
|
242
|
+
warn(suppressAllWarnings || false, `Could not resolve SDK path, falling back to regular externals: ${e instanceof Error ? e.message : String(e)}`);
|
|
243
|
+
for (const pkg of coreExternals) externalsMapping[pkg] = `commonjs ${pkg}`;
|
|
244
|
+
}
|
|
230
245
|
if (!originalExternals) {
|
|
231
|
-
webpackConfig.externals =
|
|
232
|
-
debugLog(debug, "Created new externals
|
|
246
|
+
webpackConfig.externals = [externalsMapping];
|
|
247
|
+
debugLog(debug, "Created new externals with SDK paths");
|
|
233
248
|
} else if (Array.isArray(originalExternals)) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
debugLog(debug, `Added ${pkg} to webpack externals`);
|
|
237
|
-
}
|
|
249
|
+
originalExternals.push(externalsMapping);
|
|
250
|
+
debugLog(debug, "Added SDK paths to existing externals array");
|
|
238
251
|
} else {
|
|
239
|
-
webpackConfig.externals = [originalExternals,
|
|
240
|
-
debugLog(debug, "Wrapped existing externals with
|
|
252
|
+
webpackConfig.externals = [originalExternals, externalsMapping];
|
|
253
|
+
debugLog(debug, "Wrapped existing externals with SDK paths");
|
|
241
254
|
}
|
|
242
255
|
}
|
|
243
256
|
if (typeof config.webpack === "function") return config.webpack(webpackConfig, webpackOptions);
|
|
@@ -273,7 +286,7 @@ var TdInstrumentationAbstract = class {
|
|
|
273
286
|
|
|
274
287
|
//#endregion
|
|
275
288
|
//#region package.json
|
|
276
|
-
var version = "0.1.
|
|
289
|
+
var version = "0.1.9";
|
|
277
290
|
|
|
278
291
|
//#endregion
|
|
279
292
|
//#region src/version.ts
|
|
@@ -470,6 +483,20 @@ function loadTuskConfig() {
|
|
|
470
483
|
}
|
|
471
484
|
}
|
|
472
485
|
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/core/utils/runtimeDetectionUtils.ts
|
|
488
|
+
function isNextJsRuntime() {
|
|
489
|
+
return process.env.NEXT_RUNTIME !== void 0 || typeof global.__NEXT_DATA__ !== "undefined";
|
|
490
|
+
}
|
|
491
|
+
function isEsm(moduleExports) {
|
|
492
|
+
if (!moduleExports || typeof moduleExports !== "object") return false;
|
|
493
|
+
try {
|
|
494
|
+
return moduleExports[Symbol.toStringTag] === "Module";
|
|
495
|
+
} catch (error) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
473
500
|
//#endregion
|
|
474
501
|
//#region src/core/utils/logger.ts
|
|
475
502
|
var Logger = class {
|
|
@@ -749,9 +776,11 @@ var TdInstrumentationNodeModule = class {
|
|
|
749
776
|
|
|
750
777
|
//#endregion
|
|
751
778
|
//#region src/core/types.ts
|
|
779
|
+
const TD_INSTRUMENTATION_LIBRARY_NAME = "tusk-drift-sdk";
|
|
752
780
|
const REPLAY_TRACE_ID_CONTEXT_KEY = (0, __opentelemetry_api.createContextKey)("td.replayTraceId");
|
|
753
781
|
const SPAN_KIND_CONTEXT_KEY = (0, __opentelemetry_api.createContextKey)("td.spanKind");
|
|
754
782
|
const IS_PRE_APP_START_CONTEXT_KEY = (0, __opentelemetry_api.createContextKey)("td.isPreAppStart");
|
|
783
|
+
const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, __opentelemetry_api.createContextKey)("td.stopRecordingChildSpans");
|
|
755
784
|
const CALLING_LIBRARY_CONTEXT_KEY = (0, __opentelemetry_api.createContextKey)("td.callingLibrary");
|
|
756
785
|
let TdSpanAttributes = /* @__PURE__ */ function(TdSpanAttributes$1) {
|
|
757
786
|
/**
|
|
@@ -794,6 +823,74 @@ let TdSpanAttributes = /* @__PURE__ */ function(TdSpanAttributes$1) {
|
|
|
794
823
|
return TdSpanAttributes$1;
|
|
795
824
|
}({});
|
|
796
825
|
|
|
826
|
+
//#endregion
|
|
827
|
+
//#region src/core/tracing/TraceBlockingManager.ts
|
|
828
|
+
/**
|
|
829
|
+
* Manages blocked trace IDs to prevent creation and export of spans
|
|
830
|
+
* that belong to traces exceeding size limits.
|
|
831
|
+
*
|
|
832
|
+
* This class uses an in-memory Set for O(1) lookup performance and
|
|
833
|
+
* automatically cleans up old entries to prevent memory leaks.
|
|
834
|
+
*/
|
|
835
|
+
var TraceBlockingManager = class TraceBlockingManager {
|
|
836
|
+
constructor() {
|
|
837
|
+
this.blockedTraceIds = /* @__PURE__ */ new Set();
|
|
838
|
+
this.traceTimestamps = /* @__PURE__ */ new Map();
|
|
839
|
+
this.cleanupIntervalId = null;
|
|
840
|
+
this.DEFAULT_TTL_MS = 600 * 1e3;
|
|
841
|
+
this.CLEANUP_INTERVAL_MS = 120 * 1e3;
|
|
842
|
+
this.startCleanupInterval();
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Get singleton instance
|
|
846
|
+
*/
|
|
847
|
+
static getInstance() {
|
|
848
|
+
if (!TraceBlockingManager.instance) TraceBlockingManager.instance = new TraceBlockingManager();
|
|
849
|
+
return TraceBlockingManager.instance;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Check if a trace ID is blocked
|
|
853
|
+
*/
|
|
854
|
+
isTraceBlocked(traceId) {
|
|
855
|
+
return this.blockedTraceIds.has(traceId);
|
|
856
|
+
}
|
|
857
|
+
/**
|
|
858
|
+
* Block a trace ID and all future spans for this trace
|
|
859
|
+
*/
|
|
860
|
+
blockTrace(traceId) {
|
|
861
|
+
if (!this.blockedTraceIds.has(traceId)) {
|
|
862
|
+
this.blockedTraceIds.add(traceId);
|
|
863
|
+
const originalDate = OriginalGlobalUtils.getOriginalDate();
|
|
864
|
+
this.traceTimestamps.set(traceId, originalDate.getTime());
|
|
865
|
+
logger.debug(`[TraceBlockingManager] Blocked trace: ${traceId}`);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Start periodic cleanup of old blocked trace IDs
|
|
870
|
+
*/
|
|
871
|
+
startCleanupInterval() {
|
|
872
|
+
if (this.cleanupIntervalId) return;
|
|
873
|
+
this.cleanupIntervalId = setInterval(() => {
|
|
874
|
+
this.cleanupOldTraces();
|
|
875
|
+
}, this.CLEANUP_INTERVAL_MS);
|
|
876
|
+
if (this.cleanupIntervalId.unref) this.cleanupIntervalId.unref();
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Clean up trace IDs older than TTL
|
|
880
|
+
*/
|
|
881
|
+
cleanupOldTraces() {
|
|
882
|
+
const now = OriginalGlobalUtils.getOriginalDate().getTime();
|
|
883
|
+
const expiredTraces = [];
|
|
884
|
+
for (const [traceId, timestamp] of this.traceTimestamps.entries()) if (now - timestamp > this.DEFAULT_TTL_MS) expiredTraces.push(traceId);
|
|
885
|
+
for (const traceId of expiredTraces) {
|
|
886
|
+
this.blockedTraceIds.delete(traceId);
|
|
887
|
+
this.traceTimestamps.delete(traceId);
|
|
888
|
+
}
|
|
889
|
+
if (expiredTraces.length > 0) logger.debug(`[TraceBlockingManager] Cleaned up ${expiredTraces.length} expired blocked trace(s)`);
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
TraceBlockingManager.instance = null;
|
|
893
|
+
|
|
797
894
|
//#endregion
|
|
798
895
|
//#region src/core/tracing/SpanUtils.ts
|
|
799
896
|
var SpanUtils = class SpanUtils {
|
|
@@ -804,6 +901,14 @@ var SpanUtils = class SpanUtils {
|
|
|
804
901
|
try {
|
|
805
902
|
const tracer = TuskDriftCore.getInstance().getTracer();
|
|
806
903
|
const parentContext = options.parentContext || __opentelemetry_api.context.active();
|
|
904
|
+
const activeSpan = __opentelemetry_api.trace.getSpan(parentContext);
|
|
905
|
+
if (activeSpan) {
|
|
906
|
+
const parentTraceId = activeSpan.spanContext().traceId;
|
|
907
|
+
if (TraceBlockingManager.getInstance().isTraceBlocked(parentTraceId)) {
|
|
908
|
+
logger.debug(`[SpanUtils] Skipping span creation for '${options.name}' - trace ${parentTraceId} is blocked`);
|
|
909
|
+
return null;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
807
912
|
const span = tracer.startSpan(options.name, {
|
|
808
913
|
kind: options.kind || __opentelemetry_api.SpanKind.CLIENT,
|
|
809
914
|
attributes: options.attributes || {}
|
|
@@ -843,7 +948,14 @@ var SpanUtils = class SpanUtils {
|
|
|
843
948
|
* @returns The result of the function execution
|
|
844
949
|
*/
|
|
845
950
|
static createAndExecuteSpan(mode, originalFunctionCall, options, fn) {
|
|
846
|
-
const
|
|
951
|
+
const spanContext = __opentelemetry_api.trace.getActiveSpan()?.spanContext();
|
|
952
|
+
if (spanContext) {
|
|
953
|
+
if (__opentelemetry_api.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
|
|
954
|
+
logger.debug(`[SpanUtils] Stopping recording of child spans for span ${spanContext.spanId}, packageName: ${options.packageName}, instrumentationName: ${options.instrumentationName}`);
|
|
955
|
+
return originalFunctionCall();
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
|
|
847
959
|
let spanInfo = null;
|
|
848
960
|
try {
|
|
849
961
|
spanInfo = SpanUtils.createSpan({
|
|
@@ -868,6 +980,7 @@ var SpanUtils = class SpanUtils {
|
|
|
868
980
|
}
|
|
869
981
|
if (!spanInfo) if (mode === TuskDriftMode.REPLAY) throw new Error("Error creating span in replay mode");
|
|
870
982
|
else return originalFunctionCall();
|
|
983
|
+
if (stopRecordingChildSpans) spanInfo.context = spanInfo.context.setValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY, true);
|
|
871
984
|
return SpanUtils.withSpan(spanInfo, () => fn(spanInfo));
|
|
872
985
|
}
|
|
873
986
|
/**
|
|
@@ -1123,6 +1236,22 @@ function getDecodedType(contentType) {
|
|
|
1123
1236
|
const mainType = contentTypeString.toLowerCase().split(";")[0].trim();
|
|
1124
1237
|
return CONTENT_TYPE_MAPPING[mainType];
|
|
1125
1238
|
}
|
|
1239
|
+
const STATIC_ASSET_TYPES = new Set([
|
|
1240
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.HTML,
|
|
1241
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.CSS,
|
|
1242
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.JAVASCRIPT,
|
|
1243
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.JPEG,
|
|
1244
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.PNG,
|
|
1245
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.GIF,
|
|
1246
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.WEBP,
|
|
1247
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.SVG,
|
|
1248
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.PDF,
|
|
1249
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.AUDIO,
|
|
1250
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.VIDEO,
|
|
1251
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.BINARY,
|
|
1252
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.ZIP,
|
|
1253
|
+
__use_tusk_drift_schemas_core_json_schema.DecodedType.GZIP
|
|
1254
|
+
]);
|
|
1126
1255
|
|
|
1127
1256
|
//#endregion
|
|
1128
1257
|
//#region src/instrumentation/libraries/http/mocks/TdHttpMockSocket.ts
|
|
@@ -1597,6 +1726,28 @@ async function findMockResponseAsync({ mockRequestData, tuskDrift, inputValueSch
|
|
|
1597
1726
|
return null;
|
|
1598
1727
|
}
|
|
1599
1728
|
}
|
|
1729
|
+
function findMockResponseSync({ mockRequestData, tuskDrift, inputValueSchemaMerges }) {
|
|
1730
|
+
const outboundSpan = convertMockRequestDataToCleanSpanData(mockRequestData, tuskDrift, inputValueSchemaMerges);
|
|
1731
|
+
try {
|
|
1732
|
+
const replayTraceId = SpanUtils.getCurrentReplayTraceId();
|
|
1733
|
+
logger.debug(`Finding ${outboundSpan.traceId} mock for replay trace ID: ${replayTraceId}`);
|
|
1734
|
+
const mockResponse = tuskDrift.requestMockSync({
|
|
1735
|
+
outboundSpan,
|
|
1736
|
+
testId: replayTraceId || ""
|
|
1737
|
+
});
|
|
1738
|
+
if (!mockResponse || !mockResponse.found) {
|
|
1739
|
+
logger.debug(`No matching mock found for ${outboundSpan.traceId} with input value: ${JSON.stringify(outboundSpan.inputValue)}`, replayTraceId);
|
|
1740
|
+
return null;
|
|
1741
|
+
}
|
|
1742
|
+
const responseBody = mockResponse.response?.response?.body;
|
|
1743
|
+
logger.debug(`Found ${outboundSpan.traceId} mock response and timestamp:`, responseBody, { timestamp: mockResponse.response?.timestamp });
|
|
1744
|
+
if (mockResponse.response?.timestamp) DateTracker.updateLatestTimestamp(replayTraceId || "", mockResponse.response.timestamp);
|
|
1745
|
+
return { result: responseBody };
|
|
1746
|
+
} catch (error) {
|
|
1747
|
+
logger.error(`Error finding ${outboundSpan.traceId} mock response:`, error);
|
|
1748
|
+
return null;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1600
1751
|
|
|
1601
1752
|
//#endregion
|
|
1602
1753
|
//#region src/instrumentation/libraries/http/mocks/TdMockClientRequest.ts
|
|
@@ -1727,6 +1878,24 @@ var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter
|
|
|
1727
1878
|
async startPlayback() {
|
|
1728
1879
|
this.playbackStarted = true;
|
|
1729
1880
|
try {
|
|
1881
|
+
if (!this.spanInfo) {
|
|
1882
|
+
logger.debug(`[TdMockClientRequest] Background request detected (no spanInfo), returning 200 OK without mock lookup`);
|
|
1883
|
+
const emptyResponse = {
|
|
1884
|
+
statusCode: 200,
|
|
1885
|
+
statusMessage: "OK",
|
|
1886
|
+
headers: {},
|
|
1887
|
+
httpVersion: "1.1",
|
|
1888
|
+
httpVersionMajor: 1,
|
|
1889
|
+
httpVersionMinor: 1,
|
|
1890
|
+
complete: true,
|
|
1891
|
+
readable: false
|
|
1892
|
+
};
|
|
1893
|
+
this.emit("finish");
|
|
1894
|
+
process.nextTick(() => {
|
|
1895
|
+
this.playResponse(emptyResponse);
|
|
1896
|
+
});
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1730
1899
|
const rawInputValue = {
|
|
1731
1900
|
method: this.method || "GET",
|
|
1732
1901
|
path: this.path,
|
|
@@ -1764,7 +1933,10 @@ var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter
|
|
|
1764
1933
|
headers: { matchImportance: 0 }
|
|
1765
1934
|
}
|
|
1766
1935
|
});
|
|
1767
|
-
if (!mockData)
|
|
1936
|
+
if (!mockData) {
|
|
1937
|
+
logger.warn(`[TdMockClientRequest] No mock data found for ${this.method} ${this.path}`);
|
|
1938
|
+
throw new Error(`[TdMockClientRequest] No matching mock found for ${this.method} ${this.path}`);
|
|
1939
|
+
}
|
|
1768
1940
|
this.emit("finish");
|
|
1769
1941
|
process.nextTick(() => {
|
|
1770
1942
|
this.playResponse(mockData.result);
|
|
@@ -1950,11 +2122,19 @@ function handleRecordMode({ originalFunctionCall, recordModeHandler, spanKind })
|
|
|
1950
2122
|
/**
|
|
1951
2123
|
* Utility function that abstracts the common replay mode pattern of checking if the app is ready
|
|
1952
2124
|
*
|
|
1953
|
-
*
|
|
2125
|
+
* If this is a background request (app is ready and no parent span), calls the backgroundRequestHandler.
|
|
2126
|
+
* Otherwise, calls the replayModeHandler.
|
|
1954
2127
|
* @param replayModeHandler - Function that handles the replay mode logic when app is ready
|
|
1955
|
-
* @
|
|
2128
|
+
* @param noOpRequestHandler - Function to handle no-op requests, called for background requests
|
|
2129
|
+
* @returns The result from either noOpRequestHandler or replayModeHandler
|
|
1956
2130
|
*/
|
|
1957
|
-
function handleReplayMode({ replayModeHandler }) {
|
|
2131
|
+
function handleReplayMode({ replayModeHandler, noOpRequestHandler, isServerRequest }) {
|
|
2132
|
+
const isAppReady = TuskDriftCore.getInstance().isAppReady();
|
|
2133
|
+
const currentSpanInfo = SpanUtils.getCurrentSpanInfo();
|
|
2134
|
+
if (isAppReady && !currentSpanInfo && !isServerRequest) {
|
|
2135
|
+
logger.debug(`[ModeUtils] Handling no-op request`);
|
|
2136
|
+
return noOpRequestHandler();
|
|
2137
|
+
}
|
|
1958
2138
|
return replayModeHandler();
|
|
1959
2139
|
}
|
|
1960
2140
|
|
|
@@ -2009,7 +2189,7 @@ function wrap(target, propertyName, wrapper) {
|
|
|
2009
2189
|
* Helper functions for capturing stack traces in replay mode
|
|
2010
2190
|
*
|
|
2011
2191
|
* TODO: Consider using a structured format for stack frames:
|
|
2012
|
-
*
|
|
2192
|
+
*
|
|
2013
2193
|
* {
|
|
2014
2194
|
* "frames": [
|
|
2015
2195
|
* {
|
|
@@ -2025,7 +2205,7 @@ function wrap(target, propertyName, wrapper) {
|
|
|
2025
2205
|
* It would also allow for more accurate stack trace reconstruction in replay mode.
|
|
2026
2206
|
*/
|
|
2027
2207
|
/**
|
|
2028
|
-
*
|
|
2208
|
+
*
|
|
2029
2209
|
* @param excludeClassNames - Class names to exclude from the stack trace
|
|
2030
2210
|
* @returns The stack trace as a string
|
|
2031
2211
|
*/
|
|
@@ -2438,7 +2618,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2438
2618
|
logger.debug(`[HttpInstrumentation] ${protocolUpper} module already patched, skipping`);
|
|
2439
2619
|
return httpModule;
|
|
2440
2620
|
}
|
|
2441
|
-
if (httpModule
|
|
2621
|
+
if (isEsm(httpModule)) {
|
|
2442
2622
|
if (httpModule.default) {
|
|
2443
2623
|
this._wrap(httpModule.default, "request", this._getRequestPatchFn(protocol));
|
|
2444
2624
|
this._wrap(httpModule.default, "get", this._getGetPatchFn(protocol));
|
|
@@ -2457,67 +2637,76 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2457
2637
|
return httpModule;
|
|
2458
2638
|
}
|
|
2459
2639
|
_createServerSpan({ req, res, originalHandler, protocol }) {
|
|
2640
|
+
if (isNextJsRuntime()) {
|
|
2641
|
+
logger.debug(`[HttpInstrumentation] Skipping recording/replaying for nextJs runtime, handled by nextJs instrumentation`);
|
|
2642
|
+
return originalHandler.call(this);
|
|
2643
|
+
}
|
|
2460
2644
|
const method = req.method || "GET";
|
|
2461
2645
|
const url = req.url || "/";
|
|
2462
2646
|
const target = req.url || "/";
|
|
2463
2647
|
const spanProtocol = this._normalizeProtocol(protocol, "http");
|
|
2464
|
-
if (isTuskDriftIngestionUrl(url) || isTuskDriftIngestionUrl(target))
|
|
2648
|
+
if (isTuskDriftIngestionUrl(url) || isTuskDriftIngestionUrl(target)) {
|
|
2649
|
+
logger.debug(`[HttpInstrumentation] Ignoring drift ingestion endpoints`);
|
|
2650
|
+
return originalHandler.call(this);
|
|
2651
|
+
}
|
|
2465
2652
|
if (this.transformEngine.shouldDropInboundRequest(method, url, req.headers)) {
|
|
2466
2653
|
logger.debug(`[HttpInstrumentation] Dropping inbound request due to transforms: ${method} ${url}`);
|
|
2467
2654
|
return originalHandler.call(this);
|
|
2468
2655
|
}
|
|
2469
|
-
if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
spanInfo,
|
|
2656
|
+
if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
2657
|
+
noOpRequestHandler: () => {
|
|
2658
|
+
throw new Error(`[HttpInstrumentation] Should never call noOpRequestHandler for server requests`);
|
|
2659
|
+
},
|
|
2660
|
+
isServerRequest: true,
|
|
2661
|
+
replayModeHandler: () => {
|
|
2662
|
+
if (req.headers["accept-encoding"]) delete req.headers["accept-encoding"];
|
|
2663
|
+
const fullUrl = `${spanProtocol}://${req.headers.host || "localhost"}${url}`;
|
|
2664
|
+
const inputValue = {
|
|
2665
|
+
method,
|
|
2666
|
+
url: fullUrl,
|
|
2667
|
+
target,
|
|
2668
|
+
headers: req.headers,
|
|
2669
|
+
httpVersion: req.httpVersion,
|
|
2670
|
+
remoteAddress: req.socket?.remoteAddress,
|
|
2671
|
+
remotePort: req.socket?.remotePort
|
|
2672
|
+
};
|
|
2673
|
+
const replayTraceId = this.replayHooks.extractTraceIdFromHeaders(req);
|
|
2674
|
+
if (!replayTraceId) {
|
|
2675
|
+
logger.debug(`[HttpInstrumentation] No trace id found in headers`, req.headers);
|
|
2676
|
+
return originalHandler.call(this);
|
|
2677
|
+
}
|
|
2678
|
+
logger.debug(`[HttpInstrumentation] Setting replay trace id`, replayTraceId);
|
|
2679
|
+
const envVars = this.replayHooks.extractEnvVarsFromHeaders(req);
|
|
2680
|
+
if (envVars) EnvVarTracker.setEnvVars(replayTraceId, envVars);
|
|
2681
|
+
const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
|
|
2682
|
+
if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
|
|
2683
|
+
return __opentelemetry_api.context.with(ctxWithReplayTraceId, () => {
|
|
2684
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
|
|
2685
|
+
name: `${target}`,
|
|
2686
|
+
kind: __opentelemetry_api.SpanKind.SERVER,
|
|
2687
|
+
packageName: spanProtocol,
|
|
2688
|
+
submodule: method,
|
|
2689
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
2690
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
2505
2691
|
inputValue,
|
|
2506
|
-
|
|
2507
|
-
|
|
2692
|
+
inputSchemaMerges: { headers: { matchImportance: 0 } },
|
|
2693
|
+
isPreAppStart: false
|
|
2694
|
+
}, (spanInfo) => {
|
|
2695
|
+
return this._handleInboundRequestInSpan({
|
|
2696
|
+
req,
|
|
2697
|
+
res,
|
|
2698
|
+
originalHandler,
|
|
2699
|
+
spanInfo,
|
|
2700
|
+
inputValue,
|
|
2701
|
+
schemaMerges: { headers: { matchImportance: 0 } },
|
|
2702
|
+
protocol: spanProtocol
|
|
2703
|
+
});
|
|
2508
2704
|
});
|
|
2509
2705
|
});
|
|
2510
|
-
}
|
|
2511
|
-
}
|
|
2706
|
+
}
|
|
2707
|
+
});
|
|
2512
2708
|
else if (this.mode === TuskDriftMode.RECORD) {
|
|
2513
2709
|
if (method.toUpperCase() === "OPTIONS" || !!req.headers["access-control-request-method"]) return originalHandler.call(this);
|
|
2514
|
-
if (!shouldSample({
|
|
2515
|
-
samplingRate: this.tuskDrift.getSamplingRate(),
|
|
2516
|
-
isAppReady: this.tuskDrift.isAppReady()
|
|
2517
|
-
})) {
|
|
2518
|
-
logger.debug(`Skipping server span due to sampling rate`, url, this.tuskDrift.getSamplingRate());
|
|
2519
|
-
return originalHandler.call(this);
|
|
2520
|
-
}
|
|
2521
2710
|
logger.debug(`[HttpInstrumentation] Creating server span for ${method} ${url}`);
|
|
2522
2711
|
return handleRecordMode({
|
|
2523
2712
|
originalFunctionCall: () => originalHandler.call(this),
|
|
@@ -2611,7 +2800,6 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2611
2800
|
outputValue.bodySize = responseBuffer.length;
|
|
2612
2801
|
} catch (error) {
|
|
2613
2802
|
logger.error(`[HttpInstrumentation] Error processing server response body:`, error);
|
|
2614
|
-
outputValue.bodyProcessingError = error instanceof Error ? error.message : String(error);
|
|
2615
2803
|
}
|
|
2616
2804
|
try {
|
|
2617
2805
|
const spanData = {
|
|
@@ -2629,7 +2817,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2629
2817
|
outputSchemaMerges: {
|
|
2630
2818
|
body: {
|
|
2631
2819
|
encoding: __use_tusk_drift_schemas_core_json_schema.EncodingType.BASE64,
|
|
2632
|
-
decodedType: getDecodedType(spanData.outputValue
|
|
2820
|
+
decodedType: getDecodedType(spanData.outputValue?.headers?.["content-type"] || "")
|
|
2633
2821
|
},
|
|
2634
2822
|
headers: { matchImportance: 0 }
|
|
2635
2823
|
},
|
|
@@ -2642,6 +2830,11 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2642
2830
|
message: `HTTP ${statusCode}`
|
|
2643
2831
|
} : { code: __opentelemetry_api.SpanStatusCode.OK };
|
|
2644
2832
|
SpanUtils.setStatus(spanInfo.span, status);
|
|
2833
|
+
const decodedType = getDecodedType(outputValue.headers?.["content-type"] || "");
|
|
2834
|
+
if (decodedType && STATIC_ASSET_TYPES.has(decodedType)) {
|
|
2835
|
+
TraceBlockingManager.getInstance().blockTrace(spanInfo.traceId);
|
|
2836
|
+
logger.debug(`[HttpInstrumentation] Blocking trace ${spanInfo.traceId} because it is an static asset response. Decoded type: ${decodedType}`);
|
|
2837
|
+
}
|
|
2645
2838
|
SpanUtils.endSpan(spanInfo.span);
|
|
2646
2839
|
} catch (error) {
|
|
2647
2840
|
logger.error(`[HttpInstrumentation] Error adding response attributes to span:`, error);
|
|
@@ -2992,37 +3185,48 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
2992
3185
|
const requestProtocol = self._normalizeProtocol(requestOptions.protocol || void 0, protocol);
|
|
2993
3186
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
2994
3187
|
const stackTrace = captureStackTrace(["HttpInstrumentation"]);
|
|
2995
|
-
return handleReplayMode({
|
|
2996
|
-
|
|
2997
|
-
const inputValue = {
|
|
2998
|
-
method,
|
|
2999
|
-
path: requestOptions.path || void 0,
|
|
3000
|
-
headers,
|
|
3001
|
-
protocol: requestProtocol,
|
|
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) => {
|
|
3188
|
+
return handleReplayMode({
|
|
3189
|
+
noOpRequestHandler: () => {
|
|
3016
3190
|
return self.replayHooks.handleOutboundReplayRequest({
|
|
3017
3191
|
method,
|
|
3018
3192
|
requestOptions,
|
|
3019
3193
|
protocol: requestProtocol,
|
|
3020
|
-
args
|
|
3021
|
-
spanInfo,
|
|
3022
|
-
stackTrace
|
|
3194
|
+
args
|
|
3023
3195
|
});
|
|
3024
|
-
}
|
|
3025
|
-
|
|
3196
|
+
},
|
|
3197
|
+
isServerRequest: false,
|
|
3198
|
+
replayModeHandler: () => {
|
|
3199
|
+
const headers = normalizeHeaders(requestOptions.headers || {});
|
|
3200
|
+
const inputValue = {
|
|
3201
|
+
method,
|
|
3202
|
+
path: requestOptions.path || void 0,
|
|
3203
|
+
headers,
|
|
3204
|
+
protocol: requestProtocol,
|
|
3205
|
+
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
3206
|
+
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
3207
|
+
timeout: requestOptions.timeout || void 0
|
|
3208
|
+
};
|
|
3209
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
|
|
3210
|
+
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
3211
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3212
|
+
packageName: requestProtocol,
|
|
3213
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
3214
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3215
|
+
submodule: method,
|
|
3216
|
+
inputValue,
|
|
3217
|
+
isPreAppStart: false
|
|
3218
|
+
}, (spanInfo) => {
|
|
3219
|
+
return self.replayHooks.handleOutboundReplayRequest({
|
|
3220
|
+
method,
|
|
3221
|
+
requestOptions,
|
|
3222
|
+
protocol: requestProtocol,
|
|
3223
|
+
args,
|
|
3224
|
+
spanInfo,
|
|
3225
|
+
stackTrace
|
|
3226
|
+
});
|
|
3227
|
+
});
|
|
3228
|
+
}
|
|
3229
|
+
});
|
|
3026
3230
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3027
3231
|
originalFunctionCall: () => originalRequest.apply(this, args),
|
|
3028
3232
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -3074,36 +3278,47 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
3074
3278
|
} else requestOptions = args[0] || {};
|
|
3075
3279
|
const method = "GET";
|
|
3076
3280
|
const requestProtocol = self._normalizeProtocol(requestOptions.protocol || void 0, protocol);
|
|
3077
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
3078
|
-
|
|
3079
|
-
const inputValue = {
|
|
3080
|
-
method,
|
|
3081
|
-
path: requestOptions.path || void 0,
|
|
3082
|
-
headers,
|
|
3083
|
-
protocol: requestProtocol,
|
|
3084
|
-
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
3085
|
-
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
3086
|
-
timeout: requestOptions.timeout || void 0
|
|
3087
|
-
};
|
|
3088
|
-
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
|
|
3089
|
-
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
3090
|
-
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3091
|
-
packageName: requestProtocol,
|
|
3092
|
-
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
3093
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3094
|
-
submodule: method,
|
|
3095
|
-
inputValue,
|
|
3096
|
-
isPreAppStart: false
|
|
3097
|
-
}, (spanInfo) => {
|
|
3281
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
3282
|
+
noOpRequestHandler: () => {
|
|
3098
3283
|
return self.replayHooks.handleOutboundReplayRequest({
|
|
3099
3284
|
method,
|
|
3100
3285
|
requestOptions,
|
|
3101
3286
|
protocol: requestProtocol,
|
|
3102
|
-
args
|
|
3103
|
-
spanInfo
|
|
3287
|
+
args
|
|
3104
3288
|
});
|
|
3105
|
-
}
|
|
3106
|
-
|
|
3289
|
+
},
|
|
3290
|
+
isServerRequest: false,
|
|
3291
|
+
replayModeHandler: () => {
|
|
3292
|
+
const headers = normalizeHeaders(requestOptions.headers || {});
|
|
3293
|
+
const inputValue = {
|
|
3294
|
+
method,
|
|
3295
|
+
path: requestOptions.path || void 0,
|
|
3296
|
+
headers,
|
|
3297
|
+
protocol: requestProtocol,
|
|
3298
|
+
hostname: requestOptions.hostname || requestOptions.host || void 0,
|
|
3299
|
+
port: requestOptions.port ? Number(requestOptions.port) : void 0,
|
|
3300
|
+
timeout: requestOptions.timeout || void 0
|
|
3301
|
+
};
|
|
3302
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
|
|
3303
|
+
name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
|
|
3304
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3305
|
+
packageName: requestProtocol,
|
|
3306
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
3307
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3308
|
+
submodule: method,
|
|
3309
|
+
inputValue,
|
|
3310
|
+
isPreAppStart: false
|
|
3311
|
+
}, (spanInfo) => {
|
|
3312
|
+
return self.replayHooks.handleOutboundReplayRequest({
|
|
3313
|
+
method,
|
|
3314
|
+
requestOptions,
|
|
3315
|
+
protocol: requestProtocol,
|
|
3316
|
+
args,
|
|
3317
|
+
spanInfo
|
|
3318
|
+
});
|
|
3319
|
+
});
|
|
3320
|
+
}
|
|
3321
|
+
});
|
|
3107
3322
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3108
3323
|
originalFunctionCall: () => originalGet.apply(this, args),
|
|
3109
3324
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -3143,6 +3358,12 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
|
|
|
3143
3358
|
return (originalEmit) => {
|
|
3144
3359
|
return function(eventName, ...args) {
|
|
3145
3360
|
if (eventName === "request") {
|
|
3361
|
+
if (self.mode === TuskDriftMode.RECORD) {
|
|
3362
|
+
if (!shouldSample({
|
|
3363
|
+
samplingRate: self.tuskDrift.getSamplingRate(),
|
|
3364
|
+
isAppReady: self.tuskDrift.isAppReady()
|
|
3365
|
+
})) return originalEmit.apply(this, [eventName, ...args]);
|
|
3366
|
+
}
|
|
3146
3367
|
const req = args[0];
|
|
3147
3368
|
const res = args[1];
|
|
3148
3369
|
return self._createServerSpan({
|
|
@@ -3493,7 +3714,8 @@ var TdPgClientMock = class extends events.EventEmitter {
|
|
|
3493
3714
|
clientType: "client"
|
|
3494
3715
|
};
|
|
3495
3716
|
const inputValue = createMockInputValue(rawInputValue);
|
|
3496
|
-
return this.pgInstrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
3717
|
+
if (this.spanInfo) return this.pgInstrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
3718
|
+
else return this.pgInstrumentation.handleNoOpReplayQuery(queryConfig);
|
|
3497
3719
|
}
|
|
3498
3720
|
release() {
|
|
3499
3721
|
this.emit("end");
|
|
@@ -3598,22 +3820,28 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3598
3820
|
};
|
|
3599
3821
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
3600
3822
|
const stackTrace = captureStackTrace(["PgInstrumentation"]);
|
|
3601
|
-
return handleReplayMode({
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3823
|
+
return handleReplayMode({
|
|
3824
|
+
noOpRequestHandler: () => {
|
|
3825
|
+
return self.handleNoOpReplayQuery(queryConfig);
|
|
3826
|
+
},
|
|
3827
|
+
isServerRequest: false,
|
|
3828
|
+
replayModeHandler: () => {
|
|
3829
|
+
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
3830
|
+
const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
|
|
3831
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
|
|
3832
|
+
name: spanName,
|
|
3833
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3834
|
+
submodule: "query",
|
|
3835
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
3836
|
+
packageName,
|
|
3837
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3838
|
+
inputValue,
|
|
3839
|
+
isPreAppStart: false
|
|
3840
|
+
}, (spanInfo) => {
|
|
3841
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, stackTrace);
|
|
3842
|
+
});
|
|
3843
|
+
}
|
|
3844
|
+
});
|
|
3617
3845
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3618
3846
|
originalFunctionCall: () => originalQuery.apply(this, args),
|
|
3619
3847
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -3643,20 +3871,29 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3643
3871
|
return (originalConnect) => {
|
|
3644
3872
|
return function connect(callback) {
|
|
3645
3873
|
const inputValue = { clientType };
|
|
3646
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3874
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
3875
|
+
noOpRequestHandler: () => {
|
|
3876
|
+
if (callback) {
|
|
3877
|
+
process.nextTick(() => callback(null));
|
|
3878
|
+
return;
|
|
3879
|
+
} else return Promise.resolve();
|
|
3880
|
+
},
|
|
3881
|
+
isServerRequest: false,
|
|
3882
|
+
replayModeHandler: () => {
|
|
3883
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
|
|
3884
|
+
name: `pg.connect`,
|
|
3885
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
3886
|
+
submodule: "connect",
|
|
3887
|
+
packageName: "pg",
|
|
3888
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
3889
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
3890
|
+
inputValue,
|
|
3891
|
+
isPreAppStart: false
|
|
3892
|
+
}, (spanInfo) => {
|
|
3893
|
+
return self._handleReplayConnect(callback);
|
|
3894
|
+
});
|
|
3895
|
+
}
|
|
3896
|
+
});
|
|
3660
3897
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3661
3898
|
originalFunctionCall: () => originalConnect.apply(this, [callback]),
|
|
3662
3899
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -3760,7 +3997,17 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3760
3997
|
throw error;
|
|
3761
3998
|
});
|
|
3762
3999
|
}
|
|
3763
|
-
async
|
|
4000
|
+
async handleNoOpReplayQuery(queryConfig) {
|
|
4001
|
+
const emptyResult = {
|
|
4002
|
+
rows: [],
|
|
4003
|
+
rowCount: 0
|
|
4004
|
+
};
|
|
4005
|
+
if (queryConfig.callback) {
|
|
4006
|
+
process.nextTick(() => queryConfig.callback(null, emptyResult));
|
|
4007
|
+
return;
|
|
4008
|
+
} else return Promise.resolve(emptyResult);
|
|
4009
|
+
}
|
|
4010
|
+
async handleReplayQuery(queryConfig, inputValue, spanInfo, stackTrace) {
|
|
3764
4011
|
logger.debug(`[PgInstrumentation] Replaying PG query`);
|
|
3765
4012
|
const packageName = inputValue.clientType === "pool" ? "pg-pool" : "pg";
|
|
3766
4013
|
const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
|
|
@@ -3781,10 +4028,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3781
4028
|
if (!mockData) {
|
|
3782
4029
|
const queryText = queryConfig.text || inputValue.text || "UNKNOWN_QUERY";
|
|
3783
4030
|
logger.warn(`[PgInstrumentation] No mock data found for PG query: ${queryText}`);
|
|
3784
|
-
|
|
3785
|
-
process.nextTick(() => queryConfig.callback(/* @__PURE__ */ new Error("No mock data found")));
|
|
3786
|
-
return;
|
|
3787
|
-
} else return Promise.reject(/* @__PURE__ */ new Error("No mock data found"));
|
|
4031
|
+
throw new Error(`[PgInstrumentation] No mock data found for PG query: ${queryText}`);
|
|
3788
4032
|
}
|
|
3789
4033
|
const processedResult = this.convertPostgresTypes(mockData.result);
|
|
3790
4034
|
if (queryConfig.callback) {
|
|
@@ -3919,20 +4163,30 @@ var PgInstrumentation = class extends TdInstrumentationBase {
|
|
|
3919
4163
|
return (originalConnect) => {
|
|
3920
4164
|
return function connect(callback) {
|
|
3921
4165
|
const inputValue = { clientType: "pool" };
|
|
3922
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
4166
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
4167
|
+
noOpRequestHandler: () => {
|
|
4168
|
+
const mockClient = new TdPgClientMock(self);
|
|
4169
|
+
if (callback) {
|
|
4170
|
+
process.nextTick(() => callback(null, mockClient, () => {}));
|
|
4171
|
+
return;
|
|
4172
|
+
} else return Promise.resolve(mockClient);
|
|
4173
|
+
},
|
|
4174
|
+
isServerRequest: false,
|
|
4175
|
+
replayModeHandler: () => {
|
|
4176
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
|
|
4177
|
+
name: `pg-pool.connect`,
|
|
4178
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4179
|
+
submodule: "connect",
|
|
4180
|
+
packageName: "pg-pool",
|
|
4181
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4182
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
4183
|
+
inputValue,
|
|
4184
|
+
isPreAppStart: false
|
|
4185
|
+
}, (spanInfo) => {
|
|
4186
|
+
return self._handleReplayPoolConnect(spanInfo, callback);
|
|
4187
|
+
});
|
|
4188
|
+
}
|
|
4189
|
+
});
|
|
3936
4190
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
3937
4191
|
originalFunctionCall: () => originalConnect.apply(this, [callback]),
|
|
3938
4192
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -4055,7 +4309,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4055
4309
|
return postgresModule;
|
|
4056
4310
|
}
|
|
4057
4311
|
const self = this;
|
|
4058
|
-
if (postgresModule
|
|
4312
|
+
if (isEsm(postgresModule)) {
|
|
4059
4313
|
logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
|
|
4060
4314
|
this._wrap(postgresModule, "default", (originalFunction) => {
|
|
4061
4315
|
return function(...args) {
|
|
@@ -4095,23 +4349,35 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4095
4349
|
connectionString: connectionString ? this._sanitizeConnectionString(connectionString) : void 0,
|
|
4096
4350
|
options: options ? this._sanitizeConnectionOptions(options) : void 0
|
|
4097
4351
|
};
|
|
4098
|
-
if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4352
|
+
if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
4353
|
+
noOpRequestHandler: () => {
|
|
4354
|
+
try {
|
|
4355
|
+
const sqlInstance = originalFunction(...args);
|
|
4356
|
+
return this._wrapSqlInstance(sqlInstance);
|
|
4357
|
+
} catch (error) {
|
|
4358
|
+
logger.debug(`[PostgresInstrumentation] Postgres connection error in replay: ${error.message}`);
|
|
4359
|
+
throw error;
|
|
4360
|
+
}
|
|
4361
|
+
},
|
|
4362
|
+
isServerRequest: false,
|
|
4363
|
+
replayModeHandler: () => {
|
|
4364
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => {
|
|
4365
|
+
const sqlInstance = originalFunction(...args);
|
|
4366
|
+
return this._wrapSqlInstance(sqlInstance);
|
|
4367
|
+
}, {
|
|
4368
|
+
name: "postgres.connect",
|
|
4369
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4370
|
+
submodule: "connect",
|
|
4371
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4372
|
+
packageName: "postgres",
|
|
4373
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4374
|
+
inputValue,
|
|
4375
|
+
isPreAppStart: false
|
|
4376
|
+
}, (spanInfo) => {
|
|
4377
|
+
return this._handleReplayConnect(originalFunction, args);
|
|
4378
|
+
});
|
|
4379
|
+
}
|
|
4380
|
+
});
|
|
4115
4381
|
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4116
4382
|
originalFunctionCall: () => {
|
|
4117
4383
|
const sqlInstance = originalFunction(...args);
|
|
@@ -4171,20 +4437,13 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4171
4437
|
}
|
|
4172
4438
|
return wrappedInstance;
|
|
4173
4439
|
}
|
|
4174
|
-
_handleReplayConnect(
|
|
4440
|
+
_handleReplayConnect(originalFunction, args) {
|
|
4175
4441
|
logger.debug(`[PostgresInstrumentation] Replaying Postgres connection`);
|
|
4176
4442
|
try {
|
|
4177
4443
|
const sqlInstance = originalFunction(...args);
|
|
4178
|
-
|
|
4179
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
|
|
4180
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
4181
|
-
return wrappedInstance;
|
|
4444
|
+
return this._wrapSqlInstance(sqlInstance);
|
|
4182
4445
|
} catch (error) {
|
|
4183
4446
|
logger.debug(`[PostgresInstrumentation] Postgres connection error in replay: ${error.message}`);
|
|
4184
|
-
SpanUtils.endSpan(spanInfo.span, {
|
|
4185
|
-
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
4186
|
-
message: error.message
|
|
4187
|
-
});
|
|
4188
4447
|
throw error;
|
|
4189
4448
|
}
|
|
4190
4449
|
}
|
|
@@ -4244,26 +4503,30 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4244
4503
|
};
|
|
4245
4504
|
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4246
4505
|
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4247
|
-
return handleReplayMode({
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
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",
|
|
4506
|
+
return handleReplayMode({
|
|
4507
|
+
noOpRequestHandler: () => {},
|
|
4508
|
+
isServerRequest: false,
|
|
4509
|
+
replayModeHandler: () => {
|
|
4510
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => originalSql.call(this, strings, ...values), {
|
|
4262
4511
|
name: "postgres.query",
|
|
4263
|
-
|
|
4512
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4513
|
+
submodule: "query",
|
|
4514
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4515
|
+
packageName: "postgres",
|
|
4516
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4517
|
+
inputValue,
|
|
4518
|
+
isPreAppStart: false
|
|
4519
|
+
}, (spanInfo) => {
|
|
4520
|
+
return this.handleReplaySqlQuery({
|
|
4521
|
+
inputValue,
|
|
4522
|
+
spanInfo,
|
|
4523
|
+
submodule: "query",
|
|
4524
|
+
name: "postgres.query",
|
|
4525
|
+
stackTrace
|
|
4526
|
+
});
|
|
4264
4527
|
});
|
|
4265
|
-
}
|
|
4266
|
-
}
|
|
4528
|
+
}
|
|
4529
|
+
});
|
|
4267
4530
|
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4268
4531
|
originalFunctionCall: () => originalSql.call(this, strings, ...values),
|
|
4269
4532
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -4297,28 +4560,34 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4297
4560
|
};
|
|
4298
4561
|
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4299
4562
|
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4300
|
-
return handleReplayMode({
|
|
4301
|
-
|
|
4302
|
-
return
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4309
|
-
inputValue,
|
|
4310
|
-
isPreAppStart: false
|
|
4311
|
-
}, (spanInfo) => {
|
|
4312
|
-
return this.handleReplayUnsafeQuery({
|
|
4313
|
-
inputValue,
|
|
4314
|
-
spanInfo,
|
|
4315
|
-
submodule: "unsafe",
|
|
4563
|
+
return handleReplayMode({
|
|
4564
|
+
noOpRequestHandler: () => {
|
|
4565
|
+
return Promise.resolve(void 0);
|
|
4566
|
+
},
|
|
4567
|
+
isServerRequest: false,
|
|
4568
|
+
replayModeHandler: () => {
|
|
4569
|
+
return this._createPendingQueryWrapper(() => {
|
|
4570
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => executeUnsafe(), {
|
|
4316
4571
|
name: "postgres.unsafe",
|
|
4317
|
-
|
|
4572
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4573
|
+
submodule: "unsafe",
|
|
4574
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4575
|
+
packageName: "postgres",
|
|
4576
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4577
|
+
inputValue,
|
|
4578
|
+
isPreAppStart: false
|
|
4579
|
+
}, (spanInfo) => {
|
|
4580
|
+
return this.handleReplayUnsafeQuery({
|
|
4581
|
+
inputValue,
|
|
4582
|
+
spanInfo,
|
|
4583
|
+
submodule: "unsafe",
|
|
4584
|
+
name: "postgres.unsafe",
|
|
4585
|
+
stackTrace
|
|
4586
|
+
});
|
|
4318
4587
|
});
|
|
4319
4588
|
});
|
|
4320
|
-
}
|
|
4321
|
-
}
|
|
4589
|
+
}
|
|
4590
|
+
});
|
|
4322
4591
|
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4323
4592
|
originalFunctionCall: executeUnsafe,
|
|
4324
4593
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -4351,20 +4620,24 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4351
4620
|
};
|
|
4352
4621
|
if (this.mode === TuskDriftMode.REPLAY) {
|
|
4353
4622
|
const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
|
|
4354
|
-
return handleReplayMode({
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4623
|
+
return handleReplayMode({
|
|
4624
|
+
noOpRequestHandler: () => {},
|
|
4625
|
+
isServerRequest: false,
|
|
4626
|
+
replayModeHandler: () => {
|
|
4627
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => executeBegin(), {
|
|
4628
|
+
name: "postgres.begin",
|
|
4629
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
4630
|
+
submodule: "transaction",
|
|
4631
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.PG,
|
|
4632
|
+
packageName: "postgres",
|
|
4633
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
4634
|
+
inputValue,
|
|
4635
|
+
isPreAppStart: false
|
|
4636
|
+
}, (spanInfo) => {
|
|
4637
|
+
return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
|
|
4638
|
+
});
|
|
4639
|
+
}
|
|
4640
|
+
});
|
|
4368
4641
|
} else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
4369
4642
|
originalFunctionCall: executeBegin,
|
|
4370
4643
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -4480,28 +4753,13 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4480
4753
|
});
|
|
4481
4754
|
if (!mockData) {
|
|
4482
4755
|
logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
|
|
4483
|
-
|
|
4484
|
-
return;
|
|
4756
|
+
throw new Error(`[PostgresInstrumentation] No matching mock found for transaction BEGIN`);
|
|
4485
4757
|
}
|
|
4486
4758
|
logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
|
|
4487
4759
|
const transactionResult = mockData.result;
|
|
4488
|
-
if (transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed")
|
|
4489
|
-
|
|
4490
|
-
status: "committed",
|
|
4491
|
-
result: transactionResult.result
|
|
4492
|
-
} });
|
|
4493
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
4494
|
-
return transactionResult.result;
|
|
4495
|
-
} else {
|
|
4760
|
+
if (transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed") return transactionResult.result;
|
|
4761
|
+
else {
|
|
4496
4762
|
const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
|
|
4497
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
|
|
4498
|
-
status: "rolled_back",
|
|
4499
|
-
error: errorMessage
|
|
4500
|
-
} });
|
|
4501
|
-
SpanUtils.endSpan(spanInfo.span, {
|
|
4502
|
-
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
4503
|
-
message: errorMessage
|
|
4504
|
-
});
|
|
4505
4763
|
throw new Error(errorMessage);
|
|
4506
4764
|
}
|
|
4507
4765
|
}
|
|
@@ -4548,7 +4806,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4548
4806
|
if (!mockData) {
|
|
4549
4807
|
const queryText = inputValue.query || "UNKNOWN_QUERY";
|
|
4550
4808
|
logger.warn(`[PostgresInstrumentation] No mock data found for Postgres sql query: ${queryText}`);
|
|
4551
|
-
|
|
4809
|
+
throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres sql query: ${queryText}`);
|
|
4552
4810
|
}
|
|
4553
4811
|
logger.debug(`[PostgresInstrumentation] Found mock data for Postgres sql query: ${JSON.stringify(mockData)}`);
|
|
4554
4812
|
const processedResult = this.convertPostgresTypes(mockData.result);
|
|
@@ -4579,7 +4837,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4579
4837
|
if (!mockData) {
|
|
4580
4838
|
const queryText = inputValue.query || "UNKNOWN_QUERY";
|
|
4581
4839
|
logger.warn(`[PostgresInstrumentation] No mock data found for Postgres unsafe query: ${queryText}`);
|
|
4582
|
-
|
|
4840
|
+
throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres unsafe query: ${queryText}`);
|
|
4583
4841
|
}
|
|
4584
4842
|
logger.debug(`[PostgresInstrumentation] Found mock data for Postgres unsafe query: ${JSON.stringify(mockData)}`);
|
|
4585
4843
|
const processedResult = this.convertPostgresTypes(mockData.result);
|
|
@@ -4668,7 +4926,7 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
|
|
|
4668
4926
|
* Extends EventEmitter to properly handle all connection methods and events
|
|
4669
4927
|
*/
|
|
4670
4928
|
var TdMysql2ConnectionMock = class extends events.EventEmitter {
|
|
4671
|
-
constructor(mysql2Instrumentation,
|
|
4929
|
+
constructor(mysql2Instrumentation, clientType = "poolConnection", spanInfo) {
|
|
4672
4930
|
super();
|
|
4673
4931
|
this.threadId = null;
|
|
4674
4932
|
this.config = {
|
|
@@ -4704,7 +4962,8 @@ var TdMysql2ConnectionMock = class extends events.EventEmitter {
|
|
|
4704
4962
|
clientType: this.clientType
|
|
4705
4963
|
};
|
|
4706
4964
|
const inputValue = createMockInputValue(rawInputValue);
|
|
4707
|
-
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4965
|
+
if (this.spanInfo) return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4966
|
+
else return this.mysql2Instrumentation.handleNoOpReplayQuery(queryConfig);
|
|
4708
4967
|
}
|
|
4709
4968
|
execute(...args) {
|
|
4710
4969
|
logger.debug(`[TdMysql2ConnectionMock] Mock connection execute intercepted in REPLAY mode`);
|
|
@@ -4728,7 +4987,8 @@ var TdMysql2ConnectionMock = class extends events.EventEmitter {
|
|
|
4728
4987
|
clientType: this.clientType
|
|
4729
4988
|
};
|
|
4730
4989
|
const inputValue = createMockInputValue(rawInputValue);
|
|
4731
|
-
return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4990
|
+
if (this.spanInfo) return this.mysql2Instrumentation.handleReplayQuery(queryConfig, inputValue, this.spanInfo, stackTrace);
|
|
4991
|
+
else return this.mysql2Instrumentation.handleNoOpReplayQuery(queryConfig);
|
|
4732
4992
|
}
|
|
4733
4993
|
release() {
|
|
4734
4994
|
this.emit("end");
|
|
@@ -4828,6 +5088,27 @@ var TdMysql2QueryMock = class {
|
|
|
4828
5088
|
return this._handleQuery(queryConfig, inputValue, spanInfo, spanName, submoduleName, stackTrace);
|
|
4829
5089
|
}
|
|
4830
5090
|
/**
|
|
5091
|
+
* Handle background query requests (outside of trace context)
|
|
5092
|
+
* Returns an EventEmitter that immediately completes with empty results
|
|
5093
|
+
*/
|
|
5094
|
+
handleNoOpReplayQuery(queryConfig) {
|
|
5095
|
+
logger.debug(`[Mysql2Instrumentation] Background query detected, returning empty result`);
|
|
5096
|
+
const emitter = new events.EventEmitter();
|
|
5097
|
+
emitter.then = function(onResolve, onReject) {
|
|
5098
|
+
return new Promise((resolve) => {
|
|
5099
|
+
emitter.once("end", () => {
|
|
5100
|
+
resolve([[], []]);
|
|
5101
|
+
});
|
|
5102
|
+
}).then(onResolve, onReject);
|
|
5103
|
+
};
|
|
5104
|
+
process.nextTick(() => {
|
|
5105
|
+
const callback = queryConfig.callback;
|
|
5106
|
+
if (callback) callback(null, [], []);
|
|
5107
|
+
emitter.emit("end");
|
|
5108
|
+
});
|
|
5109
|
+
return emitter;
|
|
5110
|
+
}
|
|
5111
|
+
/**
|
|
4831
5112
|
* Handle query - always returns an EventEmitter (like mysql2 does)
|
|
4832
5113
|
* This handles both callback and streaming modes
|
|
4833
5114
|
* The EventEmitter is also thenable (has a .then() method) to support await/Promise usage
|
|
@@ -4852,12 +5133,7 @@ var TdMysql2QueryMock = class {
|
|
|
4852
5133
|
if (!mockData) {
|
|
4853
5134
|
const sql = queryConfig.sql || inputValue.sql || "UNKNOWN_QUERY";
|
|
4854
5135
|
logger.warn(`[Mysql2Instrumentation] No mock data found for MySQL2 query: ${sql}`);
|
|
4855
|
-
|
|
4856
|
-
process.nextTick(() => {
|
|
4857
|
-
if (queryConfig.callback) queryConfig.callback(error);
|
|
4858
|
-
emitter.emit("error", error);
|
|
4859
|
-
});
|
|
4860
|
-
return;
|
|
5136
|
+
throw new Error(`[Mysql2Instrumentation] No matching mock found for query: ${sql}`);
|
|
4861
5137
|
}
|
|
4862
5138
|
const processedResult = this._convertMysql2Types(mockData.result);
|
|
4863
5139
|
storedRows = processedResult.rows;
|
|
@@ -5182,21 +5458,27 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5182
5458
|
};
|
|
5183
5459
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5184
5460
|
const stackTrace = captureStackTrace(["Mysql2Instrumentation"]);
|
|
5185
|
-
return handleReplayMode({
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5461
|
+
return handleReplayMode({
|
|
5462
|
+
noOpRequestHandler: () => {
|
|
5463
|
+
return self.queryMock.handleNoOpReplayQuery(queryConfig);
|
|
5464
|
+
},
|
|
5465
|
+
isServerRequest: false,
|
|
5466
|
+
replayModeHandler: () => {
|
|
5467
|
+
const spanName = `mysql2.${clientType}.query`;
|
|
5468
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
|
|
5469
|
+
name: spanName,
|
|
5470
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5471
|
+
submodule: "query",
|
|
5472
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5473
|
+
packageName: "mysql2",
|
|
5474
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5475
|
+
inputValue,
|
|
5476
|
+
isPreAppStart: false
|
|
5477
|
+
}, (spanInfo) => {
|
|
5478
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, "query", stackTrace);
|
|
5479
|
+
});
|
|
5480
|
+
}
|
|
5481
|
+
});
|
|
5200
5482
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5201
5483
|
originalFunctionCall: () => originalQuery.apply(this, args),
|
|
5202
5484
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -5241,21 +5523,27 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5241
5523
|
};
|
|
5242
5524
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5243
5525
|
const stackTrace = captureStackTrace(["Mysql2Instrumentation"]);
|
|
5244
|
-
return handleReplayMode({
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5526
|
+
return handleReplayMode({
|
|
5527
|
+
noOpRequestHandler: () => {
|
|
5528
|
+
return self.queryMock.handleNoOpReplayQuery(queryConfig);
|
|
5529
|
+
},
|
|
5530
|
+
isServerRequest: false,
|
|
5531
|
+
replayModeHandler: () => {
|
|
5532
|
+
const spanName = `mysql2.${clientType}.execute`;
|
|
5533
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalExecute.apply(this, args), {
|
|
5534
|
+
name: spanName,
|
|
5535
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5536
|
+
submodule: "execute",
|
|
5537
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5538
|
+
packageName: "mysql2",
|
|
5539
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5540
|
+
inputValue,
|
|
5541
|
+
isPreAppStart: false
|
|
5542
|
+
}, (spanInfo) => {
|
|
5543
|
+
return self.handleReplayQuery(queryConfig, inputValue, spanInfo, "execute", stackTrace);
|
|
5544
|
+
});
|
|
5545
|
+
}
|
|
5546
|
+
});
|
|
5259
5547
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5260
5548
|
originalFunctionCall: () => originalExecute.apply(this, args),
|
|
5261
5549
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -5284,20 +5572,26 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5284
5572
|
return (originalGetConnection) => {
|
|
5285
5573
|
return function getConnection(callback) {
|
|
5286
5574
|
const inputValue = { clientType: "pool" };
|
|
5287
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5575
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5576
|
+
noOpRequestHandler: () => {
|
|
5577
|
+
return self.handleNoOpReplayGetConnection(callback);
|
|
5578
|
+
},
|
|
5579
|
+
isServerRequest: false,
|
|
5580
|
+
replayModeHandler: () => {
|
|
5581
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGetConnection.apply(this, [callback]), {
|
|
5582
|
+
name: `mysql2.pool.getConnection`,
|
|
5583
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5584
|
+
submodule: "getConnection",
|
|
5585
|
+
packageName: "mysql2",
|
|
5586
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5587
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5588
|
+
inputValue,
|
|
5589
|
+
isPreAppStart: false
|
|
5590
|
+
}, (spanInfo) => {
|
|
5591
|
+
return self._handleReplayPoolGetConnection(spanInfo, callback);
|
|
5592
|
+
});
|
|
5593
|
+
}
|
|
5594
|
+
});
|
|
5301
5595
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5302
5596
|
originalFunctionCall: () => originalGetConnection.apply(this, [callback]),
|
|
5303
5597
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -5325,24 +5619,34 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5325
5619
|
return (originalConnect) => {
|
|
5326
5620
|
return function connect(callback) {
|
|
5327
5621
|
const inputValue = { clientType };
|
|
5328
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5329
|
-
|
|
5330
|
-
name: `mysql2.${clientType}.connect`,
|
|
5331
|
-
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5332
|
-
submodule: "connect",
|
|
5333
|
-
packageName: "mysql2",
|
|
5334
|
-
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5335
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5336
|
-
inputValue,
|
|
5337
|
-
isPreAppStart: false
|
|
5338
|
-
}, (spanInfo) => {
|
|
5622
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5623
|
+
noOpRequestHandler: () => {
|
|
5339
5624
|
if (callback) {
|
|
5340
5625
|
process.nextTick(() => callback(null));
|
|
5341
5626
|
return;
|
|
5342
5627
|
}
|
|
5343
5628
|
return Promise.resolve();
|
|
5344
|
-
}
|
|
5345
|
-
|
|
5629
|
+
},
|
|
5630
|
+
isServerRequest: false,
|
|
5631
|
+
replayModeHandler: () => {
|
|
5632
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
|
|
5633
|
+
name: `mysql2.${clientType}.connect`,
|
|
5634
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5635
|
+
submodule: "connect",
|
|
5636
|
+
packageName: "mysql2",
|
|
5637
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5638
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5639
|
+
inputValue,
|
|
5640
|
+
isPreAppStart: false
|
|
5641
|
+
}, (spanInfo) => {
|
|
5642
|
+
if (callback) {
|
|
5643
|
+
process.nextTick(() => callback(null));
|
|
5644
|
+
return;
|
|
5645
|
+
}
|
|
5646
|
+
return Promise.resolve();
|
|
5647
|
+
});
|
|
5648
|
+
}
|
|
5649
|
+
});
|
|
5346
5650
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5347
5651
|
originalFunctionCall: () => originalConnect.apply(this, [callback]),
|
|
5348
5652
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -5370,24 +5674,34 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5370
5674
|
return (originalPing) => {
|
|
5371
5675
|
return function ping(callback) {
|
|
5372
5676
|
const inputValue = { clientType };
|
|
5373
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5374
|
-
|
|
5375
|
-
name: `mysql2.${clientType}.ping`,
|
|
5376
|
-
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5377
|
-
submodule: "ping",
|
|
5378
|
-
packageName: "mysql2",
|
|
5379
|
-
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5380
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5381
|
-
inputValue,
|
|
5382
|
-
isPreAppStart: false
|
|
5383
|
-
}, (spanInfo) => {
|
|
5677
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5678
|
+
noOpRequestHandler: () => {
|
|
5384
5679
|
if (callback) {
|
|
5385
5680
|
process.nextTick(() => callback(null));
|
|
5386
5681
|
return;
|
|
5387
5682
|
}
|
|
5388
5683
|
return Promise.resolve();
|
|
5389
|
-
}
|
|
5390
|
-
|
|
5684
|
+
},
|
|
5685
|
+
isServerRequest: false,
|
|
5686
|
+
replayModeHandler: () => {
|
|
5687
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalPing.apply(this, [callback]), {
|
|
5688
|
+
name: `mysql2.${clientType}.ping`,
|
|
5689
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5690
|
+
submodule: "ping",
|
|
5691
|
+
packageName: "mysql2",
|
|
5692
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5693
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5694
|
+
inputValue,
|
|
5695
|
+
isPreAppStart: false
|
|
5696
|
+
}, (spanInfo) => {
|
|
5697
|
+
if (callback) {
|
|
5698
|
+
process.nextTick(() => callback(null));
|
|
5699
|
+
return;
|
|
5700
|
+
}
|
|
5701
|
+
return Promise.resolve();
|
|
5702
|
+
});
|
|
5703
|
+
}
|
|
5704
|
+
});
|
|
5391
5705
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5392
5706
|
originalFunctionCall: () => originalPing.apply(this, [callback]),
|
|
5393
5707
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -5415,24 +5729,34 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5415
5729
|
return (originalEnd) => {
|
|
5416
5730
|
return function end(callback) {
|
|
5417
5731
|
const inputValue = { clientType };
|
|
5418
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5419
|
-
|
|
5420
|
-
name: `mysql2.${clientType}.end`,
|
|
5421
|
-
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5422
|
-
submodule: "end",
|
|
5423
|
-
packageName: "mysql2",
|
|
5424
|
-
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5425
|
-
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5426
|
-
inputValue,
|
|
5427
|
-
isPreAppStart: false
|
|
5428
|
-
}, (spanInfo) => {
|
|
5732
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5733
|
+
noOpRequestHandler: () => {
|
|
5429
5734
|
if (callback) {
|
|
5430
5735
|
process.nextTick(() => callback(null));
|
|
5431
5736
|
return;
|
|
5432
5737
|
}
|
|
5433
5738
|
return Promise.resolve();
|
|
5434
|
-
}
|
|
5435
|
-
|
|
5739
|
+
},
|
|
5740
|
+
isServerRequest: false,
|
|
5741
|
+
replayModeHandler: () => {
|
|
5742
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalEnd.apply(this, [callback]), {
|
|
5743
|
+
name: `mysql2.${clientType}.end`,
|
|
5744
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
5745
|
+
submodule: "end",
|
|
5746
|
+
packageName: "mysql2",
|
|
5747
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
5748
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
5749
|
+
inputValue,
|
|
5750
|
+
isPreAppStart: false
|
|
5751
|
+
}, (spanInfo) => {
|
|
5752
|
+
if (callback) {
|
|
5753
|
+
process.nextTick(() => callback(null));
|
|
5754
|
+
return;
|
|
5755
|
+
}
|
|
5756
|
+
return Promise.resolve();
|
|
5757
|
+
});
|
|
5758
|
+
}
|
|
5759
|
+
});
|
|
5436
5760
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5437
5761
|
originalFunctionCall: () => originalEnd.apply(this, [callback]),
|
|
5438
5762
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -5607,6 +5931,9 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5607
5931
|
handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName = "query", stackTrace) {
|
|
5608
5932
|
return this.queryMock.handleReplayQuery(queryConfig, inputValue, spanInfo, submoduleName, stackTrace);
|
|
5609
5933
|
}
|
|
5934
|
+
handleNoOpReplayQuery(queryConfig) {
|
|
5935
|
+
return this.queryMock.handleNoOpReplayQuery(queryConfig);
|
|
5936
|
+
}
|
|
5610
5937
|
_handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$4) {
|
|
5611
5938
|
if (callback) {
|
|
5612
5939
|
const wrappedCallback = (error, connection) => {
|
|
@@ -5660,9 +5987,18 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5660
5987
|
throw error;
|
|
5661
5988
|
});
|
|
5662
5989
|
}
|
|
5990
|
+
handleNoOpReplayGetConnection(callback) {
|
|
5991
|
+
logger.debug(`[Mysql2Instrumentation] Background getConnection detected, returning mock connection`);
|
|
5992
|
+
const mockConnection = new TdMysql2ConnectionMock(this, "pool");
|
|
5993
|
+
if (callback) {
|
|
5994
|
+
process.nextTick(() => callback(null, mockConnection));
|
|
5995
|
+
return;
|
|
5996
|
+
}
|
|
5997
|
+
return Promise.resolve(mockConnection);
|
|
5998
|
+
}
|
|
5663
5999
|
_handleReplayPoolGetConnection(spanInfo, callback) {
|
|
5664
6000
|
logger.debug(`[Mysql2Instrumentation] Replaying MySQL2 Pool getConnection`);
|
|
5665
|
-
const mockConnection = new TdMysql2ConnectionMock(this,
|
|
6001
|
+
const mockConnection = new TdMysql2ConnectionMock(this, "pool", spanInfo);
|
|
5666
6002
|
if (callback) {
|
|
5667
6003
|
process.nextTick(() => callback(null, mockConnection));
|
|
5668
6004
|
return;
|
|
@@ -5721,58 +6057,59 @@ var Mysql2Instrumentation = class extends TdInstrumentationBase {
|
|
|
5721
6057
|
},
|
|
5722
6058
|
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
5723
6059
|
});
|
|
5724
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
clonedArgs
|
|
5743
|
-
clonedArgs[0].
|
|
6060
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
6061
|
+
noOpRequestHandler: () => {
|
|
6062
|
+
return new TdMysql2ConnectionMock(self, "connection");
|
|
6063
|
+
},
|
|
6064
|
+
isServerRequest: false,
|
|
6065
|
+
replayModeHandler: () => {
|
|
6066
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => new OriginalConnection(...args), {
|
|
6067
|
+
name: `mysql2.connection.create`,
|
|
6068
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6069
|
+
submodule: "connectEvent",
|
|
6070
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.MYSQL,
|
|
6071
|
+
packageName: "mysql2",
|
|
6072
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
6073
|
+
inputValue,
|
|
6074
|
+
isPreAppStart: false
|
|
6075
|
+
}, (spanInfo) => {
|
|
6076
|
+
class MockConnection extends OriginalConnection {
|
|
6077
|
+
constructor(...mockConnectionArgs) {
|
|
6078
|
+
const clonedArgs = JSON.parse(JSON.stringify(mockConnectionArgs));
|
|
6079
|
+
if (clonedArgs[0] && clonedArgs[0].config) {
|
|
6080
|
+
clonedArgs[0].config.host = "127.0.0.1";
|
|
6081
|
+
clonedArgs[0].config.port = 127;
|
|
6082
|
+
} else if (clonedArgs[0]) {
|
|
6083
|
+
clonedArgs[0].host = "127.0.0.1";
|
|
6084
|
+
clonedArgs[0].port = 127;
|
|
6085
|
+
}
|
|
6086
|
+
super(...clonedArgs);
|
|
6087
|
+
this._isConnectOrErrorEmitted = false;
|
|
6088
|
+
this._connectEventMock = new TdMysql2ConnectionEventMock(spanInfo);
|
|
5744
6089
|
}
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
this._isConnectOrErrorEmitted = true;
|
|
6090
|
+
on(event, listener) {
|
|
6091
|
+
if (!this._connectEventMock) return super.on(event, listener);
|
|
6092
|
+
if (event === "connect" && !this._isConnectOrErrorEmitted) {
|
|
6093
|
+
this._connectEventMock.getReplayedConnectionEvent(inputValue).then(({ output }) => {
|
|
6094
|
+
if (output !== void 0) process.nextTick(() => {
|
|
6095
|
+
listener.call(this, output);
|
|
6096
|
+
this._isConnectOrErrorEmitted = true;
|
|
6097
|
+
});
|
|
6098
|
+
}).catch((err) => {
|
|
6099
|
+
logger.error(`[Mysql2Instrumentation] Error replaying connection event:`, err);
|
|
5756
6100
|
});
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
return
|
|
6101
|
+
return this;
|
|
6102
|
+
}
|
|
6103
|
+
if (event === "error" && !this._isConnectOrErrorEmitted) return this;
|
|
6104
|
+
return super.on(event, listener);
|
|
5761
6105
|
}
|
|
5762
|
-
if (event === "error" && !this._isConnectOrErrorEmitted) return this;
|
|
5763
|
-
return super.on(event, listener);
|
|
5764
6106
|
}
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
} });
|
|
5772
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
5773
|
-
return mockConnection;
|
|
5774
|
-
});
|
|
5775
|
-
} });
|
|
6107
|
+
const mockConnection = new MockConnection(...args);
|
|
6108
|
+
mockConnection.addListener("error", (_err) => {});
|
|
6109
|
+
return mockConnection;
|
|
6110
|
+
});
|
|
6111
|
+
}
|
|
6112
|
+
});
|
|
5776
6113
|
return new OriginalConnection(...args);
|
|
5777
6114
|
}
|
|
5778
6115
|
const staticProps = Object.getOwnPropertyNames(OriginalConnection).filter((key) => ![
|
|
@@ -5821,6 +6158,7 @@ var TcpInstrumentation = class extends TdInstrumentationBase {
|
|
|
5821
6158
|
super("tcp", config);
|
|
5822
6159
|
this.loggedSpans = /* @__PURE__ */ new Set();
|
|
5823
6160
|
this.mode = config.mode || TuskDriftMode.DISABLED;
|
|
6161
|
+
this._patchLoadedModules();
|
|
5824
6162
|
}
|
|
5825
6163
|
init() {
|
|
5826
6164
|
return [new TdInstrumentationNodeModule({
|
|
@@ -5829,6 +6167,17 @@ var TcpInstrumentation = class extends TdInstrumentationBase {
|
|
|
5829
6167
|
patch: (moduleExports) => this._patchNetModule(moduleExports)
|
|
5830
6168
|
})];
|
|
5831
6169
|
}
|
|
6170
|
+
_patchLoadedModules() {
|
|
6171
|
+
if (isNextJsRuntime()) {
|
|
6172
|
+
logger.debug(`[TcpInstrumentation] Next.js environment detected - force-loading net module to ensure patching`);
|
|
6173
|
+
try {
|
|
6174
|
+
require("net");
|
|
6175
|
+
logger.debug(`[TcpInstrumentation] net module force-loaded`);
|
|
6176
|
+
} catch (err) {
|
|
6177
|
+
logger.error(`[TcpInstrumentation] Error force-loading net module:`, err);
|
|
6178
|
+
}
|
|
6179
|
+
} else logger.debug(`[TcpInstrumentation] Regular Node.js environment - hooks will catch net module on first require`);
|
|
6180
|
+
}
|
|
5832
6181
|
_patchNetModule(netModule) {
|
|
5833
6182
|
logger.debug(`[TcpInstrumentation] Patching NET module in ${this.mode} mode`);
|
|
5834
6183
|
if (this.isModulePatched(netModule)) {
|
|
@@ -5958,19 +6307,28 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
5958
6307
|
}
|
|
5959
6308
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
5960
6309
|
const stackTrace = captureStackTrace(["JsonwebtokenInstrumentation"]);
|
|
5961
|
-
return handleReplayMode({
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
6310
|
+
return handleReplayMode({
|
|
6311
|
+
noOpRequestHandler: () => {
|
|
6312
|
+
if (!!verifyConfig.callback) {
|
|
6313
|
+
process.nextTick(() => verifyConfig.callback(null, void 0));
|
|
6314
|
+
return;
|
|
6315
|
+
} else return;
|
|
6316
|
+
},
|
|
6317
|
+
isServerRequest: false,
|
|
6318
|
+
replayModeHandler: () => {
|
|
6319
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalVerify.apply(this, args), {
|
|
6320
|
+
name: "jsonwebtoken.verify",
|
|
6321
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6322
|
+
submodule: "verify",
|
|
6323
|
+
packageName: "jsonwebtoken",
|
|
6324
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
6325
|
+
inputValue,
|
|
6326
|
+
isPreAppStart: false
|
|
6327
|
+
}, (spanInfo) => {
|
|
6328
|
+
return self.handleReplayVerify(verifyConfig, inputValue, spanInfo, stackTrace);
|
|
6329
|
+
});
|
|
6330
|
+
}
|
|
6331
|
+
});
|
|
5974
6332
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
5975
6333
|
originalFunctionCall: () => originalVerify.apply(this, args),
|
|
5976
6334
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -6013,19 +6371,28 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6013
6371
|
};
|
|
6014
6372
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
6015
6373
|
const stackTrace = captureStackTrace(["JsonwebtokenInstrumentation"]);
|
|
6016
|
-
return handleReplayMode({
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6374
|
+
return handleReplayMode({
|
|
6375
|
+
noOpRequestHandler: () => {
|
|
6376
|
+
if (!!signConfig.callback) {
|
|
6377
|
+
process.nextTick(() => signConfig.callback(null, void 0));
|
|
6378
|
+
return;
|
|
6379
|
+
} else return;
|
|
6380
|
+
},
|
|
6381
|
+
isServerRequest: false,
|
|
6382
|
+
replayModeHandler: () => {
|
|
6383
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSign.apply(this, args), {
|
|
6384
|
+
name: "jsonwebtoken.sign",
|
|
6385
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
6386
|
+
submodule: "sign",
|
|
6387
|
+
packageName: "jsonwebtoken",
|
|
6388
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
6389
|
+
inputValue,
|
|
6390
|
+
isPreAppStart: false
|
|
6391
|
+
}, (spanInfo) => {
|
|
6392
|
+
return self.handleReplaySign(signConfig, inputValue, spanInfo, stackTrace);
|
|
6393
|
+
});
|
|
6394
|
+
}
|
|
6395
|
+
});
|
|
6029
6396
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
6030
6397
|
originalFunctionCall: () => originalSign.apply(this, args),
|
|
6031
6398
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -6213,11 +6580,7 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6213
6580
|
const hasCallback = !!verifyConfig.callback;
|
|
6214
6581
|
if (!mockData) {
|
|
6215
6582
|
logger.warn(`[JsonwebtokenInstrumentation] No mock data found for JWT verify: ${verifyConfig.token}`);
|
|
6216
|
-
|
|
6217
|
-
if (hasCallback) {
|
|
6218
|
-
process.nextTick(() => verifyConfig.callback(error));
|
|
6219
|
-
return;
|
|
6220
|
-
} else throw error;
|
|
6583
|
+
throw new Error(`[JsonwebtokenInstrumentation] No matching mock found for JWT verify: ${verifyConfig.token}`);
|
|
6221
6584
|
}
|
|
6222
6585
|
if (mockData.result && mockData.result.error) {
|
|
6223
6586
|
let error = mockData.result.error;
|
|
@@ -6260,11 +6623,7 @@ var JsonwebtokenInstrumentation = class extends TdInstrumentationBase {
|
|
|
6260
6623
|
const hasCallback = !!signConfig.callback;
|
|
6261
6624
|
if (!mockData) {
|
|
6262
6625
|
logger.warn(`[JsonwebtokenInstrumentation] No mock data found for JWT sign`);
|
|
6263
|
-
|
|
6264
|
-
if (hasCallback) {
|
|
6265
|
-
process.nextTick(() => signConfig.callback(error));
|
|
6266
|
-
return;
|
|
6267
|
-
} else throw error;
|
|
6626
|
+
throw new Error(`[JsonwebtokenInstrumentation] No matching mock found for JWT sign`);
|
|
6268
6627
|
}
|
|
6269
6628
|
if (mockData.result && mockData.result.error) {
|
|
6270
6629
|
let error = mockData.result.error;
|
|
@@ -6681,20 +7040,30 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6681
7040
|
headers: normalizedHeaders,
|
|
6682
7041
|
body: encodedBody
|
|
6683
7042
|
};
|
|
6684
|
-
if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
7043
|
+
if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
7044
|
+
noOpRequestHandler: () => {
|
|
7045
|
+
const mockResponse = new Response(null, {
|
|
7046
|
+
status: 200,
|
|
7047
|
+
statusText: "OK"
|
|
7048
|
+
});
|
|
7049
|
+
return Promise.resolve(mockResponse);
|
|
7050
|
+
},
|
|
7051
|
+
isServerRequest: false,
|
|
7052
|
+
replayModeHandler: () => {
|
|
7053
|
+
return SpanUtils.createAndExecuteSpan(this.mode, () => this.originalFetch(input, init), {
|
|
7054
|
+
name: url,
|
|
7055
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7056
|
+
packageName: "fetch",
|
|
7057
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
7058
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
7059
|
+
submodule: inputValue.method,
|
|
7060
|
+
inputValue,
|
|
7061
|
+
isPreAppStart: false
|
|
7062
|
+
}, (spanInfo) => {
|
|
7063
|
+
return this._handleReplayFetch(inputValue, spanInfo, stackTrace);
|
|
7064
|
+
});
|
|
7065
|
+
}
|
|
7066
|
+
});
|
|
6698
7067
|
else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
6699
7068
|
originalFunctionCall: () => this.originalFetch(input, init),
|
|
6700
7069
|
recordModeHandler: ({ isPreAppStart }) => this._handleRecordFetch(input, inputValue, isPreAppStart, init),
|
|
@@ -6796,7 +7165,10 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
|
|
|
6796
7165
|
...inputValue.headers && { headers: { matchImportance: 0 } }
|
|
6797
7166
|
}
|
|
6798
7167
|
});
|
|
6799
|
-
if (!mockData)
|
|
7168
|
+
if (!mockData) {
|
|
7169
|
+
logger.warn(`[FetchInstrumentation] No mock data found for fetch request with input value: ${JSON.stringify(inputValue)}`);
|
|
7170
|
+
throw new Error(`[FetchInstrumentation] No matching mock found for fetch request`);
|
|
7171
|
+
}
|
|
6800
7172
|
const { result } = mockData;
|
|
6801
7173
|
const responseBody = this._constructFetchResponseBody(result);
|
|
6802
7174
|
const mockResponse = new Response(responseBody, {
|
|
@@ -6981,7 +7353,7 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
6981
7353
|
logger.debug(`[IORedisInstrumentation] IORedis module already patched, skipping`);
|
|
6982
7354
|
return moduleExports;
|
|
6983
7355
|
}
|
|
6984
|
-
const actualExports = moduleExports
|
|
7356
|
+
const actualExports = isEsm(moduleExports) ? moduleExports.default : moduleExports;
|
|
6985
7357
|
if (!actualExports || !actualExports.prototype) {
|
|
6986
7358
|
logger.error(`[IORedisInstrumentation] Invalid module exports, cannot patch`);
|
|
6987
7359
|
return moduleExports;
|
|
@@ -7020,7 +7392,7 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7020
7392
|
logger.debug(`[IORedisInstrumentation] Pipeline module already patched, skipping`);
|
|
7021
7393
|
return moduleExports;
|
|
7022
7394
|
}
|
|
7023
|
-
const actualExports = moduleExports
|
|
7395
|
+
const actualExports = isEsm(moduleExports) ? moduleExports.default : moduleExports;
|
|
7024
7396
|
if (!actualExports || !actualExports.prototype) {
|
|
7025
7397
|
logger.debug(`[IORedisInstrumentation] Invalid Pipeline module exports, cannot patch`);
|
|
7026
7398
|
return moduleExports;
|
|
@@ -7062,20 +7434,24 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7062
7434
|
};
|
|
7063
7435
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
7064
7436
|
const stackTrace = captureStackTrace(["IORedisInstrumentation"]);
|
|
7065
|
-
return handleReplayMode({
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7437
|
+
return handleReplayMode({
|
|
7438
|
+
noOpRequestHandler: () => {},
|
|
7439
|
+
isServerRequest: false,
|
|
7440
|
+
replayModeHandler: () => {
|
|
7441
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSendCommand.apply(this, arguments), {
|
|
7442
|
+
name: `ioredis.${commandName}`,
|
|
7443
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7444
|
+
submodule: commandName,
|
|
7445
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.REDIS,
|
|
7446
|
+
packageName: "ioredis",
|
|
7447
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7448
|
+
inputValue,
|
|
7449
|
+
isPreAppStart: false
|
|
7450
|
+
}, (spanInfo) => {
|
|
7451
|
+
return self._handleReplaySendCommand(spanInfo, cmd, inputValue, stackTrace);
|
|
7452
|
+
});
|
|
7453
|
+
}
|
|
7454
|
+
});
|
|
7079
7455
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
7080
7456
|
originalFunctionCall: () => originalSendCommand.apply(this, arguments),
|
|
7081
7457
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -7106,20 +7482,29 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7106
7482
|
host: this.options?.host,
|
|
7107
7483
|
port: this.options?.port
|
|
7108
7484
|
};
|
|
7109
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7485
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
7486
|
+
noOpRequestHandler: () => {
|
|
7487
|
+
process.nextTick(() => {
|
|
7488
|
+
this.emit("ready");
|
|
7489
|
+
});
|
|
7490
|
+
return Promise.resolve();
|
|
7491
|
+
},
|
|
7492
|
+
isServerRequest: false,
|
|
7493
|
+
replayModeHandler: () => {
|
|
7494
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, arguments), {
|
|
7495
|
+
name: "ioredis.connect",
|
|
7496
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7497
|
+
submodule: "connect",
|
|
7498
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.REDIS,
|
|
7499
|
+
packageName: "ioredis",
|
|
7500
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7501
|
+
inputValue,
|
|
7502
|
+
isPreAppStart: false
|
|
7503
|
+
}, (spanInfo) => {
|
|
7504
|
+
return self._handleReplayConnect(this);
|
|
7505
|
+
});
|
|
7506
|
+
}
|
|
7507
|
+
});
|
|
7123
7508
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
7124
7509
|
originalFunctionCall: () => originalConnect.apply(this, arguments),
|
|
7125
7510
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -7176,20 +7561,26 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7176
7561
|
command: q.name,
|
|
7177
7562
|
args: q.args || []
|
|
7178
7563
|
})) };
|
|
7179
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7564
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
7565
|
+
noOpRequestHandler: () => {
|
|
7566
|
+
return [];
|
|
7567
|
+
},
|
|
7568
|
+
isServerRequest: false,
|
|
7569
|
+
replayModeHandler: () => {
|
|
7570
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalExec.apply(this, args), {
|
|
7571
|
+
name: "ioredis.pipeline.exec",
|
|
7572
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
7573
|
+
submodule: "pipeline-exec",
|
|
7574
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.REDIS,
|
|
7575
|
+
packageName: "ioredis",
|
|
7576
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
7577
|
+
inputValue,
|
|
7578
|
+
isPreAppStart: false
|
|
7579
|
+
}, (spanInfo) => {
|
|
7580
|
+
return self._handleReplayPipelineExec(spanInfo, inputValue, args);
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7583
|
+
});
|
|
7193
7584
|
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
7194
7585
|
originalFunctionCall: () => originalExec.apply(this, args),
|
|
7195
7586
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -7238,7 +7629,7 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7238
7629
|
});
|
|
7239
7630
|
return promise;
|
|
7240
7631
|
}
|
|
7241
|
-
async _handleReplaySendCommand(spanInfo, cmd, inputValue,
|
|
7632
|
+
async _handleReplaySendCommand(spanInfo, cmd, inputValue, stackTrace) {
|
|
7242
7633
|
logger.debug(`[IORedisInstrumentation] Replaying IORedis command ${cmd.name}`);
|
|
7243
7634
|
const mockData = await findMockResponseAsync({
|
|
7244
7635
|
mockRequestData: {
|
|
@@ -7256,13 +7647,10 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7256
7647
|
});
|
|
7257
7648
|
if (!mockData) {
|
|
7258
7649
|
logger.warn(`[IORedisInstrumentation] No mock data found for command: ${cmd.name}`);
|
|
7259
|
-
|
|
7260
|
-
return;
|
|
7650
|
+
throw new Error(`[IORedisInstrumentation] No matching mock found for command: ${cmd.name}`);
|
|
7261
7651
|
}
|
|
7262
7652
|
logger.debug(`[IORedisInstrumentation] Found mock data for command ${cmd.name}: ${JSON.stringify(mockData)}`);
|
|
7263
7653
|
const result = this._deserializeOutput(mockData.result);
|
|
7264
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: mockData.result });
|
|
7265
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
7266
7654
|
if (cmd.callback && typeof cmd.callback === "function") process.nextTick(() => {
|
|
7267
7655
|
cmd.callback(null, result);
|
|
7268
7656
|
});
|
|
@@ -7300,10 +7688,8 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7300
7688
|
}
|
|
7301
7689
|
return promise;
|
|
7302
7690
|
}
|
|
7303
|
-
async _handleReplayConnect(
|
|
7691
|
+
async _handleReplayConnect(thisContext) {
|
|
7304
7692
|
logger.debug(`[IORedisInstrumentation] Replaying IORedis connect`);
|
|
7305
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
|
|
7306
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
7307
7693
|
process.nextTick(() => {
|
|
7308
7694
|
thisContext.emit("ready");
|
|
7309
7695
|
});
|
|
@@ -7352,8 +7738,7 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7352
7738
|
});
|
|
7353
7739
|
if (!mockData) {
|
|
7354
7740
|
logger.warn(`[IORedisInstrumentation] No mock data found for pipeline exec`);
|
|
7355
|
-
|
|
7356
|
-
return [];
|
|
7741
|
+
throw new Error(`[IORedisInstrumentation] No matching mock found for pipeline exec`);
|
|
7357
7742
|
}
|
|
7358
7743
|
logger.debug(`[IORedisInstrumentation] Found mock data for pipeline exec: ${JSON.stringify(mockData)}`);
|
|
7359
7744
|
const result = this._deserializePipelineOutput(mockData.result);
|
|
@@ -7361,8 +7746,6 @@ var IORedisInstrumentation = class extends TdInstrumentationBase {
|
|
|
7361
7746
|
if (typeof callback === "function") process.nextTick(() => {
|
|
7362
7747
|
callback(null, result);
|
|
7363
7748
|
});
|
|
7364
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: mockData.result });
|
|
7365
|
-
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
7366
7749
|
return Promise.resolve(result);
|
|
7367
7750
|
}
|
|
7368
7751
|
_sanitizeArgs(args) {
|
|
@@ -7613,6 +7996,7 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7613
7996
|
return;
|
|
7614
7997
|
}
|
|
7615
7998
|
this._wrap(clientPrototype, "makeUnaryRequest", this._getMakeUnaryRequestPatchFn(version$1));
|
|
7999
|
+
this._wrap(clientPrototype, "makeServerStreamRequest", this._getMakeServerStreamRequestPatchFn(version$1));
|
|
7616
8000
|
this._wrap(clientPrototype, "waitForReady", this._getWaitForReadyPatchFn());
|
|
7617
8001
|
this._wrap(clientPrototype, "close", this._getClosePatchFn());
|
|
7618
8002
|
this._wrap(clientPrototype, "getChannel", this._getGetChannelPatchFn());
|
|
@@ -7662,6 +8046,7 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7662
8046
|
logger.debug(`[GrpcInstrumentation] _getMakeUnaryRequestPatchFn called for version: ${version$1}`);
|
|
7663
8047
|
return (original) => {
|
|
7664
8048
|
return function makeUnaryRequest(...args) {
|
|
8049
|
+
logger.debug(`[GrpcInstrumentation] makeUnaryRequest called! args length: ${args.length}`);
|
|
7665
8050
|
const MetadataConstructor = GrpcInstrumentation.metadataStore.get(version$1) || self.Metadata;
|
|
7666
8051
|
if (!MetadataConstructor) {
|
|
7667
8052
|
logger.warn(`[GrpcInstrumentation] Metadata constructor not found for version ${version$1}`);
|
|
@@ -7701,20 +8086,26 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7701
8086
|
};
|
|
7702
8087
|
if (self.mode === TuskDriftMode.REPLAY) {
|
|
7703
8088
|
const stackTrace = captureStackTrace(["GrpcInstrumentation"]);
|
|
7704
|
-
return handleReplayMode({
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
8089
|
+
return handleReplayMode({
|
|
8090
|
+
noOpRequestHandler: () => {
|
|
8091
|
+
callback(null, void 0);
|
|
8092
|
+
},
|
|
8093
|
+
isServerRequest: false,
|
|
8094
|
+
replayModeHandler: () => {
|
|
8095
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
8096
|
+
name: "grpc.client.unary",
|
|
8097
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
8098
|
+
submodule: "client",
|
|
8099
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.GRPC,
|
|
8100
|
+
packageName: GRPC_MODULE_NAME,
|
|
8101
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
8102
|
+
inputValue,
|
|
8103
|
+
isPreAppStart: false
|
|
8104
|
+
}, (spanInfo) => {
|
|
8105
|
+
return self._handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor, stackTrace);
|
|
8106
|
+
});
|
|
8107
|
+
}
|
|
8108
|
+
});
|
|
7718
8109
|
} else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
7719
8110
|
originalFunctionCall: () => original.apply(this, args),
|
|
7720
8111
|
recordModeHandler: ({ isPreAppStart }) => {
|
|
@@ -7737,33 +8128,157 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7737
8128
|
};
|
|
7738
8129
|
};
|
|
7739
8130
|
}
|
|
7740
|
-
|
|
7741
|
-
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
8131
|
+
_getMakeServerStreamRequestPatchFn(version$1) {
|
|
8132
|
+
const self = this;
|
|
8133
|
+
logger.debug(`[GrpcInstrumentation] _getMakeServerStreamRequestPatchFn called for version: ${version$1}`);
|
|
8134
|
+
return (original) => {
|
|
8135
|
+
return function makeServerStreamRequest(...args) {
|
|
8136
|
+
logger.debug(`[GrpcInstrumentation] makeServerStreamRequest called! args length: ${args.length}`);
|
|
8137
|
+
const MetadataConstructor = GrpcInstrumentation.metadataStore.get(version$1) || self.Metadata;
|
|
8138
|
+
if (!MetadataConstructor) {
|
|
8139
|
+
logger.warn(`[GrpcInstrumentation] Metadata constructor not found for version ${version$1}`);
|
|
8140
|
+
return original.apply(this, args);
|
|
8141
|
+
}
|
|
8142
|
+
let parsedParams;
|
|
8143
|
+
try {
|
|
8144
|
+
parsedParams = self.extractServerStreamRequestParameters(args, MetadataConstructor);
|
|
8145
|
+
} catch (error) {
|
|
8146
|
+
logger.error(`[GrpcInstrumentation] Error parsing makeServerStreamRequest arguments:`, error);
|
|
8147
|
+
return original.apply(this, args);
|
|
8148
|
+
}
|
|
8149
|
+
const { method: path$5, argument, metadata, options } = parsedParams;
|
|
8150
|
+
let method;
|
|
8151
|
+
let service;
|
|
8152
|
+
let readableBody;
|
|
8153
|
+
let bufferMap;
|
|
8154
|
+
let jsonableStringMap;
|
|
8155
|
+
let readableMetadata;
|
|
8156
|
+
try {
|
|
8157
|
+
({method, service} = parseGrpcPath(path$5));
|
|
8158
|
+
({readableBody, bufferMap, jsonableStringMap} = serializeGrpcPayload(argument));
|
|
8159
|
+
readableMetadata = serializeGrpcMetadata(metadata);
|
|
8160
|
+
} catch (error) {
|
|
8161
|
+
logger.error(`[GrpcInstrumentation] Error parsing makeServerStreamRequest arguments:`, error);
|
|
8162
|
+
return original.apply(this, args);
|
|
8163
|
+
}
|
|
8164
|
+
const inputValue = {
|
|
8165
|
+
method,
|
|
8166
|
+
service,
|
|
8167
|
+
body: readableBody,
|
|
8168
|
+
metadata: readableMetadata,
|
|
8169
|
+
inputMeta: {
|
|
8170
|
+
bufferMap,
|
|
8171
|
+
jsonableStringMap
|
|
8172
|
+
}
|
|
8173
|
+
};
|
|
8174
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
8175
|
+
noOpRequestHandler: () => {
|
|
8176
|
+
const stream$1 = new stream.Readable({
|
|
8177
|
+
objectMode: true,
|
|
8178
|
+
read() {}
|
|
8179
|
+
});
|
|
8180
|
+
Object.assign(stream$1, {
|
|
8181
|
+
cancel() {},
|
|
8182
|
+
getPeer: () => "0.0.0.0:0000",
|
|
8183
|
+
call: void 0
|
|
8184
|
+
});
|
|
8185
|
+
return stream$1;
|
|
8186
|
+
},
|
|
8187
|
+
isServerRequest: false,
|
|
8188
|
+
replayModeHandler: () => {
|
|
8189
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
8190
|
+
name: "grpc.client.server_stream",
|
|
8191
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
8192
|
+
submodule: "client",
|
|
8193
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.GRPC,
|
|
8194
|
+
packageName: GRPC_MODULE_NAME,
|
|
8195
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
8196
|
+
inputValue,
|
|
8197
|
+
isPreAppStart: false
|
|
8198
|
+
}, (spanInfo) => {
|
|
8199
|
+
return self._handleReplayServerStreamRequest(spanInfo, inputValue, MetadataConstructor);
|
|
8200
|
+
});
|
|
8201
|
+
}
|
|
8202
|
+
});
|
|
8203
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
8204
|
+
originalFunctionCall: () => original.apply(this, args),
|
|
8205
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
8206
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => original.apply(this, args), {
|
|
8207
|
+
name: "grpc.client.server_stream",
|
|
8208
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
8209
|
+
submodule: "client",
|
|
8210
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.GRPC,
|
|
8211
|
+
packageName: GRPC_MODULE_NAME,
|
|
8212
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
8213
|
+
inputValue,
|
|
8214
|
+
isPreAppStart
|
|
8215
|
+
}, (spanInfo) => {
|
|
8216
|
+
return self._handleRecordServerStreamRequest(spanInfo, original, this, parsedParams);
|
|
8217
|
+
});
|
|
8218
|
+
},
|
|
8219
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
8220
|
+
});
|
|
8221
|
+
else return original.apply(this, args);
|
|
8222
|
+
};
|
|
8223
|
+
};
|
|
8224
|
+
}
|
|
8225
|
+
extractServerStreamRequestParameters(args, MetadataConstructor) {
|
|
8226
|
+
const method = args[0];
|
|
8227
|
+
const serialize = args[1];
|
|
8228
|
+
const deserialize = args[2];
|
|
8229
|
+
const argument = args[3];
|
|
8230
|
+
let metadata;
|
|
8231
|
+
let options;
|
|
8232
|
+
if (args.length === 6) {
|
|
8233
|
+
metadata = args[4];
|
|
8234
|
+
options = args[5];
|
|
8235
|
+
} else if (args.length === 5) if (args[4] instanceof MetadataConstructor) {
|
|
8236
|
+
metadata = args[4];
|
|
8237
|
+
options = {};
|
|
8238
|
+
} else {
|
|
8239
|
+
metadata = new MetadataConstructor();
|
|
8240
|
+
options = args[4] || {};
|
|
8241
|
+
}
|
|
8242
|
+
else {
|
|
8243
|
+
metadata = new MetadataConstructor();
|
|
8244
|
+
options = {};
|
|
8245
|
+
}
|
|
8246
|
+
return {
|
|
8247
|
+
method,
|
|
8248
|
+
serialize,
|
|
8249
|
+
deserialize,
|
|
8250
|
+
argument,
|
|
8251
|
+
metadata,
|
|
8252
|
+
options
|
|
8253
|
+
};
|
|
8254
|
+
}
|
|
8255
|
+
_handleRecordUnaryRequest(spanInfo, original, context$4, parsedParams, callback) {
|
|
8256
|
+
let isResponseReceived = false;
|
|
8257
|
+
let isStatusEmitted = false;
|
|
8258
|
+
let hasErrorOccurred = false;
|
|
8259
|
+
let isSpanCompleted = false;
|
|
8260
|
+
let readableResponseBody;
|
|
8261
|
+
let responseBufferMap = {};
|
|
8262
|
+
let responseJsonableStringMap = {};
|
|
8263
|
+
let status;
|
|
8264
|
+
let responseMetadataInitial = {};
|
|
8265
|
+
let serviceError;
|
|
8266
|
+
/**
|
|
8267
|
+
* Completes the span exactly once, regardless of which event fires first.
|
|
8268
|
+
* gRPC's asynchronous nature means the callback and status event can fire in any order,
|
|
8269
|
+
* so we need to guard against double span completion.
|
|
8270
|
+
*/
|
|
8271
|
+
const completeSpan = (output, statusCode, errorMessage) => {
|
|
8272
|
+
if (isSpanCompleted) return;
|
|
8273
|
+
isSpanCompleted = true;
|
|
8274
|
+
try {
|
|
8275
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: output });
|
|
8276
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
8277
|
+
code: statusCode,
|
|
8278
|
+
message: errorMessage
|
|
8279
|
+
});
|
|
8280
|
+
} catch (e) {
|
|
8281
|
+
logger.error(`[GrpcInstrumentation] Error completing span:`, e);
|
|
7767
8282
|
}
|
|
7768
8283
|
};
|
|
7769
8284
|
const patchedCallback = (err, value) => {
|
|
@@ -7839,113 +8354,1221 @@ var GrpcInstrumentation = class GrpcInstrumentation extends TdInstrumentationBas
|
|
|
7839
8354
|
status,
|
|
7840
8355
|
metadata: responseMetadataInitial
|
|
7841
8356
|
};
|
|
7842
|
-
completeSpan(errorOutput, __opentelemetry_api.SpanStatusCode.ERROR, serviceError.message);
|
|
7843
|
-
}
|
|
7844
|
-
});
|
|
7845
|
-
return result;
|
|
8357
|
+
completeSpan(errorOutput, __opentelemetry_api.SpanStatusCode.ERROR, serviceError.message);
|
|
8358
|
+
}
|
|
8359
|
+
});
|
|
8360
|
+
return result;
|
|
8361
|
+
}
|
|
8362
|
+
isGrpcErrorOutput(result) {
|
|
8363
|
+
return "error" in result;
|
|
8364
|
+
}
|
|
8365
|
+
_handleReplayUnaryRequest(spanInfo, inputValue, callback, MetadataConstructor, stackTrace) {
|
|
8366
|
+
logger.debug(`[GrpcInstrumentation] Replaying gRPC unary request`);
|
|
8367
|
+
const emitter = Object.assign(new events.EventEmitter(), {
|
|
8368
|
+
cancel() {},
|
|
8369
|
+
getPeer: () => "0.0.0.0:0000",
|
|
8370
|
+
call: void 0
|
|
8371
|
+
});
|
|
8372
|
+
findMockResponseAsync({
|
|
8373
|
+
mockRequestData: {
|
|
8374
|
+
traceId: spanInfo.traceId,
|
|
8375
|
+
spanId: spanInfo.spanId,
|
|
8376
|
+
name: "grpc.client.unary",
|
|
8377
|
+
inputValue,
|
|
8378
|
+
packageName: GRPC_MODULE_NAME,
|
|
8379
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.GRPC,
|
|
8380
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
8381
|
+
submoduleName: "client",
|
|
8382
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
8383
|
+
stackTrace
|
|
8384
|
+
},
|
|
8385
|
+
tuskDrift: this.tuskDrift
|
|
8386
|
+
}).then((mockData) => {
|
|
8387
|
+
if (!mockData) {
|
|
8388
|
+
logger.warn(`[GrpcInstrumentation] No mock data found for gRPC request: ${inputValue.service}/${inputValue.method}`, inputValue);
|
|
8389
|
+
throw new Error(`[GrpcInstrumentation] No matching mock found for gRPC unary request`);
|
|
8390
|
+
}
|
|
8391
|
+
const mockResult = mockData.result;
|
|
8392
|
+
let status;
|
|
8393
|
+
if (this.isGrpcErrorOutput(mockResult)) {
|
|
8394
|
+
const { error, status: errorStatus } = mockResult;
|
|
8395
|
+
status = {
|
|
8396
|
+
code: errorStatus.code,
|
|
8397
|
+
details: errorStatus.details,
|
|
8398
|
+
metadata: deserializeGrpcMetadata(MetadataConstructor, errorStatus.metadata)
|
|
8399
|
+
};
|
|
8400
|
+
const errorObj = Object.assign(new Error(error.message), {
|
|
8401
|
+
name: error.name,
|
|
8402
|
+
stack: error.stack,
|
|
8403
|
+
...status
|
|
8404
|
+
});
|
|
8405
|
+
callback(errorObj);
|
|
8406
|
+
} else {
|
|
8407
|
+
const { body, status: successStatus, bufferMap, jsonableStringMap } = mockResult;
|
|
8408
|
+
const bufferMapToUse = bufferMap || {};
|
|
8409
|
+
const jsonableStringMapToUse = jsonableStringMap || {};
|
|
8410
|
+
status = {
|
|
8411
|
+
code: successStatus.code,
|
|
8412
|
+
details: successStatus.details,
|
|
8413
|
+
metadata: deserializeGrpcMetadata(MetadataConstructor, successStatus.metadata)
|
|
8414
|
+
};
|
|
8415
|
+
const realResponse = deserializeGrpcPayload(body, bufferMapToUse, jsonableStringMapToUse);
|
|
8416
|
+
callback(null, realResponse);
|
|
8417
|
+
}
|
|
8418
|
+
process.nextTick(() => {
|
|
8419
|
+
if (mockResult.metadata) emitter.emit("metadata", deserializeGrpcMetadata(MetadataConstructor, mockResult.metadata));
|
|
8420
|
+
emitter.emit("status", status);
|
|
8421
|
+
});
|
|
8422
|
+
}).catch((error) => {
|
|
8423
|
+
logger.error(`[GrpcInstrumentation] Error fetching mock data:`, error);
|
|
8424
|
+
callback(error);
|
|
8425
|
+
});
|
|
8426
|
+
return emitter;
|
|
8427
|
+
}
|
|
8428
|
+
_handleRecordServerStreamRequest(spanInfo, original, context$4, parsedParams) {
|
|
8429
|
+
let hasErrorOccurred = false;
|
|
8430
|
+
let isSpanCompleted = false;
|
|
8431
|
+
let streamResponses = [];
|
|
8432
|
+
let status;
|
|
8433
|
+
let responseMetadataInitial = {};
|
|
8434
|
+
let serviceError;
|
|
8435
|
+
/**
|
|
8436
|
+
* Completes the span exactly once
|
|
8437
|
+
*/
|
|
8438
|
+
const completeSpan = (output, statusCode, errorMessage) => {
|
|
8439
|
+
if (isSpanCompleted) return;
|
|
8440
|
+
isSpanCompleted = true;
|
|
8441
|
+
try {
|
|
8442
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: output });
|
|
8443
|
+
SpanUtils.endSpan(spanInfo.span, { code: statusCode });
|
|
8444
|
+
} catch (e) {
|
|
8445
|
+
logger.error(`[GrpcInstrumentation] Error completing span:`, e);
|
|
8446
|
+
}
|
|
8447
|
+
};
|
|
8448
|
+
const inputArgs = [
|
|
8449
|
+
parsedParams.method,
|
|
8450
|
+
parsedParams.serialize,
|
|
8451
|
+
parsedParams.deserialize,
|
|
8452
|
+
parsedParams.argument,
|
|
8453
|
+
parsedParams.metadata,
|
|
8454
|
+
parsedParams.options
|
|
8455
|
+
];
|
|
8456
|
+
const stream$1 = original.apply(context$4, inputArgs);
|
|
8457
|
+
stream$1.on("data", (data) => {
|
|
8458
|
+
try {
|
|
8459
|
+
const { readableBody, bufferMap, jsonableStringMap } = serializeGrpcPayload(data);
|
|
8460
|
+
streamResponses.push({
|
|
8461
|
+
body: readableBody,
|
|
8462
|
+
bufferMap,
|
|
8463
|
+
jsonableStringMap
|
|
8464
|
+
});
|
|
8465
|
+
} catch (e) {
|
|
8466
|
+
logger.error(`[GrpcInstrumentation] Error serializing stream data:`, e);
|
|
8467
|
+
}
|
|
8468
|
+
});
|
|
8469
|
+
stream$1.on("metadata", (initialMetadata) => {
|
|
8470
|
+
responseMetadataInitial = serializeGrpcMetadata(initialMetadata);
|
|
8471
|
+
});
|
|
8472
|
+
stream$1.on("error", (err) => {
|
|
8473
|
+
serviceError = err;
|
|
8474
|
+
hasErrorOccurred = true;
|
|
8475
|
+
});
|
|
8476
|
+
stream$1.on("status", (responseStatus) => {
|
|
8477
|
+
status = {
|
|
8478
|
+
code: responseStatus.code,
|
|
8479
|
+
details: responseStatus.details,
|
|
8480
|
+
metadata: serializeGrpcMetadata(responseStatus.metadata)
|
|
8481
|
+
};
|
|
8482
|
+
if (!hasErrorOccurred && streamResponses.length > 0) completeSpan({
|
|
8483
|
+
body: streamResponses,
|
|
8484
|
+
metadata: responseMetadataInitial,
|
|
8485
|
+
status,
|
|
8486
|
+
bufferMap: {},
|
|
8487
|
+
jsonableStringMap: {}
|
|
8488
|
+
}, __opentelemetry_api.SpanStatusCode.OK);
|
|
8489
|
+
else if (!hasErrorOccurred && streamResponses.length === 0) completeSpan({
|
|
8490
|
+
body: [],
|
|
8491
|
+
metadata: responseMetadataInitial,
|
|
8492
|
+
status,
|
|
8493
|
+
bufferMap: {},
|
|
8494
|
+
jsonableStringMap: {}
|
|
8495
|
+
}, __opentelemetry_api.SpanStatusCode.OK);
|
|
8496
|
+
else if (hasErrorOccurred) {
|
|
8497
|
+
const errorOutput = {
|
|
8498
|
+
error: {
|
|
8499
|
+
message: serviceError.message,
|
|
8500
|
+
name: serviceError.name,
|
|
8501
|
+
stack: serviceError.stack
|
|
8502
|
+
},
|
|
8503
|
+
status,
|
|
8504
|
+
metadata: responseMetadataInitial
|
|
8505
|
+
};
|
|
8506
|
+
completeSpan(errorOutput, __opentelemetry_api.SpanStatusCode.ERROR, serviceError.message);
|
|
8507
|
+
}
|
|
8508
|
+
});
|
|
8509
|
+
return stream$1;
|
|
8510
|
+
}
|
|
8511
|
+
_handleReplayServerStreamRequest(spanInfo, inputValue, MetadataConstructor) {
|
|
8512
|
+
logger.debug(`[GrpcInstrumentation] Replaying gRPC server stream request`);
|
|
8513
|
+
const stream$1 = new stream.Readable({
|
|
8514
|
+
objectMode: true,
|
|
8515
|
+
read() {}
|
|
8516
|
+
});
|
|
8517
|
+
Object.assign(stream$1, {
|
|
8518
|
+
cancel() {},
|
|
8519
|
+
getPeer: () => "0.0.0.0:0000",
|
|
8520
|
+
call: void 0
|
|
8521
|
+
});
|
|
8522
|
+
findMockResponseAsync({
|
|
8523
|
+
mockRequestData: {
|
|
8524
|
+
traceId: spanInfo.traceId,
|
|
8525
|
+
spanId: spanInfo.spanId,
|
|
8526
|
+
name: "grpc.client.server_stream",
|
|
8527
|
+
inputValue,
|
|
8528
|
+
packageName: GRPC_MODULE_NAME,
|
|
8529
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.GRPC,
|
|
8530
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
8531
|
+
submoduleName: "client",
|
|
8532
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
8533
|
+
},
|
|
8534
|
+
tuskDrift: this.tuskDrift
|
|
8535
|
+
}).then((mockData) => {
|
|
8536
|
+
if (!mockData) {
|
|
8537
|
+
logger.warn(`[GrpcInstrumentation] No mock data found for gRPC server stream request: ${inputValue.service}/${inputValue.method}`, inputValue);
|
|
8538
|
+
throw new Error(`[GrpcInstrumentation] No matching mock found for gRPC server stream request`);
|
|
8539
|
+
}
|
|
8540
|
+
const mockResult = mockData.result;
|
|
8541
|
+
process.nextTick(() => {
|
|
8542
|
+
if (this.isGrpcErrorOutput(mockResult)) {
|
|
8543
|
+
const { error, status: errorStatus } = mockResult;
|
|
8544
|
+
const status = {
|
|
8545
|
+
code: errorStatus.code,
|
|
8546
|
+
details: errorStatus.details,
|
|
8547
|
+
metadata: deserializeGrpcMetadata(MetadataConstructor, errorStatus.metadata)
|
|
8548
|
+
};
|
|
8549
|
+
if (mockResult.metadata) stream$1.emit("metadata", deserializeGrpcMetadata(MetadataConstructor, mockResult.metadata));
|
|
8550
|
+
const errorObj = Object.assign(new Error(error.message), {
|
|
8551
|
+
name: error.name,
|
|
8552
|
+
stack: error.stack,
|
|
8553
|
+
...status
|
|
8554
|
+
});
|
|
8555
|
+
stream$1.emit("error", errorObj);
|
|
8556
|
+
stream$1.emit("status", status);
|
|
8557
|
+
stream$1.push(null);
|
|
8558
|
+
} else {
|
|
8559
|
+
const { body, status: successStatus } = mockResult;
|
|
8560
|
+
const status = {
|
|
8561
|
+
code: successStatus.code,
|
|
8562
|
+
details: successStatus.details,
|
|
8563
|
+
metadata: deserializeGrpcMetadata(MetadataConstructor, successStatus.metadata)
|
|
8564
|
+
};
|
|
8565
|
+
if (mockResult.metadata) stream$1.emit("metadata", deserializeGrpcMetadata(MetadataConstructor, mockResult.metadata));
|
|
8566
|
+
if (Array.isArray(body)) body.forEach((item) => {
|
|
8567
|
+
const bufferMapToUse = item.bufferMap || {};
|
|
8568
|
+
const jsonableStringMapToUse = item.jsonableStringMap || {};
|
|
8569
|
+
const realResponse = deserializeGrpcPayload(item.body, bufferMapToUse, jsonableStringMapToUse);
|
|
8570
|
+
stream$1.push(realResponse);
|
|
8571
|
+
});
|
|
8572
|
+
stream$1.push(null);
|
|
8573
|
+
stream$1.emit("status", status);
|
|
8574
|
+
}
|
|
8575
|
+
});
|
|
8576
|
+
}).catch((error) => {
|
|
8577
|
+
logger.error(`[GrpcInstrumentation] Error fetching mock data for server stream:`, error);
|
|
8578
|
+
process.nextTick(() => {
|
|
8579
|
+
stream$1.emit("error", error);
|
|
8580
|
+
stream$1.emit("status", {
|
|
8581
|
+
code: 2,
|
|
8582
|
+
details: error.message,
|
|
8583
|
+
metadata: new MetadataConstructor()
|
|
8584
|
+
});
|
|
8585
|
+
stream$1.push(null);
|
|
8586
|
+
});
|
|
8587
|
+
});
|
|
8588
|
+
return stream$1;
|
|
8589
|
+
}
|
|
8590
|
+
_getWaitForReadyPatchFn() {
|
|
8591
|
+
const self = this;
|
|
8592
|
+
return (original) => {
|
|
8593
|
+
return function waitForReady(deadline, callback) {
|
|
8594
|
+
if (self.mode === TuskDriftMode.REPLAY) {
|
|
8595
|
+
process.nextTick(() => callback());
|
|
8596
|
+
return;
|
|
8597
|
+
} else return original.apply(this, [deadline, callback]);
|
|
8598
|
+
};
|
|
8599
|
+
};
|
|
8600
|
+
}
|
|
8601
|
+
_getClosePatchFn() {
|
|
8602
|
+
const self = this;
|
|
8603
|
+
return (original) => {
|
|
8604
|
+
return function close() {
|
|
8605
|
+
if (self.mode === TuskDriftMode.REPLAY) return;
|
|
8606
|
+
else return original.apply(this, arguments);
|
|
8607
|
+
};
|
|
8608
|
+
};
|
|
8609
|
+
}
|
|
8610
|
+
_getGetChannelPatchFn() {
|
|
8611
|
+
const self = this;
|
|
8612
|
+
return (original) => {
|
|
8613
|
+
return function getChannel() {
|
|
8614
|
+
if (self.mode === TuskDriftMode.REPLAY) return {};
|
|
8615
|
+
else return original.apply(this, arguments);
|
|
8616
|
+
};
|
|
8617
|
+
};
|
|
8618
|
+
}
|
|
8619
|
+
_wrap(target, propertyName, wrapper) {
|
|
8620
|
+
wrap(target, propertyName, wrapper);
|
|
8621
|
+
}
|
|
8622
|
+
};
|
|
8623
|
+
GrpcInstrumentation.metadataStore = /* @__PURE__ */ new Map();
|
|
8624
|
+
|
|
8625
|
+
//#endregion
|
|
8626
|
+
//#region src/instrumentation/libraries/firestore/mocks/TdFirestoreDocumentMock.ts
|
|
8627
|
+
/**
|
|
8628
|
+
* Mock Firestore DocumentSnapshot for replay mode
|
|
8629
|
+
* Mimics the Firestore DocumentSnapshot API
|
|
8630
|
+
*/
|
|
8631
|
+
var TdFirestoreDocumentMock = class {
|
|
8632
|
+
constructor(documentData) {
|
|
8633
|
+
this.documentData = documentData;
|
|
8634
|
+
}
|
|
8635
|
+
/**
|
|
8636
|
+
* The document's identifier within its collection
|
|
8637
|
+
*/
|
|
8638
|
+
get id() {
|
|
8639
|
+
return this.documentData.id;
|
|
8640
|
+
}
|
|
8641
|
+
/**
|
|
8642
|
+
* Whether the document exists
|
|
8643
|
+
*/
|
|
8644
|
+
get exists() {
|
|
8645
|
+
return this.documentData.exists;
|
|
8646
|
+
}
|
|
8647
|
+
/**
|
|
8648
|
+
* A DocumentReference to the document location
|
|
8649
|
+
*/
|
|
8650
|
+
get ref() {
|
|
8651
|
+
return {
|
|
8652
|
+
id: this.documentData.id,
|
|
8653
|
+
path: this.documentData.path
|
|
8654
|
+
};
|
|
8655
|
+
}
|
|
8656
|
+
/**
|
|
8657
|
+
* The time the document was created (if available)
|
|
8658
|
+
*/
|
|
8659
|
+
get createTime() {
|
|
8660
|
+
return this.documentData.createTime ? {
|
|
8661
|
+
seconds: this.documentData.createTime.seconds,
|
|
8662
|
+
nanoseconds: this.documentData.createTime.nanoseconds,
|
|
8663
|
+
toDate: () => /* @__PURE__ */ new Date(this.documentData.createTime.seconds * 1e3 + this.documentData.createTime.nanoseconds / 1e6)
|
|
8664
|
+
} : null;
|
|
8665
|
+
}
|
|
8666
|
+
/**
|
|
8667
|
+
* The time the document was last updated (if available)
|
|
8668
|
+
*/
|
|
8669
|
+
get updateTime() {
|
|
8670
|
+
return this.documentData.updateTime ? {
|
|
8671
|
+
seconds: this.documentData.updateTime.seconds,
|
|
8672
|
+
nanoseconds: this.documentData.updateTime.nanoseconds,
|
|
8673
|
+
toDate: () => /* @__PURE__ */ new Date(this.documentData.updateTime.seconds * 1e3 + this.documentData.updateTime.nanoseconds / 1e6)
|
|
8674
|
+
} : null;
|
|
8675
|
+
}
|
|
8676
|
+
/**
|
|
8677
|
+
* The time the document was read (if available)
|
|
8678
|
+
*/
|
|
8679
|
+
get readTime() {
|
|
8680
|
+
return this.documentData.readTime ? {
|
|
8681
|
+
seconds: this.documentData.readTime.seconds,
|
|
8682
|
+
nanoseconds: this.documentData.readTime.nanoseconds,
|
|
8683
|
+
toDate: () => /* @__PURE__ */ new Date(this.documentData.readTime.seconds * 1e3 + this.documentData.readTime.nanoseconds / 1e6)
|
|
8684
|
+
} : null;
|
|
8685
|
+
}
|
|
8686
|
+
/**
|
|
8687
|
+
* Retrieves all fields in the document as an object
|
|
8688
|
+
*/
|
|
8689
|
+
data() {
|
|
8690
|
+
return this.documentData.data;
|
|
8691
|
+
}
|
|
8692
|
+
/**
|
|
8693
|
+
* Retrieves the field specified by fieldPath
|
|
8694
|
+
*/
|
|
8695
|
+
get(fieldPath) {
|
|
8696
|
+
if (!this.documentData.data) return;
|
|
8697
|
+
return this.documentData.data[fieldPath];
|
|
8698
|
+
}
|
|
8699
|
+
/**
|
|
8700
|
+
* Returns true if the document's data and path are equal to the provided value
|
|
8701
|
+
*/
|
|
8702
|
+
isEqual(other) {
|
|
8703
|
+
return this.documentData.path === other.documentData.path;
|
|
8704
|
+
}
|
|
8705
|
+
};
|
|
8706
|
+
|
|
8707
|
+
//#endregion
|
|
8708
|
+
//#region src/instrumentation/libraries/firestore/mocks/TdFirestoreQueryMock.ts
|
|
8709
|
+
/**
|
|
8710
|
+
* Mock Firestore QuerySnapshot for replay mode
|
|
8711
|
+
* Mimics the Firestore QuerySnapshot API
|
|
8712
|
+
*/
|
|
8713
|
+
var TdFirestoreQueryMock = class {
|
|
8714
|
+
constructor(queryResult) {
|
|
8715
|
+
this.queryResult = queryResult;
|
|
8716
|
+
this._docs = queryResult.docs.map((doc) => new TdFirestoreDocumentMock(doc));
|
|
8717
|
+
}
|
|
8718
|
+
/**
|
|
8719
|
+
* An array of all the documents in the QuerySnapshot
|
|
8720
|
+
*/
|
|
8721
|
+
get docs() {
|
|
8722
|
+
return this._docs;
|
|
8723
|
+
}
|
|
8724
|
+
/**
|
|
8725
|
+
* The number of documents in the QuerySnapshot
|
|
8726
|
+
*/
|
|
8727
|
+
get size() {
|
|
8728
|
+
return this.queryResult.size;
|
|
8729
|
+
}
|
|
8730
|
+
/**
|
|
8731
|
+
* True if there are no documents in the QuerySnapshot
|
|
8732
|
+
*/
|
|
8733
|
+
get empty() {
|
|
8734
|
+
return this.queryResult.empty;
|
|
8735
|
+
}
|
|
8736
|
+
/**
|
|
8737
|
+
* The time the query snapshot was read
|
|
8738
|
+
*/
|
|
8739
|
+
get readTime() {
|
|
8740
|
+
return this.queryResult.readTime ? {
|
|
8741
|
+
seconds: this.queryResult.readTime.seconds,
|
|
8742
|
+
nanoseconds: this.queryResult.readTime.nanoseconds,
|
|
8743
|
+
toDate: () => /* @__PURE__ */ new Date(this.queryResult.readTime.seconds * 1e3 + this.queryResult.readTime.nanoseconds / 1e6)
|
|
8744
|
+
} : null;
|
|
8745
|
+
}
|
|
8746
|
+
/**
|
|
8747
|
+
* The query on which you called get or onSnapshot
|
|
8748
|
+
*/
|
|
8749
|
+
get query() {
|
|
8750
|
+
return {};
|
|
8751
|
+
}
|
|
8752
|
+
/**
|
|
8753
|
+
* Enumerates all of the documents in the QuerySnapshot
|
|
8754
|
+
*/
|
|
8755
|
+
forEach(callback, thisArg) {
|
|
8756
|
+
this._docs.forEach(callback, thisArg);
|
|
8757
|
+
}
|
|
8758
|
+
/**
|
|
8759
|
+
* Returns an array of the documents changes since the last snapshot
|
|
8760
|
+
*/
|
|
8761
|
+
docChanges() {
|
|
8762
|
+
return [];
|
|
8763
|
+
}
|
|
8764
|
+
/**
|
|
8765
|
+
* Returns true if the document data and path are equal to this QuerySnapshot
|
|
8766
|
+
*/
|
|
8767
|
+
isEqual(other) {
|
|
8768
|
+
if (this.size !== other.size) return false;
|
|
8769
|
+
return this.size === other.size && this.empty === other.empty;
|
|
8770
|
+
}
|
|
8771
|
+
};
|
|
8772
|
+
|
|
8773
|
+
//#endregion
|
|
8774
|
+
//#region src/instrumentation/libraries/firestore/mocks/TdFirestoreWriteResultMock.ts
|
|
8775
|
+
/**
|
|
8776
|
+
* Mock Firestore WriteResult for replay mode
|
|
8777
|
+
* Mimics the Firestore WriteResult API
|
|
8778
|
+
*/
|
|
8779
|
+
var TdFirestoreWriteResultMock = class {
|
|
8780
|
+
constructor(result) {
|
|
8781
|
+
this.result = result;
|
|
8782
|
+
}
|
|
8783
|
+
/**
|
|
8784
|
+
* The write time as reported by the server
|
|
8785
|
+
*/
|
|
8786
|
+
get writeTime() {
|
|
8787
|
+
return this.result.writeTime ? {
|
|
8788
|
+
seconds: this.result.writeTime.seconds,
|
|
8789
|
+
nanoseconds: this.result.writeTime.nanoseconds,
|
|
8790
|
+
toDate: () => /* @__PURE__ */ new Date(this.result.writeTime.seconds * 1e3 + this.result.writeTime.nanoseconds / 1e6)
|
|
8791
|
+
} : null;
|
|
8792
|
+
}
|
|
8793
|
+
/**
|
|
8794
|
+
* Returns true if this WriteResult is equal to the provided one
|
|
8795
|
+
*/
|
|
8796
|
+
isEqual(other) {
|
|
8797
|
+
if (!this.writeTime || !other.writeTime) return this.writeTime === other.writeTime;
|
|
8798
|
+
return this.writeTime.seconds === other.writeTime.seconds && this.writeTime.nanoseconds === other.writeTime.nanoseconds;
|
|
8799
|
+
}
|
|
8800
|
+
};
|
|
8801
|
+
|
|
8802
|
+
//#endregion
|
|
8803
|
+
//#region src/instrumentation/libraries/firestore/Instrumentation.ts
|
|
8804
|
+
const FIRESTORE_VERSION = "7.*";
|
|
8805
|
+
const PACKAGE_NAME = "@google-cloud/firestore";
|
|
8806
|
+
var FirestoreInstrumentation = class extends TdInstrumentationBase {
|
|
8807
|
+
constructor(config = {}) {
|
|
8808
|
+
super(PACKAGE_NAME, config);
|
|
8809
|
+
this.INSTRUMENTATION_NAME = "FirestoreInstrumentation";
|
|
8810
|
+
this.originalCollectionDocFn = null;
|
|
8811
|
+
this.mode = config.mode || TuskDriftMode.DISABLED;
|
|
8812
|
+
this.tuskDrift = TuskDriftCore.getInstance();
|
|
8813
|
+
}
|
|
8814
|
+
init() {
|
|
8815
|
+
return [new TdInstrumentationNodeModule({
|
|
8816
|
+
name: PACKAGE_NAME,
|
|
8817
|
+
supportedVersions: [FIRESTORE_VERSION],
|
|
8818
|
+
files: [
|
|
8819
|
+
new TdInstrumentationNodeModuleFile({
|
|
8820
|
+
name: "@google-cloud/firestore/build/src/reference/document-reference.js",
|
|
8821
|
+
supportedVersions: [FIRESTORE_VERSION],
|
|
8822
|
+
patch: (moduleExports) => this._patchDocumentReference(moduleExports)
|
|
8823
|
+
}),
|
|
8824
|
+
new TdInstrumentationNodeModuleFile({
|
|
8825
|
+
name: "@google-cloud/firestore/build/src/reference/collection-reference.js",
|
|
8826
|
+
supportedVersions: [FIRESTORE_VERSION],
|
|
8827
|
+
patch: (moduleExports) => this._patchCollectionReference(moduleExports)
|
|
8828
|
+
}),
|
|
8829
|
+
new TdInstrumentationNodeModuleFile({
|
|
8830
|
+
name: "@google-cloud/firestore/build/src/reference/query.js",
|
|
8831
|
+
supportedVersions: [FIRESTORE_VERSION],
|
|
8832
|
+
patch: (moduleExports) => this._patchQuery(moduleExports)
|
|
8833
|
+
})
|
|
8834
|
+
]
|
|
8835
|
+
})];
|
|
8836
|
+
}
|
|
8837
|
+
_patchDocumentReference(moduleExports) {
|
|
8838
|
+
logger.debug(`[FirestoreInstrumentation] Patching DocumentReference in ${this.mode} mode`);
|
|
8839
|
+
if (this.isModulePatched(moduleExports)) {
|
|
8840
|
+
logger.debug(`[FirestoreInstrumentation] DocumentReference already patched, skipping`);
|
|
8841
|
+
return moduleExports;
|
|
8842
|
+
}
|
|
8843
|
+
const DocumentReference = moduleExports.DocumentReference;
|
|
8844
|
+
if (!DocumentReference || !DocumentReference.prototype) {
|
|
8845
|
+
logger.warn(`[FirestoreInstrumentation] DocumentReference.prototype not found`);
|
|
8846
|
+
return moduleExports;
|
|
8847
|
+
}
|
|
8848
|
+
this._wrap(DocumentReference.prototype, "get", this._getDocumentGetPatchFn());
|
|
8849
|
+
this._wrap(DocumentReference.prototype, "create", this._getDocumentCreatePatchFn());
|
|
8850
|
+
this._wrap(DocumentReference.prototype, "set", this._getDocumentSetPatchFn());
|
|
8851
|
+
this._wrap(DocumentReference.prototype, "update", this._getDocumentUpdatePatchFn());
|
|
8852
|
+
this._wrap(DocumentReference.prototype, "delete", this._getDocumentDeletePatchFn());
|
|
8853
|
+
this.markModuleAsPatched(moduleExports);
|
|
8854
|
+
logger.debug(`[FirestoreInstrumentation] DocumentReference patching complete`);
|
|
8855
|
+
return moduleExports;
|
|
8856
|
+
}
|
|
8857
|
+
_patchCollectionReference(moduleExports) {
|
|
8858
|
+
logger.debug(`[FirestoreInstrumentation] Patching CollectionReference in ${this.mode} mode`);
|
|
8859
|
+
if (this.isModulePatched(moduleExports)) {
|
|
8860
|
+
logger.debug(`[FirestoreInstrumentation] CollectionReference already patched, skipping`);
|
|
8861
|
+
return moduleExports;
|
|
8862
|
+
}
|
|
8863
|
+
const CollectionReference = moduleExports.CollectionReference;
|
|
8864
|
+
if (!CollectionReference || !CollectionReference.prototype) {
|
|
8865
|
+
logger.warn(`[FirestoreInstrumentation] CollectionReference.prototype not found`);
|
|
8866
|
+
return moduleExports;
|
|
8867
|
+
}
|
|
8868
|
+
this.originalCollectionDocFn = CollectionReference.prototype.doc;
|
|
8869
|
+
this._wrap(CollectionReference.prototype, "add", this._getCollectionAddPatchFn());
|
|
8870
|
+
this._wrap(CollectionReference.prototype, "doc", this._getCollectionDocPatchFn());
|
|
8871
|
+
this.markModuleAsPatched(moduleExports);
|
|
8872
|
+
logger.debug(`[FirestoreInstrumentation] CollectionReference patching complete`);
|
|
8873
|
+
return moduleExports;
|
|
8874
|
+
}
|
|
8875
|
+
_patchQuery(moduleExports) {
|
|
8876
|
+
logger.debug(`[FirestoreInstrumentation] Patching Query in ${this.mode} mode`);
|
|
8877
|
+
if (this.isModulePatched(moduleExports)) {
|
|
8878
|
+
logger.debug(`[FirestoreInstrumentation] Query already patched, skipping`);
|
|
8879
|
+
return moduleExports;
|
|
8880
|
+
}
|
|
8881
|
+
const Query = moduleExports.Query;
|
|
8882
|
+
if (!Query || !Query.prototype) {
|
|
8883
|
+
logger.warn(`[FirestoreInstrumentation] Query.prototype not found`);
|
|
8884
|
+
return moduleExports;
|
|
8885
|
+
}
|
|
8886
|
+
this._wrap(Query.prototype, "get", this._getQueryGetPatchFn());
|
|
8887
|
+
this.markModuleAsPatched(moduleExports);
|
|
8888
|
+
logger.debug(`[FirestoreInstrumentation] Query patching complete`);
|
|
8889
|
+
return moduleExports;
|
|
8890
|
+
}
|
|
8891
|
+
_getDocumentGetPatchFn() {
|
|
8892
|
+
const self = this;
|
|
8893
|
+
return (originalGet) => {
|
|
8894
|
+
return function() {
|
|
8895
|
+
const inputValue = {
|
|
8896
|
+
operation: "document.get",
|
|
8897
|
+
path: this.path
|
|
8898
|
+
};
|
|
8899
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
8900
|
+
noOpRequestHandler: () => {
|
|
8901
|
+
return new TdFirestoreDocumentMock({
|
|
8902
|
+
exists: false,
|
|
8903
|
+
id: "",
|
|
8904
|
+
path: ""
|
|
8905
|
+
});
|
|
8906
|
+
},
|
|
8907
|
+
isServerRequest: false,
|
|
8908
|
+
replayModeHandler: () => {
|
|
8909
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.call(this), {
|
|
8910
|
+
name: "firestore.document.get",
|
|
8911
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
8912
|
+
submodule: "document",
|
|
8913
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
8914
|
+
packageName: PACKAGE_NAME,
|
|
8915
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
8916
|
+
inputValue,
|
|
8917
|
+
isPreAppStart: false,
|
|
8918
|
+
stopRecordingChildSpans: true
|
|
8919
|
+
}, (spanInfo) => {
|
|
8920
|
+
return self._handleReplayDocumentGet(spanInfo, inputValue);
|
|
8921
|
+
});
|
|
8922
|
+
}
|
|
8923
|
+
});
|
|
8924
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
8925
|
+
originalFunctionCall: () => originalGet.call(this),
|
|
8926
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
8927
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.call(this), {
|
|
8928
|
+
name: "firestore.document.get",
|
|
8929
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
8930
|
+
submodule: "document",
|
|
8931
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
8932
|
+
packageName: PACKAGE_NAME,
|
|
8933
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
8934
|
+
inputValue,
|
|
8935
|
+
isPreAppStart,
|
|
8936
|
+
stopRecordingChildSpans: true
|
|
8937
|
+
}, (spanInfo) => {
|
|
8938
|
+
return self._handleRecordDocumentGet(spanInfo, originalGet, this);
|
|
8939
|
+
});
|
|
8940
|
+
},
|
|
8941
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
8942
|
+
});
|
|
8943
|
+
else return originalGet.call(this);
|
|
8944
|
+
};
|
|
8945
|
+
};
|
|
8946
|
+
}
|
|
8947
|
+
async _handleRecordDocumentGet(spanInfo, originalGet, context$4) {
|
|
8948
|
+
const snapshot = await originalGet.call(context$4);
|
|
8949
|
+
const documentResult = {
|
|
8950
|
+
id: snapshot.id,
|
|
8951
|
+
path: snapshot.ref.path,
|
|
8952
|
+
exists: snapshot.exists,
|
|
8953
|
+
data: snapshot.exists ? snapshot.data() : void 0,
|
|
8954
|
+
createTime: snapshot.createTime ? {
|
|
8955
|
+
seconds: snapshot.createTime.seconds,
|
|
8956
|
+
nanoseconds: snapshot.createTime.nanoseconds
|
|
8957
|
+
} : void 0,
|
|
8958
|
+
updateTime: snapshot.updateTime ? {
|
|
8959
|
+
seconds: snapshot.updateTime.seconds,
|
|
8960
|
+
nanoseconds: snapshot.updateTime.nanoseconds
|
|
8961
|
+
} : void 0,
|
|
8962
|
+
readTime: snapshot.readTime ? {
|
|
8963
|
+
seconds: snapshot.readTime.seconds,
|
|
8964
|
+
nanoseconds: snapshot.readTime.nanoseconds
|
|
8965
|
+
} : void 0
|
|
8966
|
+
};
|
|
8967
|
+
try {
|
|
8968
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: documentResult });
|
|
8969
|
+
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
8970
|
+
} catch {
|
|
8971
|
+
logger.error(`[FirestoreInstrumentation] Error updating span attributes for document.get`);
|
|
8972
|
+
}
|
|
8973
|
+
return snapshot;
|
|
8974
|
+
}
|
|
8975
|
+
async _handleReplayDocumentGet(spanInfo, inputValue) {
|
|
8976
|
+
logger.debug(`[FirestoreInstrumentation] Replaying document.get`);
|
|
8977
|
+
const mockData = await findMockResponseAsync({
|
|
8978
|
+
mockRequestData: {
|
|
8979
|
+
traceId: spanInfo.traceId,
|
|
8980
|
+
spanId: spanInfo.spanId,
|
|
8981
|
+
name: "firestore.document.get",
|
|
8982
|
+
inputValue: createMockInputValue(inputValue),
|
|
8983
|
+
packageName: PACKAGE_NAME,
|
|
8984
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
8985
|
+
submoduleName: "document",
|
|
8986
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
8987
|
+
},
|
|
8988
|
+
tuskDrift: this.tuskDrift
|
|
8989
|
+
});
|
|
8990
|
+
if (!mockData) {
|
|
8991
|
+
logger.warn(`[FirestoreInstrumentation] No mock data found for document.get: ${inputValue.path}`);
|
|
8992
|
+
throw new Error(`[FirestoreInstrumentation] No matching mock found for document.get`);
|
|
8993
|
+
}
|
|
8994
|
+
const documentResult = mockData.result;
|
|
8995
|
+
return new TdFirestoreDocumentMock(documentResult);
|
|
8996
|
+
}
|
|
8997
|
+
_getDocumentCreatePatchFn() {
|
|
8998
|
+
const self = this;
|
|
8999
|
+
return (originalCreate) => {
|
|
9000
|
+
return function(data) {
|
|
9001
|
+
const inputValue = {
|
|
9002
|
+
operation: "document.create",
|
|
9003
|
+
path: this.path,
|
|
9004
|
+
data
|
|
9005
|
+
};
|
|
9006
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9007
|
+
noOpRequestHandler: () => {
|
|
9008
|
+
const now = Date.now();
|
|
9009
|
+
const emptyWriteResult = { writeTime: {
|
|
9010
|
+
seconds: Math.floor(now / 1e3),
|
|
9011
|
+
nanoseconds: now % 1e3 * 1e6
|
|
9012
|
+
} };
|
|
9013
|
+
return new TdFirestoreWriteResultMock(emptyWriteResult);
|
|
9014
|
+
},
|
|
9015
|
+
isServerRequest: false,
|
|
9016
|
+
replayModeHandler: () => {
|
|
9017
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalCreate.call(this, data), {
|
|
9018
|
+
name: "firestore.document.create",
|
|
9019
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9020
|
+
submodule: "document",
|
|
9021
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9022
|
+
packageName: PACKAGE_NAME,
|
|
9023
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9024
|
+
inputValue,
|
|
9025
|
+
isPreAppStart: false,
|
|
9026
|
+
stopRecordingChildSpans: true
|
|
9027
|
+
}, (spanInfo) => {
|
|
9028
|
+
return self._handleReplayDocumentWrite(spanInfo, inputValue);
|
|
9029
|
+
});
|
|
9030
|
+
}
|
|
9031
|
+
});
|
|
9032
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9033
|
+
originalFunctionCall: () => originalCreate.call(this, data),
|
|
9034
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9035
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalCreate.call(this, data), {
|
|
9036
|
+
name: "firestore.document.create",
|
|
9037
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9038
|
+
submodule: "document",
|
|
9039
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9040
|
+
packageName: PACKAGE_NAME,
|
|
9041
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9042
|
+
inputValue,
|
|
9043
|
+
isPreAppStart,
|
|
9044
|
+
stopRecordingChildSpans: true
|
|
9045
|
+
}, (spanInfo) => {
|
|
9046
|
+
return self._handleRecordDocumentWrite(spanInfo, originalCreate, this, data);
|
|
9047
|
+
});
|
|
9048
|
+
},
|
|
9049
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9050
|
+
});
|
|
9051
|
+
else return originalCreate.call(this, data);
|
|
9052
|
+
};
|
|
9053
|
+
};
|
|
9054
|
+
}
|
|
9055
|
+
_getDocumentSetPatchFn() {
|
|
9056
|
+
const self = this;
|
|
9057
|
+
return (originalSet) => {
|
|
9058
|
+
return function(data, options) {
|
|
9059
|
+
const inputValue = {
|
|
9060
|
+
operation: "document.set",
|
|
9061
|
+
path: this.path,
|
|
9062
|
+
data,
|
|
9063
|
+
options
|
|
9064
|
+
};
|
|
9065
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9066
|
+
noOpRequestHandler: () => {
|
|
9067
|
+
const now = Date.now();
|
|
9068
|
+
const emptyWriteResult = { writeTime: {
|
|
9069
|
+
seconds: Math.floor(now / 1e3),
|
|
9070
|
+
nanoseconds: now % 1e3 * 1e6
|
|
9071
|
+
} };
|
|
9072
|
+
return new TdFirestoreWriteResultMock(emptyWriteResult);
|
|
9073
|
+
},
|
|
9074
|
+
isServerRequest: false,
|
|
9075
|
+
replayModeHandler: () => {
|
|
9076
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSet.call(this, data, options), {
|
|
9077
|
+
name: "firestore.document.set",
|
|
9078
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9079
|
+
submodule: "document",
|
|
9080
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9081
|
+
packageName: PACKAGE_NAME,
|
|
9082
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9083
|
+
inputValue,
|
|
9084
|
+
isPreAppStart: false,
|
|
9085
|
+
stopRecordingChildSpans: true
|
|
9086
|
+
}, (spanInfo) => {
|
|
9087
|
+
return self._handleReplayDocumentWrite(spanInfo, inputValue);
|
|
9088
|
+
});
|
|
9089
|
+
}
|
|
9090
|
+
});
|
|
9091
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9092
|
+
originalFunctionCall: () => originalSet.call(this, data, options),
|
|
9093
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9094
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalSet.call(this, data, options), {
|
|
9095
|
+
name: "firestore.document.set",
|
|
9096
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9097
|
+
submodule: "document",
|
|
9098
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9099
|
+
packageName: PACKAGE_NAME,
|
|
9100
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9101
|
+
inputValue,
|
|
9102
|
+
isPreAppStart,
|
|
9103
|
+
stopRecordingChildSpans: true
|
|
9104
|
+
}, (spanInfo) => {
|
|
9105
|
+
return self._handleRecordDocumentWrite(spanInfo, originalSet, this, data, options);
|
|
9106
|
+
});
|
|
9107
|
+
},
|
|
9108
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9109
|
+
});
|
|
9110
|
+
else return originalSet.call(this, data, options);
|
|
9111
|
+
};
|
|
9112
|
+
};
|
|
9113
|
+
}
|
|
9114
|
+
_getDocumentUpdatePatchFn() {
|
|
9115
|
+
const self = this;
|
|
9116
|
+
return (originalUpdate) => {
|
|
9117
|
+
return function(...args) {
|
|
9118
|
+
const inputValue = {
|
|
9119
|
+
operation: "document.update",
|
|
9120
|
+
path: this.path,
|
|
9121
|
+
data: args.length === 1 ? args[0] : args
|
|
9122
|
+
};
|
|
9123
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9124
|
+
noOpRequestHandler: () => {
|
|
9125
|
+
const now = Date.now();
|
|
9126
|
+
const emptyWriteResult = { writeTime: {
|
|
9127
|
+
seconds: Math.floor(now / 1e3),
|
|
9128
|
+
nanoseconds: now % 1e3 * 1e6
|
|
9129
|
+
} };
|
|
9130
|
+
return new TdFirestoreWriteResultMock(emptyWriteResult);
|
|
9131
|
+
},
|
|
9132
|
+
isServerRequest: false,
|
|
9133
|
+
replayModeHandler: () => {
|
|
9134
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalUpdate.apply(this, args), {
|
|
9135
|
+
name: "firestore.document.update",
|
|
9136
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9137
|
+
submodule: "document",
|
|
9138
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9139
|
+
packageName: PACKAGE_NAME,
|
|
9140
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9141
|
+
inputValue,
|
|
9142
|
+
isPreAppStart: false,
|
|
9143
|
+
stopRecordingChildSpans: true
|
|
9144
|
+
}, (spanInfo) => {
|
|
9145
|
+
return self._handleReplayDocumentWrite(spanInfo, inputValue);
|
|
9146
|
+
});
|
|
9147
|
+
}
|
|
9148
|
+
});
|
|
9149
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9150
|
+
originalFunctionCall: () => originalUpdate.apply(this, args),
|
|
9151
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9152
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalUpdate.apply(this, args), {
|
|
9153
|
+
name: "firestore.document.update",
|
|
9154
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9155
|
+
submodule: "document",
|
|
9156
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9157
|
+
packageName: PACKAGE_NAME,
|
|
9158
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9159
|
+
inputValue,
|
|
9160
|
+
isPreAppStart,
|
|
9161
|
+
stopRecordingChildSpans: true
|
|
9162
|
+
}, (spanInfo) => {
|
|
9163
|
+
return self._handleRecordDocumentWrite(spanInfo, originalUpdate, this, ...args);
|
|
9164
|
+
});
|
|
9165
|
+
},
|
|
9166
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9167
|
+
});
|
|
9168
|
+
else return originalUpdate.apply(this, args);
|
|
9169
|
+
};
|
|
9170
|
+
};
|
|
9171
|
+
}
|
|
9172
|
+
_getDocumentDeletePatchFn() {
|
|
9173
|
+
const self = this;
|
|
9174
|
+
return (originalDelete) => {
|
|
9175
|
+
return function(precondition) {
|
|
9176
|
+
const inputValue = {
|
|
9177
|
+
operation: "document.delete",
|
|
9178
|
+
path: this.path,
|
|
9179
|
+
options: precondition
|
|
9180
|
+
};
|
|
9181
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9182
|
+
noOpRequestHandler: () => {
|
|
9183
|
+
const now = Date.now();
|
|
9184
|
+
const emptyWriteResult = { writeTime: {
|
|
9185
|
+
seconds: Math.floor(now / 1e3),
|
|
9186
|
+
nanoseconds: now % 1e3 * 1e6
|
|
9187
|
+
} };
|
|
9188
|
+
return new TdFirestoreWriteResultMock(emptyWriteResult);
|
|
9189
|
+
},
|
|
9190
|
+
isServerRequest: false,
|
|
9191
|
+
replayModeHandler: () => {
|
|
9192
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalDelete.call(this, precondition), {
|
|
9193
|
+
name: "firestore.document.delete",
|
|
9194
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9195
|
+
submodule: "document",
|
|
9196
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9197
|
+
packageName: PACKAGE_NAME,
|
|
9198
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9199
|
+
inputValue,
|
|
9200
|
+
isPreAppStart: false,
|
|
9201
|
+
stopRecordingChildSpans: true
|
|
9202
|
+
}, (spanInfo) => {
|
|
9203
|
+
return self._handleReplayDocumentWrite(spanInfo, inputValue);
|
|
9204
|
+
});
|
|
9205
|
+
}
|
|
9206
|
+
});
|
|
9207
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9208
|
+
originalFunctionCall: () => originalDelete.call(this, precondition),
|
|
9209
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9210
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalDelete.call(this, precondition), {
|
|
9211
|
+
name: "firestore.document.delete",
|
|
9212
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9213
|
+
submodule: "document",
|
|
9214
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9215
|
+
packageName: PACKAGE_NAME,
|
|
9216
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9217
|
+
inputValue,
|
|
9218
|
+
isPreAppStart,
|
|
9219
|
+
stopRecordingChildSpans: true
|
|
9220
|
+
}, (spanInfo) => {
|
|
9221
|
+
return self._handleRecordDocumentWrite(spanInfo, originalDelete, this, precondition);
|
|
9222
|
+
});
|
|
9223
|
+
},
|
|
9224
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9225
|
+
});
|
|
9226
|
+
else return originalDelete.call(this, precondition);
|
|
9227
|
+
};
|
|
9228
|
+
};
|
|
9229
|
+
}
|
|
9230
|
+
async _handleRecordDocumentWrite(spanInfo, originalWrite, context$4, ...args) {
|
|
9231
|
+
const writeResult = await originalWrite.apply(context$4, args);
|
|
9232
|
+
const result = { writeTime: writeResult.writeTime ? {
|
|
9233
|
+
seconds: writeResult.writeTime.seconds,
|
|
9234
|
+
nanoseconds: writeResult.writeTime.nanoseconds
|
|
9235
|
+
} : void 0 };
|
|
9236
|
+
try {
|
|
9237
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: result });
|
|
9238
|
+
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
9239
|
+
} catch {
|
|
9240
|
+
logger.error(`[FirestoreInstrumentation] Error updating span attributes for document.write`);
|
|
9241
|
+
}
|
|
9242
|
+
return writeResult;
|
|
9243
|
+
}
|
|
9244
|
+
async _handleReplayDocumentWrite(spanInfo, inputValue) {
|
|
9245
|
+
logger.debug(`[FirestoreInstrumentation] Replaying document write: ${inputValue.operation}`);
|
|
9246
|
+
const mockData = await findMockResponseAsync({
|
|
9247
|
+
mockRequestData: {
|
|
9248
|
+
traceId: spanInfo.traceId,
|
|
9249
|
+
spanId: spanInfo.spanId,
|
|
9250
|
+
name: `firestore.${inputValue.operation}`,
|
|
9251
|
+
inputValue: createMockInputValue(inputValue),
|
|
9252
|
+
packageName: PACKAGE_NAME,
|
|
9253
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
9254
|
+
submoduleName: "document",
|
|
9255
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
9256
|
+
},
|
|
9257
|
+
tuskDrift: this.tuskDrift
|
|
9258
|
+
});
|
|
9259
|
+
if (!mockData) {
|
|
9260
|
+
logger.warn(`[FirestoreInstrumentation] No mock data found for ${inputValue.operation}: ${inputValue.path}`);
|
|
9261
|
+
throw new Error(`[FirestoreInstrumentation] No matching mock found for ${inputValue.operation}`);
|
|
9262
|
+
}
|
|
9263
|
+
const writeResult = mockData.result;
|
|
9264
|
+
return new TdFirestoreWriteResultMock(writeResult);
|
|
9265
|
+
}
|
|
9266
|
+
_getCollectionAddPatchFn() {
|
|
9267
|
+
const self = this;
|
|
9268
|
+
return (originalAdd) => {
|
|
9269
|
+
return function(data) {
|
|
9270
|
+
const inputValue = {
|
|
9271
|
+
operation: "collection.add",
|
|
9272
|
+
path: this.path,
|
|
9273
|
+
data
|
|
9274
|
+
};
|
|
9275
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9276
|
+
noOpRequestHandler: () => {
|
|
9277
|
+
if (!this.originalCollectionDocFn) {
|
|
9278
|
+
logger.error(`[FirestoreInstrumentation] Original doc function not available`);
|
|
9279
|
+
return Promise.reject(/* @__PURE__ */ new Error("Original doc function not available"));
|
|
9280
|
+
}
|
|
9281
|
+
return this.originalCollectionDocFn.call(this, "");
|
|
9282
|
+
},
|
|
9283
|
+
isServerRequest: false,
|
|
9284
|
+
replayModeHandler: () => {
|
|
9285
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalAdd.call(this, data), {
|
|
9286
|
+
name: "firestore.collection.add",
|
|
9287
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9288
|
+
submodule: "collection",
|
|
9289
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9290
|
+
packageName: PACKAGE_NAME,
|
|
9291
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9292
|
+
inputValue,
|
|
9293
|
+
isPreAppStart: false,
|
|
9294
|
+
stopRecordingChildSpans: true
|
|
9295
|
+
}, (spanInfo) => {
|
|
9296
|
+
return self._handleReplayCollectionAdd(spanInfo, inputValue, this);
|
|
9297
|
+
});
|
|
9298
|
+
}
|
|
9299
|
+
});
|
|
9300
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9301
|
+
originalFunctionCall: () => originalAdd.call(this, data),
|
|
9302
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9303
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalAdd.call(this, data), {
|
|
9304
|
+
name: "firestore.collection.add",
|
|
9305
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9306
|
+
submodule: "collection",
|
|
9307
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9308
|
+
packageName: PACKAGE_NAME,
|
|
9309
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9310
|
+
inputValue,
|
|
9311
|
+
isPreAppStart,
|
|
9312
|
+
stopRecordingChildSpans: true
|
|
9313
|
+
}, (spanInfo) => {
|
|
9314
|
+
return self._handleRecordCollectionAdd(spanInfo, originalAdd, this, data);
|
|
9315
|
+
});
|
|
9316
|
+
},
|
|
9317
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9318
|
+
});
|
|
9319
|
+
else return originalAdd.call(this, data);
|
|
9320
|
+
};
|
|
9321
|
+
};
|
|
7846
9322
|
}
|
|
7847
|
-
|
|
7848
|
-
|
|
9323
|
+
async _handleRecordCollectionAdd(spanInfo, originalAdd, context$4, data) {
|
|
9324
|
+
const docRef = await originalAdd.call(context$4, data);
|
|
9325
|
+
const result = {
|
|
9326
|
+
id: docRef.id,
|
|
9327
|
+
path: docRef.path
|
|
9328
|
+
};
|
|
9329
|
+
try {
|
|
9330
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: result });
|
|
9331
|
+
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
9332
|
+
} catch {
|
|
9333
|
+
logger.error(`[FirestoreInstrumentation] Error updating span attributes for collection.add`);
|
|
9334
|
+
}
|
|
9335
|
+
return docRef;
|
|
7849
9336
|
}
|
|
7850
|
-
async
|
|
7851
|
-
logger.debug(`[
|
|
9337
|
+
async _handleReplayCollectionAdd(spanInfo, inputValue, collectionRef) {
|
|
9338
|
+
logger.debug(`[FirestoreInstrumentation] Replaying collection.add`);
|
|
7852
9339
|
const mockData = await findMockResponseAsync({
|
|
7853
9340
|
mockRequestData: {
|
|
7854
9341
|
traceId: spanInfo.traceId,
|
|
7855
9342
|
spanId: spanInfo.spanId,
|
|
7856
|
-
name: "
|
|
7857
|
-
inputValue,
|
|
7858
|
-
packageName:
|
|
9343
|
+
name: "firestore.collection.add",
|
|
9344
|
+
inputValue: createMockInputValue(inputValue),
|
|
9345
|
+
packageName: PACKAGE_NAME,
|
|
7859
9346
|
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
7860
|
-
submoduleName: "
|
|
7861
|
-
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
7862
|
-
stackTrace
|
|
9347
|
+
submoduleName: "collection",
|
|
9348
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
7863
9349
|
},
|
|
7864
9350
|
tuskDrift: this.tuskDrift
|
|
7865
9351
|
});
|
|
7866
9352
|
if (!mockData) {
|
|
7867
|
-
logger.warn(`[
|
|
7868
|
-
|
|
7869
|
-
SpanUtils.endSpan(spanInfo.span, {
|
|
7870
|
-
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
7871
|
-
message: "No mock data found"
|
|
7872
|
-
});
|
|
7873
|
-
return;
|
|
9353
|
+
logger.warn(`[FirestoreInstrumentation] No mock data found for collection.add: ${inputValue.path}`);
|
|
9354
|
+
throw new Error(`[FirestoreInstrumentation] No matching mock found for collection.add`);
|
|
7874
9355
|
}
|
|
7875
|
-
const
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
status = {
|
|
7880
|
-
code: errorStatus.code,
|
|
7881
|
-
details: errorStatus.details,
|
|
7882
|
-
metadata: deserializeGrpcMetadata(MetadataConstructor, errorStatus.metadata)
|
|
7883
|
-
};
|
|
7884
|
-
const errorObj = Object.assign(new Error(error.message), {
|
|
7885
|
-
name: error.name,
|
|
7886
|
-
stack: error.stack,
|
|
7887
|
-
...status
|
|
7888
|
-
});
|
|
7889
|
-
callback(errorObj);
|
|
7890
|
-
} else {
|
|
7891
|
-
const { body, status: successStatus, bufferMap, jsonableStringMap } = mockResult;
|
|
7892
|
-
const bufferMapToUse = bufferMap || {};
|
|
7893
|
-
const jsonableStringMapToUse = jsonableStringMap || {};
|
|
7894
|
-
status = {
|
|
7895
|
-
code: successStatus.code,
|
|
7896
|
-
details: successStatus.details,
|
|
7897
|
-
metadata: deserializeGrpcMetadata(MetadataConstructor, successStatus.metadata)
|
|
7898
|
-
};
|
|
7899
|
-
const realResponse = deserializeGrpcPayload(body, bufferMapToUse, jsonableStringMapToUse);
|
|
7900
|
-
callback(null, realResponse);
|
|
9356
|
+
const recordedId = mockData.result.id;
|
|
9357
|
+
if (!this.originalCollectionDocFn) {
|
|
9358
|
+
logger.error(`[FirestoreInstrumentation] Original doc function not available`);
|
|
9359
|
+
return Promise.reject(/* @__PURE__ */ new Error("Original doc function not available"));
|
|
7901
9360
|
}
|
|
7902
|
-
|
|
7903
|
-
cancel() {},
|
|
7904
|
-
getPeer: () => "0.0.0.0:0000",
|
|
7905
|
-
call: void 0
|
|
7906
|
-
});
|
|
7907
|
-
process.nextTick(() => {
|
|
7908
|
-
if (mockResult.metadata) emitter.emit("metadata", deserializeGrpcMetadata(MetadataConstructor, mockResult.metadata));
|
|
7909
|
-
emitter.emit("status", status);
|
|
7910
|
-
});
|
|
7911
|
-
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: mockResult });
|
|
7912
|
-
SpanUtils.endSpan(spanInfo.span, { code: mockResult.error ? __opentelemetry_api.SpanStatusCode.ERROR : __opentelemetry_api.SpanStatusCode.OK });
|
|
7913
|
-
return emitter;
|
|
9361
|
+
return this.originalCollectionDocFn.call(collectionRef, recordedId);
|
|
7914
9362
|
}
|
|
7915
|
-
|
|
9363
|
+
_getCollectionDocPatchFn() {
|
|
7916
9364
|
const self = this;
|
|
7917
|
-
return (
|
|
7918
|
-
return function
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
9365
|
+
return (originalDoc) => {
|
|
9366
|
+
return function(documentPath) {
|
|
9367
|
+
const collectionPath = this.path;
|
|
9368
|
+
const inputValue = {
|
|
9369
|
+
operation: "collection.doc",
|
|
9370
|
+
path: collectionPath,
|
|
9371
|
+
documentId: documentPath
|
|
9372
|
+
};
|
|
9373
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9374
|
+
noOpRequestHandler: () => {
|
|
9375
|
+
return originalDoc.call(this, "");
|
|
9376
|
+
},
|
|
9377
|
+
isServerRequest: false,
|
|
9378
|
+
replayModeHandler: () => {
|
|
9379
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => documentPath ? originalDoc.call(this, documentPath) : originalDoc.call(this), {
|
|
9380
|
+
name: "firestore.collection.doc",
|
|
9381
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9382
|
+
submodule: "collection",
|
|
9383
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9384
|
+
packageName: PACKAGE_NAME,
|
|
9385
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9386
|
+
inputValue,
|
|
9387
|
+
isPreAppStart: false,
|
|
9388
|
+
stopRecordingChildSpans: true
|
|
9389
|
+
}, (spanInfo) => {
|
|
9390
|
+
const mockData = findMockResponseSync({
|
|
9391
|
+
mockRequestData: {
|
|
9392
|
+
traceId: spanInfo.traceId,
|
|
9393
|
+
spanId: spanInfo.spanId,
|
|
9394
|
+
name: "firestore.collection.doc",
|
|
9395
|
+
inputValue: createMockInputValue(inputValue),
|
|
9396
|
+
packageName: PACKAGE_NAME,
|
|
9397
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9398
|
+
submoduleName: "collection",
|
|
9399
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
9400
|
+
},
|
|
9401
|
+
tuskDrift: self.tuskDrift
|
|
9402
|
+
});
|
|
9403
|
+
if (!mockData) {
|
|
9404
|
+
logger.warn(`[FirestoreInstrumentation] No mock data found for collection.doc: ${collectionPath}`);
|
|
9405
|
+
throw new Error(`[FirestoreInstrumentation] No matching mock found for collection.doc`);
|
|
9406
|
+
}
|
|
9407
|
+
const recordedId = mockData.result.id;
|
|
9408
|
+
logger.debug(`[FirestoreInstrumentation] replaying doc call with recorded id: ${recordedId}`);
|
|
9409
|
+
const docRef = originalDoc.call(this, recordedId);
|
|
9410
|
+
logger.debug(`[FirestoreInstrumentation] doc ref, id`, docRef, recordedId);
|
|
9411
|
+
return docRef;
|
|
9412
|
+
});
|
|
9413
|
+
}
|
|
9414
|
+
});
|
|
9415
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9416
|
+
originalFunctionCall: () => documentPath ? originalDoc.call(this, documentPath) : originalDoc.call(this),
|
|
9417
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9418
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => documentPath ? originalDoc.call(this, documentPath) : originalDoc.call(this), {
|
|
9419
|
+
name: "firestore.collection.doc",
|
|
9420
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9421
|
+
submodule: "collection",
|
|
9422
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9423
|
+
packageName: PACKAGE_NAME,
|
|
9424
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9425
|
+
inputValue,
|
|
9426
|
+
isPreAppStart,
|
|
9427
|
+
stopRecordingChildSpans: true
|
|
9428
|
+
}, (spanInfo) => {
|
|
9429
|
+
const docRef = documentPath ? originalDoc.call(this, documentPath) : originalDoc.call(this);
|
|
9430
|
+
const result = {
|
|
9431
|
+
id: docRef.id,
|
|
9432
|
+
path: docRef.path
|
|
9433
|
+
};
|
|
9434
|
+
try {
|
|
9435
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: result });
|
|
9436
|
+
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
9437
|
+
} catch {
|
|
9438
|
+
logger.error(`[FirestoreInstrumentation] Error updating span attributes for collection.doc`);
|
|
9439
|
+
}
|
|
9440
|
+
return docRef;
|
|
9441
|
+
});
|
|
9442
|
+
},
|
|
9443
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9444
|
+
});
|
|
9445
|
+
else return documentPath ? originalDoc.call(this, documentPath) : originalDoc.call(this);
|
|
7923
9446
|
};
|
|
7924
9447
|
};
|
|
7925
9448
|
}
|
|
7926
|
-
|
|
9449
|
+
_getQueryGetPatchFn() {
|
|
7927
9450
|
const self = this;
|
|
7928
|
-
return (
|
|
7929
|
-
return function
|
|
7930
|
-
|
|
7931
|
-
|
|
9451
|
+
return (originalGet) => {
|
|
9452
|
+
return function() {
|
|
9453
|
+
const inputValue = {
|
|
9454
|
+
operation: "query.get",
|
|
9455
|
+
path: this._queryOptions?.parentPath?.formattedName || "unknown"
|
|
9456
|
+
};
|
|
9457
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9458
|
+
noOpRequestHandler: () => {
|
|
9459
|
+
return new TdFirestoreQueryMock({
|
|
9460
|
+
size: 0,
|
|
9461
|
+
empty: true,
|
|
9462
|
+
docs: []
|
|
9463
|
+
});
|
|
9464
|
+
},
|
|
9465
|
+
isServerRequest: false,
|
|
9466
|
+
replayModeHandler: () => {
|
|
9467
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.call(this), {
|
|
9468
|
+
name: "firestore.query.get",
|
|
9469
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9470
|
+
submodule: "query",
|
|
9471
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9472
|
+
packageName: PACKAGE_NAME,
|
|
9473
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9474
|
+
inputValue,
|
|
9475
|
+
isPreAppStart: false,
|
|
9476
|
+
stopRecordingChildSpans: true
|
|
9477
|
+
}, (spanInfo) => {
|
|
9478
|
+
return self._handleReplayQueryGet(spanInfo, inputValue);
|
|
9479
|
+
});
|
|
9480
|
+
}
|
|
9481
|
+
});
|
|
9482
|
+
else if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
|
|
9483
|
+
originalFunctionCall: () => originalGet.call(this),
|
|
9484
|
+
recordModeHandler: ({ isPreAppStart }) => {
|
|
9485
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.call(this), {
|
|
9486
|
+
name: "firestore.query.get",
|
|
9487
|
+
kind: __opentelemetry_api.SpanKind.CLIENT,
|
|
9488
|
+
submodule: "query",
|
|
9489
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.FIRESTORE,
|
|
9490
|
+
packageName: PACKAGE_NAME,
|
|
9491
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
9492
|
+
inputValue,
|
|
9493
|
+
isPreAppStart,
|
|
9494
|
+
stopRecordingChildSpans: true
|
|
9495
|
+
}, (spanInfo) => {
|
|
9496
|
+
return self._handleRecordQueryGet(spanInfo, originalGet, this);
|
|
9497
|
+
});
|
|
9498
|
+
},
|
|
9499
|
+
spanKind: __opentelemetry_api.SpanKind.CLIENT
|
|
9500
|
+
});
|
|
9501
|
+
else return originalGet.call(this);
|
|
7932
9502
|
};
|
|
7933
9503
|
};
|
|
7934
9504
|
}
|
|
7935
|
-
|
|
7936
|
-
const
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
9505
|
+
async _handleRecordQueryGet(spanInfo, originalGet, context$4) {
|
|
9506
|
+
const querySnapshot = await originalGet.call(context$4);
|
|
9507
|
+
const queryResult = {
|
|
9508
|
+
docs: querySnapshot.docs.map((doc) => ({
|
|
9509
|
+
id: doc.id,
|
|
9510
|
+
path: doc.ref.path,
|
|
9511
|
+
exists: doc.exists,
|
|
9512
|
+
data: doc.exists ? doc.data() : void 0,
|
|
9513
|
+
createTime: doc.createTime ? {
|
|
9514
|
+
seconds: doc.createTime.seconds,
|
|
9515
|
+
nanoseconds: doc.createTime.nanoseconds
|
|
9516
|
+
} : void 0,
|
|
9517
|
+
updateTime: doc.updateTime ? {
|
|
9518
|
+
seconds: doc.updateTime.seconds,
|
|
9519
|
+
nanoseconds: doc.updateTime.nanoseconds
|
|
9520
|
+
} : void 0,
|
|
9521
|
+
readTime: doc.readTime ? {
|
|
9522
|
+
seconds: doc.readTime.seconds,
|
|
9523
|
+
nanoseconds: doc.readTime.nanoseconds
|
|
9524
|
+
} : void 0
|
|
9525
|
+
})),
|
|
9526
|
+
size: querySnapshot.size,
|
|
9527
|
+
empty: querySnapshot.empty,
|
|
9528
|
+
readTime: querySnapshot.readTime ? {
|
|
9529
|
+
seconds: querySnapshot.readTime.seconds,
|
|
9530
|
+
nanoseconds: querySnapshot.readTime.nanoseconds
|
|
9531
|
+
} : void 0
|
|
7942
9532
|
};
|
|
9533
|
+
try {
|
|
9534
|
+
SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: queryResult });
|
|
9535
|
+
SpanUtils.endSpan(spanInfo.span, { code: __opentelemetry_api.SpanStatusCode.OK });
|
|
9536
|
+
} catch {
|
|
9537
|
+
logger.error(`[FirestoreInstrumentation] Error updating span attributes for query.get`);
|
|
9538
|
+
}
|
|
9539
|
+
return querySnapshot;
|
|
9540
|
+
}
|
|
9541
|
+
async _handleReplayQueryGet(spanInfo, inputValue) {
|
|
9542
|
+
logger.debug(`[FirestoreInstrumentation] Replaying query.get`);
|
|
9543
|
+
const mockData = await findMockResponseAsync({
|
|
9544
|
+
mockRequestData: {
|
|
9545
|
+
traceId: spanInfo.traceId,
|
|
9546
|
+
spanId: spanInfo.spanId,
|
|
9547
|
+
name: "firestore.query.get",
|
|
9548
|
+
inputValue: createMockInputValue(inputValue),
|
|
9549
|
+
packageName: PACKAGE_NAME,
|
|
9550
|
+
instrumentationName: this.INSTRUMENTATION_NAME,
|
|
9551
|
+
submoduleName: "query",
|
|
9552
|
+
kind: __opentelemetry_api.SpanKind.CLIENT
|
|
9553
|
+
},
|
|
9554
|
+
tuskDrift: this.tuskDrift
|
|
9555
|
+
});
|
|
9556
|
+
if (!mockData) {
|
|
9557
|
+
logger.warn(`[FirestoreInstrumentation] No mock data found for query.get: ${inputValue.path}`);
|
|
9558
|
+
throw new Error(`[FirestoreInstrumentation] No matching mock found for query.get`);
|
|
9559
|
+
}
|
|
9560
|
+
const queryResult = mockData.result;
|
|
9561
|
+
return new TdFirestoreQueryMock(queryResult);
|
|
7943
9562
|
}
|
|
7944
9563
|
_wrap(target, propertyName, wrapper) {
|
|
7945
|
-
|
|
9564
|
+
if (!target || typeof target[propertyName] !== "function") {
|
|
9565
|
+
logger.warn(`[FirestoreInstrumentation] Cannot wrap ${propertyName}: not a function or target is undefined`);
|
|
9566
|
+
return;
|
|
9567
|
+
}
|
|
9568
|
+
const original = target[propertyName];
|
|
9569
|
+
target[propertyName] = wrapper(original);
|
|
7946
9570
|
}
|
|
7947
9571
|
};
|
|
7948
|
-
GrpcInstrumentation.metadataStore = /* @__PURE__ */ new Map();
|
|
7949
9572
|
|
|
7950
9573
|
//#endregion
|
|
7951
9574
|
//#region src/instrumentation/libraries/nextjs/Instrumentation.ts
|
|
@@ -8005,58 +9628,64 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
|
|
|
8005
9628
|
const self = this;
|
|
8006
9629
|
return (originalHandleRequest) => {
|
|
8007
9630
|
return async function(req, res, parsedUrl) {
|
|
9631
|
+
if (self.mode === TuskDriftMode.RECORD) {
|
|
9632
|
+
if (!shouldSample({
|
|
9633
|
+
samplingRate: self.tuskDrift.getSamplingRate(),
|
|
9634
|
+
isAppReady: self.tuskDrift.isAppReady()
|
|
9635
|
+
})) return originalHandleRequest.call(this, req, res, parsedUrl);
|
|
9636
|
+
}
|
|
8008
9637
|
const method = req.method || "GET";
|
|
8009
9638
|
const url = req.url || "/";
|
|
8010
9639
|
logger.debug(`[NextjsInstrumentation] Intercepted Next.js request: ${method} ${url}`);
|
|
8011
|
-
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
8012
|
-
|
|
8013
|
-
method
|
|
8014
|
-
|
|
8015
|
-
|
|
8016
|
-
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
res,
|
|
8042
|
-
parsedUrl,
|
|
8043
|
-
originalHandleRequest,
|
|
8044
|
-
spanInfo,
|
|
9640
|
+
if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
|
|
9641
|
+
noOpRequestHandler: () => {
|
|
9642
|
+
throw new Error(`[NextjsInstrumentation] Should never call noOpRequestHandler for server requests ${method} ${url}`);
|
|
9643
|
+
},
|
|
9644
|
+
isServerRequest: true,
|
|
9645
|
+
replayModeHandler: () => {
|
|
9646
|
+
const inputValue = {
|
|
9647
|
+
method,
|
|
9648
|
+
url,
|
|
9649
|
+
target: url,
|
|
9650
|
+
headers: self._normalizeHeaders(req.headers || {})
|
|
9651
|
+
};
|
|
9652
|
+
const replayTraceId = self.replayHooks.extractTraceIdFromHeaders(req);
|
|
9653
|
+
if (!replayTraceId) {
|
|
9654
|
+
logger.debug(`[NextjsInstrumentation] No trace ID found, calling original handler`);
|
|
9655
|
+
return originalHandleRequest.call(this, req, res, parsedUrl);
|
|
9656
|
+
}
|
|
9657
|
+
logger.debug(`[NextjsInstrumentation] Setting replay trace id`, replayTraceId);
|
|
9658
|
+
const envVars = self.replayHooks.extractEnvVarsFromHeaders(req);
|
|
9659
|
+
if (envVars) EnvVarTracker.setEnvVars(replayTraceId, envVars);
|
|
9660
|
+
const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
|
|
9661
|
+
if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
|
|
9662
|
+
return __opentelemetry_api.context.with(ctxWithReplayTraceId, () => {
|
|
9663
|
+
return SpanUtils.createAndExecuteSpan(self.mode, () => originalHandleRequest.call(this, req, res, parsedUrl), {
|
|
9664
|
+
name: url,
|
|
9665
|
+
kind: __opentelemetry_api.SpanKind.SERVER,
|
|
9666
|
+
packageName: "nextjs",
|
|
9667
|
+
submodule: method,
|
|
9668
|
+
packageType: __use_tusk_drift_schemas_core_span.PackageType.HTTP,
|
|
9669
|
+
instrumentationName: self.INSTRUMENTATION_NAME,
|
|
8045
9670
|
inputValue,
|
|
8046
|
-
|
|
9671
|
+
inputSchemaMerges: { headers: { matchImportance: 0 } },
|
|
9672
|
+
isPreAppStart: false
|
|
9673
|
+
}, (spanInfo) => {
|
|
9674
|
+
return self._handleNextjsRequestInSpan({
|
|
9675
|
+
req,
|
|
9676
|
+
res,
|
|
9677
|
+
parsedUrl,
|
|
9678
|
+
originalHandleRequest,
|
|
9679
|
+
spanInfo,
|
|
9680
|
+
inputValue,
|
|
9681
|
+
thisContext: this
|
|
9682
|
+
});
|
|
8047
9683
|
});
|
|
8048
9684
|
});
|
|
8049
|
-
}
|
|
8050
|
-
}
|
|
9685
|
+
}
|
|
9686
|
+
});
|
|
8051
9687
|
else if (self.mode === TuskDriftMode.RECORD) {
|
|
8052
9688
|
if (method.toUpperCase() === "OPTIONS" || !!req.headers["access-control-request-method"]) return originalHandleRequest.call(this, req, res, parsedUrl);
|
|
8053
|
-
if (!shouldSample({
|
|
8054
|
-
samplingRate: self.tuskDrift.getSamplingRate(),
|
|
8055
|
-
isAppReady: self.tuskDrift.isAppReady()
|
|
8056
|
-
})) {
|
|
8057
|
-
logger.debug(`[NextjsInstrumentation] Skipping server span due to sampling rate: ${url}`);
|
|
8058
|
-
return originalHandleRequest.call(this, req, res, parsedUrl);
|
|
8059
|
-
}
|
|
8060
9689
|
logger.debug(`[NextjsInstrumentation] Creating server span for ${method} ${url}`);
|
|
8061
9690
|
return handleRecordMode({
|
|
8062
9691
|
originalFunctionCall: () => originalHandleRequest.call(this, req, res, parsedUrl),
|
|
@@ -8135,6 +9764,19 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
|
|
|
8135
9764
|
};
|
|
8136
9765
|
try {
|
|
8137
9766
|
await originalHandleRequest.call(thisContext, req, res, parsedUrl);
|
|
9767
|
+
} catch (error) {
|
|
9768
|
+
logger.error(`[NextjsInstrumentation] Error in Next.js request: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
9769
|
+
try {
|
|
9770
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
9771
|
+
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
9772
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
9773
|
+
});
|
|
9774
|
+
} catch (e) {
|
|
9775
|
+
logger.error(`[NextjsInstrumentation] Error ending span:`, e);
|
|
9776
|
+
}
|
|
9777
|
+
throw error;
|
|
9778
|
+
}
|
|
9779
|
+
try {
|
|
8138
9780
|
if (!capturedStatusCode) {
|
|
8139
9781
|
capturedStatusCode = res.statusCode;
|
|
8140
9782
|
capturedStatusMessage = res.statusMessage;
|
|
@@ -8159,7 +9801,6 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
|
|
|
8159
9801
|
outputValue.bodySize = responseBuffer.length;
|
|
8160
9802
|
} catch (error) {
|
|
8161
9803
|
logger.error(`[NextjsInstrumentation] Error processing response body:`, error);
|
|
8162
|
-
outputValue.bodyProcessingError = error instanceof Error ? error.message : String(error);
|
|
8163
9804
|
}
|
|
8164
9805
|
SpanUtils.addSpanAttributes(spanInfo.span, {
|
|
8165
9806
|
inputValue: completeInputValue,
|
|
@@ -8179,6 +9820,11 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
|
|
|
8179
9820
|
message: `HTTP ${capturedStatusCode}`
|
|
8180
9821
|
} : { code: __opentelemetry_api.SpanStatusCode.OK };
|
|
8181
9822
|
SpanUtils.setStatus(spanInfo.span, status);
|
|
9823
|
+
const decodedType = getDecodedType(outputValue.headers?.["content-type"] || "");
|
|
9824
|
+
if (decodedType && STATIC_ASSET_TYPES.has(decodedType)) {
|
|
9825
|
+
TraceBlockingManager.getInstance().blockTrace(spanInfo.traceId);
|
|
9826
|
+
logger.debug(`[NextjsInstrumentation] Blocking trace ${spanInfo.traceId} because it is an static asset response. Decoded type: ${decodedType}`);
|
|
9827
|
+
}
|
|
8182
9828
|
SpanUtils.endSpan(spanInfo.span);
|
|
8183
9829
|
if (self.mode === TuskDriftMode.REPLAY) try {
|
|
8184
9830
|
const now = OriginalGlobalUtils.getOriginalDate();
|
|
@@ -8236,12 +9882,15 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
|
|
|
8236
9882
|
logger.error("[NextjsInstrumentation] Failed to build/send inbound replay span:", e);
|
|
8237
9883
|
}
|
|
8238
9884
|
} catch (error) {
|
|
8239
|
-
logger.error(`[NextjsInstrumentation] Error in Next.js request: ${error instanceof Error ? error.message :
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
9885
|
+
logger.error(`[NextjsInstrumentation] Error in Next.js request: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
9886
|
+
try {
|
|
9887
|
+
SpanUtils.endSpan(spanInfo.span, {
|
|
9888
|
+
code: __opentelemetry_api.SpanStatusCode.ERROR,
|
|
9889
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
9890
|
+
});
|
|
9891
|
+
} catch (e) {
|
|
9892
|
+
logger.error(`[NextjsInstrumentation] Error ending span:`, e);
|
|
9893
|
+
}
|
|
8245
9894
|
}
|
|
8246
9895
|
}
|
|
8247
9896
|
/**
|
|
@@ -10468,20 +12117,21 @@ var SpanTransformer = class SpanTransformer {
|
|
|
10468
12117
|
const inputData = JSON.parse(inputValueString);
|
|
10469
12118
|
const inputSchemaMergesString = attributes[TdSpanAttributes.INPUT_SCHEMA_MERGES];
|
|
10470
12119
|
const inputSchemaMerges = inputSchemaMergesString ? JSON.parse(inputSchemaMergesString) : void 0;
|
|
10471
|
-
const { schema: inputSchema, decodedValueHash: inputValueHash } = JsonSchemaHelper.generateSchemaAndHash(inputData, inputSchemaMerges);
|
|
12120
|
+
const { schema: inputSchema, decodedValueHash: inputValueHash, decodedSchemaHash: inputSchemaHash } = JsonSchemaHelper.generateSchemaAndHash(inputData, inputSchemaMerges);
|
|
10472
12121
|
let outputData = {};
|
|
10473
12122
|
let outputSchema = {
|
|
10474
12123
|
type: __use_tusk_drift_schemas_core_json_schema.JsonSchemaType.OBJECT,
|
|
10475
12124
|
properties: {}
|
|
10476
12125
|
};
|
|
10477
12126
|
let outputValueHash = "";
|
|
12127
|
+
let outputSchemaHash = "";
|
|
10478
12128
|
if (attributes[TdSpanAttributes.OUTPUT_VALUE]) {
|
|
10479
12129
|
const outputValueString = attributes[TdSpanAttributes.OUTPUT_VALUE];
|
|
10480
12130
|
outputData = JSON.parse(outputValueString);
|
|
10481
12131
|
const outputSchemaMergesString = attributes[TdSpanAttributes.OUTPUT_SCHEMA_MERGES];
|
|
10482
12132
|
const outputSchemaMerges = outputSchemaMergesString ? JSON.parse(outputSchemaMergesString) : void 0;
|
|
10483
|
-
({schema: outputSchema, decodedValueHash: outputValueHash} = JsonSchemaHelper.generateSchemaAndHash(outputData, outputSchemaMerges));
|
|
10484
|
-
} else ({schema: outputSchema, decodedSchemaHash:
|
|
12133
|
+
({schema: outputSchema, decodedValueHash: outputValueHash, decodedSchemaHash: outputSchemaHash} = JsonSchemaHelper.generateSchemaAndHash(outputData, outputSchemaMerges));
|
|
12134
|
+
} else ({schema: outputSchema, decodedValueHash: outputValueHash, decodedSchemaHash: outputSchemaHash} = JsonSchemaHelper.generateSchemaAndHash(outputData));
|
|
10485
12135
|
let metadata = void 0;
|
|
10486
12136
|
if (attributes[TdSpanAttributes.METADATA]) metadata = JSON.parse(attributes[TdSpanAttributes.METADATA]);
|
|
10487
12137
|
let transformMetadata;
|
|
@@ -10505,8 +12155,8 @@ var SpanTransformer = class SpanTransformer {
|
|
|
10505
12155
|
outputValue: outputData,
|
|
10506
12156
|
inputSchema,
|
|
10507
12157
|
outputSchema,
|
|
10508
|
-
inputSchemaHash
|
|
10509
|
-
outputSchemaHash
|
|
12158
|
+
inputSchemaHash,
|
|
12159
|
+
outputSchemaHash,
|
|
10510
12160
|
inputValueHash,
|
|
10511
12161
|
outputValueHash,
|
|
10512
12162
|
kind: span.kind,
|
|
@@ -10749,18 +12399,35 @@ var TdSpanExporter = class {
|
|
|
10749
12399
|
*/
|
|
10750
12400
|
export(spans, resultCallback) {
|
|
10751
12401
|
logger.debug(`TdSpanExporter.export() called with ${spans.length} span(s)`);
|
|
10752
|
-
const
|
|
10753
|
-
|
|
12402
|
+
const traceBlockingManager = TraceBlockingManager.getInstance();
|
|
12403
|
+
const filteredSpansBasedOnLibraryName = spans.filter((span) => {
|
|
12404
|
+
if (span.instrumentationLibrary.name === TD_INSTRUMENTATION_LIBRARY_NAME) return true;
|
|
12405
|
+
return false;
|
|
12406
|
+
});
|
|
12407
|
+
logger.debug(`After filtering based on library name: ${filteredSpansBasedOnLibraryName.length} span(s) remaining`);
|
|
12408
|
+
const MAX_SPAN_SIZE_MB = 1;
|
|
12409
|
+
const MAX_SPAN_SIZE_BYTES = MAX_SPAN_SIZE_MB * 1024 * 1024;
|
|
12410
|
+
const filteredBlockedSpans = filteredSpansBasedOnLibraryName.filter((span) => {
|
|
12411
|
+
const traceId = span.spanContext().traceId;
|
|
12412
|
+
if (traceBlockingManager.isTraceBlocked(traceId)) {
|
|
12413
|
+
logger.debug(`Skipping span '${span.name}' (${span.spanContext().spanId}) - trace ${traceId} is blocked`);
|
|
12414
|
+
return false;
|
|
12415
|
+
}
|
|
12416
|
+
const inputValueString = span.attributes[TdSpanAttributes.INPUT_VALUE] || "";
|
|
12417
|
+
const outputValueString = span.attributes[TdSpanAttributes.OUTPUT_VALUE] || "";
|
|
12418
|
+
const inputSize = Buffer.byteLength(inputValueString, "utf8");
|
|
12419
|
+
const outputSize = Buffer.byteLength(outputValueString, "utf8");
|
|
12420
|
+
const estimatedTotalSize = inputSize + outputSize + 5e4;
|
|
12421
|
+
const estimatedSizeMB = estimatedTotalSize / (1024 * 1024);
|
|
12422
|
+
if (estimatedTotalSize > MAX_SPAN_SIZE_BYTES) {
|
|
12423
|
+
traceBlockingManager.blockTrace(traceId);
|
|
12424
|
+
logger.warn(`Blocking trace ${traceId} - span '${span.name}' (${span.spanContext().spanId}) has estimated size ${estimatedSizeMB.toFixed(2)} MB exceeding limit of ${MAX_SPAN_SIZE_MB} MB. Future spans for this trace will be prevented.`);
|
|
12425
|
+
return false;
|
|
12426
|
+
}
|
|
10754
12427
|
return true;
|
|
10755
12428
|
});
|
|
10756
|
-
logger.debug(`
|
|
10757
|
-
|
|
10758
|
-
try {
|
|
10759
|
-
cleanSpans = filteredSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span));
|
|
10760
|
-
} catch (error) {
|
|
10761
|
-
logger.error("Error transforming spans to CleanSpanData", error);
|
|
10762
|
-
throw error;
|
|
10763
|
-
}
|
|
12429
|
+
logger.debug(`Filtered ${filteredSpansBasedOnLibraryName.length - filteredBlockedSpans.length} blocked/oversized span(s), ${filteredBlockedSpans.length} remaining`);
|
|
12430
|
+
const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span));
|
|
10764
12431
|
if (this.adapters.length === 0) {
|
|
10765
12432
|
logger.debug("No adapters configured");
|
|
10766
12433
|
resultCallback({ code: import_src.ExportResultCode.SUCCESS });
|
|
@@ -10895,15 +12562,12 @@ var ProtobufCommunicator = class {
|
|
|
10895
12562
|
});
|
|
10896
12563
|
}
|
|
10897
12564
|
/**
|
|
10898
|
-
* This function uses a Node.js
|
|
10899
|
-
* The
|
|
10900
|
-
*
|
|
10901
|
-
* Since this function blocks the main thread, there is a perfomance impact for using this. We should use requestMockAsync whenever possilbe and only use this function
|
|
10902
|
-
* for instrumentations that request fetching mocks synchronously.
|
|
12565
|
+
* This function uses a separate Node.js child process to communicate with the CLI over a socket.
|
|
12566
|
+
* The child process creates its own connection and event loop, allowing proper async socket handling.
|
|
12567
|
+
* The parent process blocks synchronously waiting for the child to complete.
|
|
10903
12568
|
*
|
|
10904
|
-
*
|
|
10905
|
-
*
|
|
10906
|
-
* Better approach is replacing nc command with pure Node.js implementation
|
|
12569
|
+
* Since this function blocks the main thread, there is a performance impact. We should use requestMockAsync whenever possible and only use this function
|
|
12570
|
+
* for instrumentations that require fetching mocks synchronously.
|
|
10907
12571
|
*/
|
|
10908
12572
|
requestMockSync(mockRequest) {
|
|
10909
12573
|
const requestId = this.generateRequestId();
|
|
@@ -10926,10 +12590,15 @@ var ProtobufCommunicator = class {
|
|
|
10926
12590
|
getMockRequest: protoMockRequest
|
|
10927
12591
|
}
|
|
10928
12592
|
});
|
|
12593
|
+
logger.debug("Sending protobuf request to CLI (sync)", {
|
|
12594
|
+
outboundSpan: mockRequest.outboundSpan,
|
|
12595
|
+
testId: mockRequest.testId
|
|
12596
|
+
});
|
|
10929
12597
|
const messageBytes = __use_tusk_drift_schemas_core_communication.SDKMessage.toBinary(sdkMessage);
|
|
10930
12598
|
const tempDir = os.default.tmpdir();
|
|
10931
|
-
const requestFile = path.default.join(tempDir, `tusk-request-${requestId}.bin`);
|
|
10932
|
-
const responseFile = path.default.join(tempDir, `tusk-response-${requestId}.bin`);
|
|
12599
|
+
const requestFile = path.default.join(tempDir, `tusk-sync-request-${requestId}.bin`);
|
|
12600
|
+
const responseFile = path.default.join(tempDir, `tusk-sync-response-${requestId}.bin`);
|
|
12601
|
+
const scriptFile = path.default.join(tempDir, `tusk-sync-script-${requestId}.js`);
|
|
10933
12602
|
try {
|
|
10934
12603
|
const lengthBuffer = Buffer.allocUnsafe(4);
|
|
10935
12604
|
lengthBuffer.writeUInt32BE(messageBytes.length, 0);
|
|
@@ -10938,19 +12607,112 @@ var ProtobufCommunicator = class {
|
|
|
10938
12607
|
const mockSocket = OriginalGlobalUtils.getOriginalProcessEnvVar("TUSK_MOCK_SOCKET");
|
|
10939
12608
|
const mockHost = OriginalGlobalUtils.getOriginalProcessEnvVar("TUSK_MOCK_HOST");
|
|
10940
12609
|
const mockPort = OriginalGlobalUtils.getOriginalProcessEnvVar("TUSK_MOCK_PORT");
|
|
10941
|
-
let
|
|
10942
|
-
if (mockSocket) {
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
}
|
|
10946
|
-
else {
|
|
10947
|
-
|
|
10948
|
-
|
|
10949
|
-
|
|
10950
|
-
}
|
|
12610
|
+
let connectionConfig;
|
|
12611
|
+
if (mockSocket) connectionConfig = {
|
|
12612
|
+
type: "unix",
|
|
12613
|
+
path: mockSocket
|
|
12614
|
+
};
|
|
12615
|
+
else if (mockHost && mockPort) connectionConfig = {
|
|
12616
|
+
type: "tcp",
|
|
12617
|
+
host: mockHost,
|
|
12618
|
+
port: parseInt(mockPort, 10)
|
|
12619
|
+
};
|
|
12620
|
+
else connectionConfig = {
|
|
12621
|
+
type: "unix",
|
|
12622
|
+
path: path.default.join(os.default.tmpdir(), "tusk-connect.sock")
|
|
12623
|
+
};
|
|
12624
|
+
fs.default.writeFileSync(scriptFile, `
|
|
12625
|
+
const net = require('net');
|
|
12626
|
+
const fs = require('fs');
|
|
12627
|
+
|
|
12628
|
+
const requestFile = process.argv[2];
|
|
12629
|
+
const responseFile = process.argv[3];
|
|
12630
|
+
const config = JSON.parse(process.argv[4]);
|
|
12631
|
+
|
|
12632
|
+
let responseReceived = false;
|
|
12633
|
+
let timeoutId;
|
|
12634
|
+
|
|
12635
|
+
function cleanup(exitCode) {
|
|
12636
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
12637
|
+
process.exit(exitCode);
|
|
12638
|
+
}
|
|
12639
|
+
|
|
12640
|
+
try {
|
|
12641
|
+
// Read the request data
|
|
12642
|
+
const requestData = fs.readFileSync(requestFile);
|
|
12643
|
+
|
|
12644
|
+
// Create connection based on config
|
|
12645
|
+
const client = config.type === 'unix'
|
|
12646
|
+
? net.createConnection({ path: config.path })
|
|
12647
|
+
: net.createConnection({ host: config.host, port: config.port });
|
|
12648
|
+
|
|
12649
|
+
const incomingChunks = [];
|
|
12650
|
+
let incomingBuffer = Buffer.alloc(0);
|
|
12651
|
+
|
|
12652
|
+
// Set timeout
|
|
12653
|
+
timeoutId = setTimeout(() => {
|
|
12654
|
+
if (!responseReceived) {
|
|
12655
|
+
console.error('Timeout waiting for response');
|
|
12656
|
+
client.destroy();
|
|
12657
|
+
cleanup(1);
|
|
12658
|
+
}
|
|
12659
|
+
}, 10000);
|
|
12660
|
+
|
|
12661
|
+
client.on('connect', () => {
|
|
12662
|
+
// Send the request
|
|
12663
|
+
client.write(requestData);
|
|
12664
|
+
});
|
|
12665
|
+
|
|
12666
|
+
client.on('data', (data) => {
|
|
12667
|
+
incomingBuffer = Buffer.concat([incomingBuffer, data]);
|
|
12668
|
+
|
|
12669
|
+
// Try to parse complete message (4 byte length prefix + message)
|
|
12670
|
+
while (incomingBuffer.length >= 4) {
|
|
12671
|
+
const messageLength = incomingBuffer.readUInt32BE(0);
|
|
12672
|
+
|
|
12673
|
+
if (incomingBuffer.length < 4 + messageLength) {
|
|
12674
|
+
// Incomplete message, wait for more data
|
|
12675
|
+
break;
|
|
12676
|
+
}
|
|
12677
|
+
|
|
12678
|
+
// We have a complete message
|
|
12679
|
+
const messageData = incomingBuffer.slice(4, 4 + messageLength);
|
|
12680
|
+
incomingBuffer = incomingBuffer.slice(4 + messageLength);
|
|
12681
|
+
|
|
12682
|
+
// Write the complete response (including length prefix)
|
|
12683
|
+
const lengthPrefix = Buffer.allocUnsafe(4);
|
|
12684
|
+
lengthPrefix.writeUInt32BE(messageLength, 0);
|
|
12685
|
+
fs.writeFileSync(responseFile, Buffer.concat([lengthPrefix, messageData]));
|
|
12686
|
+
|
|
12687
|
+
responseReceived = true;
|
|
12688
|
+
client.destroy();
|
|
12689
|
+
cleanup(0);
|
|
12690
|
+
break;
|
|
12691
|
+
}
|
|
12692
|
+
});
|
|
12693
|
+
|
|
12694
|
+
client.on('error', (err) => {
|
|
12695
|
+
if (!responseReceived) {
|
|
12696
|
+
console.error('Connection error:', err.message);
|
|
12697
|
+
cleanup(1);
|
|
12698
|
+
}
|
|
12699
|
+
});
|
|
12700
|
+
|
|
12701
|
+
client.on('close', () => {
|
|
12702
|
+
if (!responseReceived) {
|
|
12703
|
+
console.error('Connection closed without response');
|
|
12704
|
+
cleanup(1);
|
|
12705
|
+
}
|
|
12706
|
+
});
|
|
12707
|
+
|
|
12708
|
+
} catch (err) {
|
|
12709
|
+
console.error('Script error:', err.message);
|
|
12710
|
+
cleanup(1);
|
|
12711
|
+
}
|
|
12712
|
+
`);
|
|
10951
12713
|
try {
|
|
10952
|
-
(0, child_process.execSync)(
|
|
10953
|
-
timeout:
|
|
12714
|
+
(0, child_process.execSync)(`node "${scriptFile}" "${requestFile}" "${responseFile}" '${JSON.stringify(connectionConfig)}'`, {
|
|
12715
|
+
timeout: 12e3,
|
|
10954
12716
|
stdio: "pipe"
|
|
10955
12717
|
});
|
|
10956
12718
|
const responseBuffer = fs.default.readFileSync(responseFile);
|
|
@@ -10975,22 +12737,27 @@ var ProtobufCommunicator = class {
|
|
|
10975
12737
|
error: mockResponse.error || "Mock not found"
|
|
10976
12738
|
};
|
|
10977
12739
|
} catch (error) {
|
|
10978
|
-
logger.error("[ProtobufCommunicator] error
|
|
12740
|
+
logger.error("[ProtobufCommunicator] error in sync request child process:", error);
|
|
10979
12741
|
throw error;
|
|
10980
12742
|
}
|
|
10981
12743
|
} catch (error) {
|
|
10982
12744
|
throw new Error(`Sync request failed: ${error.message}`);
|
|
10983
12745
|
} finally {
|
|
10984
12746
|
try {
|
|
10985
|
-
fs.default.unlinkSync(requestFile);
|
|
12747
|
+
if (fs.default.existsSync(requestFile)) fs.default.unlinkSync(requestFile);
|
|
10986
12748
|
} catch (e) {
|
|
10987
12749
|
logger.error("[ProtobufCommunicator] error cleaning up request file:", e);
|
|
10988
12750
|
}
|
|
10989
12751
|
try {
|
|
10990
|
-
fs.default.unlinkSync(responseFile);
|
|
12752
|
+
if (fs.default.existsSync(responseFile)) fs.default.unlinkSync(responseFile);
|
|
10991
12753
|
} catch (e) {
|
|
10992
12754
|
logger.error("[ProtobufCommunicator] error cleaning up response file:", e);
|
|
10993
12755
|
}
|
|
12756
|
+
try {
|
|
12757
|
+
if (fs.default.existsSync(scriptFile)) fs.default.unlinkSync(scriptFile);
|
|
12758
|
+
} catch (e) {
|
|
12759
|
+
logger.error("[ProtobufCommunicator] error cleaning up script file:", e);
|
|
12760
|
+
}
|
|
10994
12761
|
}
|
|
10995
12762
|
}
|
|
10996
12763
|
async sendProtobufMessage(message) {
|
|
@@ -11158,7 +12925,8 @@ const TuskDriftInstrumentationModuleNames = [
|
|
|
11158
12925
|
"jwks-rsa",
|
|
11159
12926
|
"mysql2",
|
|
11160
12927
|
"ioredis",
|
|
11161
|
-
"@grpc/grpc-js"
|
|
12928
|
+
"@grpc/grpc-js",
|
|
12929
|
+
"@google-cloud/firestore"
|
|
11162
12930
|
];
|
|
11163
12931
|
|
|
11164
12932
|
//#endregion
|
|
@@ -11280,6 +13048,10 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11280
13048
|
enabled: true,
|
|
11281
13049
|
mode: this.mode
|
|
11282
13050
|
});
|
|
13051
|
+
new FirestoreInstrumentation({
|
|
13052
|
+
enabled: true,
|
|
13053
|
+
mode: this.mode
|
|
13054
|
+
});
|
|
11283
13055
|
new NextjsInstrumentation({
|
|
11284
13056
|
enabled: true,
|
|
11285
13057
|
mode: this.mode
|
|
@@ -11299,14 +13071,15 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11299
13071
|
sdkVersion: SDK_VERSION,
|
|
11300
13072
|
sdkInstanceId: this.generateSdkInstanceId()
|
|
11301
13073
|
});
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
13074
|
+
new __opentelemetry_sdk_trace_node.NodeTracerProvider({
|
|
13075
|
+
resource: new __opentelemetry_resources.Resource({ [__opentelemetry_semantic_conventions.ATTR_SERVICE_NAME]: serviceName }),
|
|
13076
|
+
spanProcessors: [new __opentelemetry_sdk_trace_node.BatchSpanProcessor(this.spanExporter, {
|
|
13077
|
+
maxQueueSize: 2048,
|
|
13078
|
+
maxExportBatchSize: 512,
|
|
13079
|
+
scheduledDelayMillis: 2e3,
|
|
13080
|
+
exportTimeoutMillis: 3e4
|
|
13081
|
+
})]
|
|
13082
|
+
}).register();
|
|
11310
13083
|
logger.debug(`OpenTelemetry tracing initialized`);
|
|
11311
13084
|
}
|
|
11312
13085
|
generateSdkInstanceId() {
|
|
@@ -11452,6 +13225,10 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11452
13225
|
}
|
|
11453
13226
|
}
|
|
11454
13227
|
requestMockSync(mockRequest) {
|
|
13228
|
+
if (!this.isConnectedWithCLI) {
|
|
13229
|
+
logger.error("Requesting sync mock but CLI is not ready yet");
|
|
13230
|
+
throw new Error("Requesting sync mock but CLI is not ready yet");
|
|
13231
|
+
}
|
|
11455
13232
|
const mockRequestCore = this.createMockRequestCore(mockRequest);
|
|
11456
13233
|
if (mockRequestCore) return mockRequestCore;
|
|
11457
13234
|
return this.requestMockFromCLISync(mockRequest);
|
|
@@ -11499,7 +13276,7 @@ var TuskDriftCore = class TuskDriftCore {
|
|
|
11499
13276
|
return this.initParams;
|
|
11500
13277
|
}
|
|
11501
13278
|
getTracer() {
|
|
11502
|
-
return __opentelemetry_api.trace.getTracer(
|
|
13279
|
+
return __opentelemetry_api.trace.getTracer(TD_INSTRUMENTATION_LIBRARY_NAME);
|
|
11503
13280
|
}
|
|
11504
13281
|
};
|
|
11505
13282
|
var TuskDriftSDK = class {
|