@use-tusk/drift-node-sdk 0.1.18 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4978,31 +4978,31 @@ var require_SamplingResult = /* @__PURE__ */ __commonJS({ "node_modules/@opentel
4978
4978
  var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/span_kind.js": ((exports) => {
4979
4979
  Object.defineProperty(exports, "__esModule", { value: true });
4980
4980
  exports.SpanKind = void 0;
4981
- (function(SpanKind$25) {
4981
+ (function(SpanKind$26) {
4982
4982
  /** Default value. Indicates that the span is used internally. */
4983
- SpanKind$25[SpanKind$25["INTERNAL"] = 0] = "INTERNAL";
4983
+ SpanKind$26[SpanKind$26["INTERNAL"] = 0] = "INTERNAL";
4984
4984
  /**
4985
4985
  * Indicates that the span covers server-side handling of an RPC or other
4986
4986
  * remote request.
4987
4987
  */
4988
- SpanKind$25[SpanKind$25["SERVER"] = 1] = "SERVER";
4988
+ SpanKind$26[SpanKind$26["SERVER"] = 1] = "SERVER";
4989
4989
  /**
4990
4990
  * Indicates that the span covers the client-side wrapper around an RPC or
4991
4991
  * other remote request.
4992
4992
  */
4993
- SpanKind$25[SpanKind$25["CLIENT"] = 2] = "CLIENT";
4993
+ SpanKind$26[SpanKind$26["CLIENT"] = 2] = "CLIENT";
4994
4994
  /**
4995
4995
  * Indicates that the span describes producer sending a message to a
4996
4996
  * broker. Unlike client and server, there is no direct critical path latency
4997
4997
  * relationship between producer and consumer spans.
4998
4998
  */
4999
- SpanKind$25[SpanKind$25["PRODUCER"] = 3] = "PRODUCER";
4999
+ SpanKind$26[SpanKind$26["PRODUCER"] = 3] = "PRODUCER";
5000
5000
  /**
5001
5001
  * Indicates that the span describes consumer receiving a message from a
5002
5002
  * broker. Unlike client and server, there is no direct critical path latency
5003
5003
  * relationship between producer and consumer spans.
5004
5004
  */
5005
- SpanKind$25[SpanKind$25["CONSUMER"] = 4] = "CONSUMER";
5005
+ SpanKind$26[SpanKind$26["CONSUMER"] = 4] = "CONSUMER";
5006
5006
  })(exports.SpanKind || (exports.SpanKind = {}));
5007
5007
  }) });
5008
5008
 
@@ -5011,20 +5011,20 @@ var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetr
5011
5011
  var require_status = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/status.js": ((exports) => {
5012
5012
  Object.defineProperty(exports, "__esModule", { value: true });
5013
5013
  exports.SpanStatusCode = void 0;
5014
- (function(SpanStatusCode$14) {
5014
+ (function(SpanStatusCode$15) {
5015
5015
  /**
5016
5016
  * The default status.
5017
5017
  */
5018
- SpanStatusCode$14[SpanStatusCode$14["UNSET"] = 0] = "UNSET";
5018
+ SpanStatusCode$15[SpanStatusCode$15["UNSET"] = 0] = "UNSET";
5019
5019
  /**
5020
5020
  * The operation has been validated by an Application developer or
5021
5021
  * Operator to have completed successfully.
5022
5022
  */
5023
- SpanStatusCode$14[SpanStatusCode$14["OK"] = 1] = "OK";
5023
+ SpanStatusCode$15[SpanStatusCode$15["OK"] = 1] = "OK";
5024
5024
  /**
5025
5025
  * The operation contains an error.
5026
5026
  */
5027
- SpanStatusCode$14[SpanStatusCode$14["ERROR"] = 2] = "ERROR";
5027
+ SpanStatusCode$15[SpanStatusCode$15["ERROR"] = 2] = "ERROR";
5028
5028
  })(exports.SpanStatusCode || (exports.SpanStatusCode = {}));
5029
5029
  }) });
5030
5030
 
@@ -5673,7 +5673,7 @@ var require_src$7 = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/ap
5673
5673
 
5674
5674
  //#endregion
5675
5675
  //#region node_modules/@use-tusk/drift-schemas/dist/duration-B3fwb4jB.js
5676
- var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
5676
+ var import_src$35 = /* @__PURE__ */ __toESM(require_src$7(), 1);
5677
5677
  var import_commonjs$9 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
5678
5678
  var Duration$Type = class extends import_commonjs$9.MessageType {
5679
5679
  constructor() {
@@ -6997,11 +6997,11 @@ const Trace = new Trace$Type();
6997
6997
  const toStruct = (obj) => obj ? objectToProtobufStruct(obj) : void 0;
6998
6998
  const mapOtToPb = (k) => {
6999
6999
  switch (k) {
7000
- case import_src$34.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
7001
- case import_src$34.SpanKind.SERVER: return SpanKind$1.SERVER;
7002
- case import_src$34.SpanKind.CLIENT: return SpanKind$1.CLIENT;
7003
- case import_src$34.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
7004
- case import_src$34.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
7000
+ case import_src$35.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
7001
+ case import_src$35.SpanKind.SERVER: return SpanKind$1.SERVER;
7002
+ case import_src$35.SpanKind.CLIENT: return SpanKind$1.CLIENT;
7003
+ case import_src$35.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
7004
+ case import_src$35.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
7005
7005
  default: return SpanKind$1.UNSPECIFIED;
7006
7006
  }
7007
7007
  };
@@ -7405,13 +7405,13 @@ var TdInstrumentationNodeModule = class {
7405
7405
 
7406
7406
  //#endregion
7407
7407
  //#region src/core/types.ts
7408
- var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7408
+ var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7409
7409
  const TD_INSTRUMENTATION_LIBRARY_NAME = "tusk-drift-sdk";
7410
- const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.replayTraceId");
7411
- const SPAN_KIND_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.spanKind");
7412
- const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.isPreAppStart");
7413
- const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.stopRecordingChildSpans");
7414
- const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.callingLibrary");
7410
+ const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.replayTraceId");
7411
+ const SPAN_KIND_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.spanKind");
7412
+ const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.isPreAppStart");
7413
+ const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.stopRecordingChildSpans");
7414
+ const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.callingLibrary");
7415
7415
  let TdSpanAttributes = /* @__PURE__ */ function(TdSpanAttributes$1) {
7416
7416
  /**
7417
7417
  * Presentational information:
@@ -7523,7 +7523,7 @@ TraceBlockingManager.instance = null;
7523
7523
 
7524
7524
  //#endregion
7525
7525
  //#region src/core/tracing/SpanUtils.ts
7526
- var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7526
+ var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7527
7527
  var SpanUtils = class SpanUtils {
7528
7528
  /**
7529
7529
  * Creates a new span and returns span info including trace ID and span ID
@@ -7531,8 +7531,8 @@ var SpanUtils = class SpanUtils {
7531
7531
  static createSpan(options) {
7532
7532
  try {
7533
7533
  const tracer = TuskDriftCore.getInstance().getTracer();
7534
- const parentContext = options.parentContext || import_src$32.context.active();
7535
- const activeSpan = import_src$32.trace.getSpan(parentContext);
7534
+ const parentContext = options.parentContext || import_src$33.context.active();
7535
+ const activeSpan = import_src$33.trace.getSpan(parentContext);
7536
7536
  if (activeSpan) {
7537
7537
  const parentTraceId = activeSpan.spanContext().traceId;
7538
7538
  if (TraceBlockingManager.getInstance().isTraceBlocked(parentTraceId)) {
@@ -7541,11 +7541,11 @@ var SpanUtils = class SpanUtils {
7541
7541
  }
7542
7542
  }
7543
7543
  const span = tracer.startSpan(options.name, {
7544
- kind: options.kind || import_src$32.SpanKind.CLIENT,
7544
+ kind: options.kind || import_src$33.SpanKind.CLIENT,
7545
7545
  attributes: options.attributes || {}
7546
7546
  }, parentContext);
7547
7547
  const spanContext = span.spanContext();
7548
- const newContext = import_src$32.trace.setSpan(parentContext, span).setValue(SPAN_KIND_CONTEXT_KEY, options.kind).setValue(IS_PRE_APP_START_CONTEXT_KEY, options.isPreAppStart);
7548
+ const newContext = import_src$33.trace.setSpan(parentContext, span).setValue(SPAN_KIND_CONTEXT_KEY, options.kind).setValue(IS_PRE_APP_START_CONTEXT_KEY, options.isPreAppStart);
7549
7549
  return {
7550
7550
  traceId: spanContext.traceId,
7551
7551
  spanId: spanContext.spanId,
@@ -7562,7 +7562,7 @@ var SpanUtils = class SpanUtils {
7562
7562
  * Executes a function within a span context
7563
7563
  */
7564
7564
  static withSpan(spanInfo, fn) {
7565
- return import_src$32.context.with(spanInfo.context, fn);
7565
+ return import_src$33.context.with(spanInfo.context, fn);
7566
7566
  }
7567
7567
  /**
7568
7568
  * Execute a function within a properly configured span
@@ -7579,9 +7579,9 @@ var SpanUtils = class SpanUtils {
7579
7579
  * @returns The result of the function execution
7580
7580
  */
7581
7581
  static createAndExecuteSpan(mode, originalFunctionCall, options, fn) {
7582
- const spanContext = import_src$32.trace.getActiveSpan()?.spanContext();
7582
+ const spanContext = import_src$33.trace.getActiveSpan()?.spanContext();
7583
7583
  if (spanContext) {
7584
- if (import_src$32.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
7584
+ if (import_src$33.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
7585
7585
  logger.debug(`[SpanUtils] Stopping recording of child spans for span ${spanContext.spanId}, packageName: ${options.packageName}, instrumentationName: ${options.instrumentationName}`);
7586
7586
  return originalFunctionCall();
7587
7587
  }
@@ -7620,15 +7620,15 @@ var SpanUtils = class SpanUtils {
7620
7620
  */
7621
7621
  static getCurrentSpanInfo() {
7622
7622
  try {
7623
- const activeSpan = import_src$32.trace.getActiveSpan();
7623
+ const activeSpan = import_src$33.trace.getActiveSpan();
7624
7624
  if (!activeSpan) return null;
7625
7625
  const spanContext = activeSpan.spanContext();
7626
7626
  return {
7627
7627
  traceId: spanContext.traceId,
7628
7628
  spanId: spanContext.spanId,
7629
7629
  span: activeSpan,
7630
- context: import_src$32.context.active(),
7631
- isPreAppStart: import_src$32.context.active().getValue(IS_PRE_APP_START_CONTEXT_KEY)
7630
+ context: import_src$33.context.active(),
7631
+ isPreAppStart: import_src$33.context.active().getValue(IS_PRE_APP_START_CONTEXT_KEY)
7632
7632
  };
7633
7633
  } catch (error) {
7634
7634
  logger.error("SpanUtils error getting current span info:", error);
@@ -7692,7 +7692,7 @@ var SpanUtils = class SpanUtils {
7692
7692
  }
7693
7693
  static setCurrentReplayTraceId(replayTraceId) {
7694
7694
  try {
7695
- return import_src$32.context.active().setValue(REPLAY_TRACE_ID_CONTEXT_KEY, replayTraceId);
7695
+ return import_src$33.context.active().setValue(REPLAY_TRACE_ID_CONTEXT_KEY, replayTraceId);
7696
7696
  } catch (error) {
7697
7697
  logger.error("SpanUtils error setting current replay trace id:", error);
7698
7698
  return null;
@@ -7703,7 +7703,7 @@ var SpanUtils = class SpanUtils {
7703
7703
  */
7704
7704
  static getCurrentReplayTraceId() {
7705
7705
  try {
7706
- return import_src$32.context.active().getValue(REPLAY_TRACE_ID_CONTEXT_KEY);
7706
+ return import_src$33.context.active().getValue(REPLAY_TRACE_ID_CONTEXT_KEY);
7707
7707
  } catch (error) {
7708
7708
  logger.error("SpanUtils error getting current replay trace id:", error);
7709
7709
  return null;
@@ -8352,7 +8352,7 @@ function findMockResponseSync({ mockRequestData, tuskDrift, inputValueSchemaMerg
8352
8352
 
8353
8353
  //#endregion
8354
8354
  //#region src/instrumentation/libraries/http/mocks/TdMockClientRequest.ts
8355
- var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8355
+ var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8356
8356
  let ClientRequest;
8357
8357
  /**
8358
8358
  * Mock ClientRequest implementation for Tusk Drift HTTP replay
@@ -8523,7 +8523,7 @@ var TdMockClientRequest = class TdMockClientRequest extends EventEmitter {
8523
8523
  instrumentationName: this.INSTRUMENTATION_NAME,
8524
8524
  submoduleName: rawInputValue.method,
8525
8525
  inputValue,
8526
- kind: import_src$31.SpanKind.CLIENT,
8526
+ kind: import_src$32.SpanKind.CLIENT,
8527
8527
  stackTrace: this.stackTrace
8528
8528
  },
8529
8529
  tuskDrift: this.tuskDrift,
@@ -8693,7 +8693,7 @@ var HttpReplayHooks = class {
8693
8693
 
8694
8694
  //#endregion
8695
8695
  //#region src/instrumentation/core/utils/modeUtils.ts
8696
- var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8696
+ var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8697
8697
  /**
8698
8698
  * Utility function that abstracts the common record mode pattern of checking for current span context
8699
8699
  * and deciding whether to execute record mode logic or just call the original function.
@@ -8714,7 +8714,7 @@ function handleRecordMode({ originalFunctionCall, recordModeHandler, spanKind })
8714
8714
  return originalFunctionCall();
8715
8715
  }
8716
8716
  if (!isAppReady) return recordModeHandler({ isPreAppStart: true });
8717
- if (!currentSpanInfo && spanKind !== import_src$30.SpanKind.SERVER || currentSpanInfo?.isPreAppStart) return originalFunctionCall();
8717
+ if (!currentSpanInfo && spanKind !== import_src$31.SpanKind.SERVER || currentSpanInfo?.isPreAppStart) return originalFunctionCall();
8718
8718
  else return recordModeHandler({ isPreAppStart: false });
8719
8719
  }
8720
8720
  /**
@@ -10194,7 +10194,7 @@ function captureStackTrace(excludeClassNames = []) {
10194
10194
 
10195
10195
  //#endregion
10196
10196
  //#region src/instrumentation/libraries/http/HttpTransformEngine.ts
10197
- var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10197
+ var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10198
10198
  /**
10199
10199
  * Creates an empty HttpClientInputValue object for dropped spans
10200
10200
  */
@@ -10247,7 +10247,7 @@ var HttpTransformEngine = class {
10247
10247
  const testSpan = {
10248
10248
  traceId: "",
10249
10249
  spanId: "",
10250
- kind: import_src$29.SpanKind.SERVER,
10250
+ kind: import_src$30.SpanKind.SERVER,
10251
10251
  protocol: "http",
10252
10252
  inputValue: {
10253
10253
  method,
@@ -10270,7 +10270,7 @@ var HttpTransformEngine = class {
10270
10270
  const testSpan = {
10271
10271
  traceId: "",
10272
10272
  spanId: "",
10273
- kind: import_src$29.SpanKind.CLIENT,
10273
+ kind: import_src$30.SpanKind.CLIENT,
10274
10274
  protocol: inputValue.protocol || "http",
10275
10275
  inputValue: clonedInputValue
10276
10276
  };
@@ -10297,8 +10297,8 @@ var HttpTransformEngine = class {
10297
10297
  const matcherFunction = this.compileMatcher(matcher);
10298
10298
  if (action.type === "drop") return (span) => {
10299
10299
  if (!matcherFunction(span)) return;
10300
- if (span.inputValue) span.inputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10301
- if (span.outputValue) span.outputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientOutputValue() : createEmptyServerOutputValue();
10300
+ if (span.inputValue) span.inputValue = span.kind === import_src$30.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10301
+ if (span.outputValue) span.outputValue = span.kind === import_src$30.SpanKind.CLIENT ? createEmptyClientOutputValue() : createEmptyServerOutputValue();
10302
10302
  return {
10303
10303
  type: "drop",
10304
10304
  field: "entire_span",
@@ -10328,8 +10328,8 @@ var HttpTransformEngine = class {
10328
10328
  }
10329
10329
  compileMatcher(matcher) {
10330
10330
  const checks = [];
10331
- if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$29.SpanKind.CLIENT);
10332
- else if (matcher.direction === "inbound") checks.push((span) => span.kind === import_src$29.SpanKind.SERVER);
10331
+ if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$30.SpanKind.CLIENT);
10332
+ else if (matcher.direction === "inbound") checks.push((span) => span.kind === import_src$30.SpanKind.SERVER);
10333
10333
  if (matcher.method) if (matcher.method.length === 0) {} else {
10334
10334
  const methods = matcher.method.map((method) => method.toUpperCase());
10335
10335
  checks.push((span) => {
@@ -10557,7 +10557,7 @@ var HttpTransformEngine = class {
10557
10557
 
10558
10558
  //#endregion
10559
10559
  //#region src/instrumentation/libraries/http/Instrumentation.ts
10560
- var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10560
+ var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10561
10561
  var HttpInstrumentation = class extends TdInstrumentationBase {
10562
10562
  constructor(config) {
10563
10563
  super("http", config);
@@ -10644,10 +10644,10 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10644
10644
  logger.debug(`[HttpInstrumentation] Setting replay trace id`, replayTraceId);
10645
10645
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
10646
10646
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
10647
- return import_src$28.context.with(ctxWithReplayTraceId, () => {
10647
+ return import_src$29.context.with(ctxWithReplayTraceId, () => {
10648
10648
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10649
10649
  name: `${target}`,
10650
- kind: import_src$28.SpanKind.SERVER,
10650
+ kind: import_src$29.SpanKind.SERVER,
10651
10651
  packageName: spanProtocol,
10652
10652
  submodule: method,
10653
10653
  packageType: PackageType.HTTP,
@@ -10692,7 +10692,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10692
10692
  logger.debug(`[HttpInstrumentation] Http inbound request arriving, inputValue: ${JSON.stringify(inputValue)}`);
10693
10693
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10694
10694
  name: `${target}`,
10695
- kind: import_src$28.SpanKind.SERVER,
10695
+ kind: import_src$29.SpanKind.SERVER,
10696
10696
  packageName: spanProtocol,
10697
10697
  packageType: PackageType.HTTP,
10698
10698
  submodule: method,
@@ -10712,7 +10712,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10712
10712
  });
10713
10713
  });
10714
10714
  },
10715
- spanKind: import_src$28.SpanKind.SERVER
10715
+ spanKind: import_src$29.SpanKind.SERVER
10716
10716
  });
10717
10717
  } else return originalHandler.call(this);
10718
10718
  }
@@ -10729,8 +10729,8 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10729
10729
  _handleInboundRequestInSpan({ req, res, originalHandler, spanInfo, inputValue, schemaMerges, protocol }) {
10730
10730
  const self = this;
10731
10731
  const spanProtocol = this._normalizeProtocol(protocol, "http");
10732
- import_src$28.context.bind(spanInfo.context, req);
10733
- import_src$28.context.bind(spanInfo.context, res);
10732
+ import_src$29.context.bind(spanInfo.context, req);
10733
+ import_src$29.context.bind(spanInfo.context, res);
10734
10734
  let completeInputValue = inputValue;
10735
10735
  this._captureServerRequestBody(req, spanInfo, inputValue, schemaMerges, (updatedInputValue) => {
10736
10736
  completeInputValue = updatedInputValue;
@@ -10768,7 +10768,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10768
10768
  const spanData = {
10769
10769
  traceId: spanInfo.traceId,
10770
10770
  spanId: spanInfo.spanId,
10771
- kind: import_src$28.SpanKind.SERVER,
10771
+ kind: import_src$29.SpanKind.SERVER,
10772
10772
  protocol: spanProtocol,
10773
10773
  inputValue: completeInputValue,
10774
10774
  outputValue
@@ -10786,10 +10786,10 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10786
10786
  },
10787
10787
  ...spanData.transformMetadata && { transformMetadata: spanData.transformMetadata }
10788
10788
  });
10789
- const status = statusCode >= 400 ? {
10790
- code: import_src$28.SpanStatusCode.ERROR,
10789
+ const status = statusCode >= 300 ? {
10790
+ code: import_src$29.SpanStatusCode.ERROR,
10791
10791
  message: `HTTP ${statusCode}`
10792
- } : { code: import_src$28.SpanStatusCode.OK };
10792
+ } : { code: import_src$29.SpanStatusCode.OK };
10793
10793
  SpanUtils.setStatus(spanInfo.span, status);
10794
10794
  const decodedType = getDecodedType(outputValue.headers?.["content-type"] || "");
10795
10795
  if (decodedType && !ACCEPTABLE_CONTENT_TYPES.has(decodedType)) {
@@ -10839,11 +10839,11 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10839
10839
  outputSchemaHash: JsonSchemaHelper.generateDeterministicHash(outputSchema),
10840
10840
  inputValueHash,
10841
10841
  outputValueHash,
10842
- kind: import_src$28.SpanKind.SERVER,
10842
+ kind: import_src$29.SpanKind.SERVER,
10843
10843
  packageType: PackageType.HTTP,
10844
10844
  status: {
10845
- code: statusCode >= 400 ? StatusCode.ERROR : StatusCode.OK,
10846
- message: statusCode >= 400 ? `HTTP ${statusCode}` : ""
10845
+ code: statusCode >= 300 ? StatusCode.ERROR : StatusCode.OK,
10846
+ message: statusCode >= 300 ? `HTTP ${statusCode}` : ""
10847
10847
  },
10848
10848
  timestamp: {
10849
10849
  seconds: Math.floor(now.getTime() / 1e3),
@@ -10868,7 +10868,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10868
10868
  try {
10869
10869
  logger.debug(`[HttpInstrumentation] Server request error: ${error.message} (${SpanUtils.getTraceInfo()})`);
10870
10870
  SpanUtils.endSpan(spanInfo.span, {
10871
- code: import_src$28.SpanStatusCode.ERROR,
10871
+ code: import_src$29.SpanStatusCode.ERROR,
10872
10872
  message: error.message
10873
10873
  });
10874
10874
  } catch (error$1) {
@@ -10879,7 +10879,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10879
10879
  try {
10880
10880
  logger.debug(`[HttpInstrumentation] Server response error: ${error.message} (${SpanUtils.getTraceInfo()})`);
10881
10881
  SpanUtils.endSpan(spanInfo.span, {
10882
- code: import_src$28.SpanStatusCode.ERROR,
10882
+ code: import_src$29.SpanStatusCode.ERROR,
10883
10883
  message: error.message
10884
10884
  });
10885
10885
  } catch (error$1) {
@@ -11084,7 +11084,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11084
11084
  inputValue: completeInputValue
11085
11085
  });
11086
11086
  SpanUtils.endSpan(spanInfo.span, {
11087
- code: import_src$28.SpanStatusCode.ERROR,
11087
+ code: import_src$29.SpanStatusCode.ERROR,
11088
11088
  message: error.message
11089
11089
  });
11090
11090
  } catch (error$1) {
@@ -11101,7 +11101,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11101
11101
  const spanData = {
11102
11102
  traceId: spanInfo.traceId,
11103
11103
  spanId: spanInfo.spanId,
11104
- kind: import_src$28.SpanKind.CLIENT,
11104
+ kind: import_src$29.SpanKind.CLIENT,
11105
11105
  protocol: normalizedProtocol,
11106
11106
  inputValue,
11107
11107
  outputValue
@@ -11113,10 +11113,10 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11113
11113
  outputSchemaMerges,
11114
11114
  transformMetadata: spanData.transformMetadata ? spanData.transformMetadata : void 0
11115
11115
  });
11116
- const status = statusCode >= 400 ? {
11117
- code: import_src$28.SpanStatusCode.ERROR,
11116
+ const status = statusCode >= 300 ? {
11117
+ code: import_src$29.SpanStatusCode.ERROR,
11118
11118
  message: `HTTP ${statusCode}`
11119
- } : { code: import_src$28.SpanStatusCode.OK };
11119
+ } : { code: import_src$29.SpanStatusCode.OK };
11120
11120
  SpanUtils.endSpan(spanInfo.span, status);
11121
11121
  }
11122
11122
  _captureHeadersFromRawHeaders(rawHeaders) {
@@ -11170,7 +11170,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11170
11170
  };
11171
11171
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11172
11172
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11173
- kind: import_src$28.SpanKind.CLIENT,
11173
+ kind: import_src$29.SpanKind.CLIENT,
11174
11174
  packageName: requestProtocol,
11175
11175
  packageType: PackageType.HTTP,
11176
11176
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11205,7 +11205,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11205
11205
  };
11206
11206
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11207
11207
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11208
- kind: import_src$28.SpanKind.CLIENT,
11208
+ kind: import_src$29.SpanKind.CLIENT,
11209
11209
  packageName: requestProtocol,
11210
11210
  packageType: PackageType.HTTP,
11211
11211
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11217,7 +11217,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11217
11217
  return self._handleOutboundRequestInSpan(originalRequest, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11218
11218
  });
11219
11219
  },
11220
- spanKind: import_src$28.SpanKind.CLIENT
11220
+ spanKind: import_src$29.SpanKind.CLIENT
11221
11221
  });
11222
11222
  else return originalRequest.apply(this, args);
11223
11223
  };
@@ -11263,7 +11263,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11263
11263
  };
11264
11264
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11265
11265
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11266
- kind: import_src$28.SpanKind.CLIENT,
11266
+ kind: import_src$29.SpanKind.CLIENT,
11267
11267
  packageName: requestProtocol,
11268
11268
  packageType: PackageType.HTTP,
11269
11269
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11297,7 +11297,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11297
11297
  };
11298
11298
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11299
11299
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11300
- kind: import_src$28.SpanKind.CLIENT,
11300
+ kind: import_src$29.SpanKind.CLIENT,
11301
11301
  packageName: requestProtocol,
11302
11302
  packageType: PackageType.HTTP,
11303
11303
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11309,7 +11309,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11309
11309
  return self._handleOutboundRequestInSpan(originalGet, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11310
11310
  });
11311
11311
  },
11312
- spanKind: import_src$28.SpanKind.CLIENT
11312
+ spanKind: import_src$29.SpanKind.CLIENT
11313
11313
  });
11314
11314
  else return originalGet.apply(this, args);
11315
11315
  };
@@ -11354,7 +11354,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11354
11354
 
11355
11355
  //#endregion
11356
11356
  //#region src/instrumentation/libraries/date/Instrumentation.ts
11357
- var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11357
+ var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11358
11358
  /**
11359
11359
  * Date instrumentation that provides consistent dates in replay mode.
11360
11360
  * In replay mode, new Date() calls return the latest mock response timestamp.
@@ -11393,7 +11393,7 @@ var DateInstrumentation = class DateInstrumentation extends TdInstrumentationBas
11393
11393
  if (this.mode !== TuskDriftMode.REPLAY) return this._callOriginalDate(args, isConstructorCall);
11394
11394
  const currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11395
11395
  if (!currentSpanInfo) return this._callOriginalDate(args, isConstructorCall);
11396
- if (currentSpanInfo.context.getValue(SPAN_KIND_CONTEXT_KEY) !== import_src$27.SpanKind.SERVER) return this._callOriginalDate(args, isConstructorCall);
11396
+ if (currentSpanInfo.context.getValue(SPAN_KIND_CONTEXT_KEY) !== import_src$28.SpanKind.SERVER) return this._callOriginalDate(args, isConstructorCall);
11397
11397
  this.isInPatchedCall = true;
11398
11398
  try {
11399
11399
  return this._handleReplayDate(args, isConstructorCall);
@@ -11639,7 +11639,7 @@ var TdPgClientMock = class extends EventEmitter {
11639
11639
 
11640
11640
  //#endregion
11641
11641
  //#region src/instrumentation/libraries/pg/Instrumentation.ts
11642
- var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11642
+ var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11643
11643
  var PgInstrumentation = class extends TdInstrumentationBase {
11644
11644
  constructor(config = {}) {
11645
11645
  super("pg", config);
@@ -11680,6 +11680,10 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11680
11680
  const self = this;
11681
11681
  return (originalQuery) => {
11682
11682
  return function query(...args) {
11683
+ if (self.isSubmittable(args[0])) {
11684
+ logger.debug(`[PgInstrumentation] Submittable query detected, passing through uninstrumented`);
11685
+ return originalQuery.apply(this, args);
11686
+ }
11683
11687
  let queryConfig = null;
11684
11688
  try {
11685
11689
  queryConfig = self.parseQueryArgs(args);
@@ -11708,7 +11712,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11708
11712
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11709
11713
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11710
11714
  name: spanName,
11711
- kind: import_src$26.SpanKind.CLIENT,
11715
+ kind: import_src$27.SpanKind.CLIENT,
11712
11716
  submodule: "query",
11713
11717
  packageType: PackageType.PG,
11714
11718
  packageName,
@@ -11727,7 +11731,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11727
11731
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11728
11732
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11729
11733
  name: spanName,
11730
- kind: import_src$26.SpanKind.CLIENT,
11734
+ kind: import_src$27.SpanKind.CLIENT,
11731
11735
  submodule: "query",
11732
11736
  packageType: PackageType.PG,
11733
11737
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11738,7 +11742,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11738
11742
  return self._handleRecordQueryInSpan(spanInfo, originalQuery, queryConfig, args, this);
11739
11743
  });
11740
11744
  },
11741
- spanKind: import_src$26.SpanKind.CLIENT
11745
+ spanKind: import_src$27.SpanKind.CLIENT
11742
11746
  });
11743
11747
  else return originalQuery.apply(this, args);
11744
11748
  };
@@ -11760,7 +11764,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11760
11764
  replayModeHandler: () => {
11761
11765
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11762
11766
  name: `pg.connect`,
11763
- kind: import_src$26.SpanKind.CLIENT,
11767
+ kind: import_src$27.SpanKind.CLIENT,
11764
11768
  submodule: "connect",
11765
11769
  packageName: "pg",
11766
11770
  packageType: PackageType.PG,
@@ -11777,7 +11781,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11777
11781
  recordModeHandler: ({ isPreAppStart }) => {
11778
11782
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11779
11783
  name: `pg.connect`,
11780
- kind: import_src$26.SpanKind.CLIENT,
11784
+ kind: import_src$27.SpanKind.CLIENT,
11781
11785
  submodule: "connect",
11782
11786
  packageName: "pg",
11783
11787
  packageType: PackageType.PG,
@@ -11788,12 +11792,19 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11788
11792
  return self._handleRecordConnectInSpan(spanInfo, originalConnect, callback, this);
11789
11793
  });
11790
11794
  },
11791
- spanKind: import_src$26.SpanKind.CLIENT
11795
+ spanKind: import_src$27.SpanKind.CLIENT
11792
11796
  });
11793
11797
  else return originalConnect.apply(this, [callback]);
11794
11798
  };
11795
11799
  };
11796
11800
  }
11801
+ /**
11802
+ * Check if an object is a Submittable (Query object with submit method).
11803
+ * This is the same check pg uses internally: typeof config.submit === 'function'
11804
+ */
11805
+ isSubmittable(arg) {
11806
+ return arg && typeof arg.submit === "function";
11807
+ }
11797
11808
  parseQueryArgs(args) {
11798
11809
  if (args.length === 0) return null;
11799
11810
  const firstArg = args[0];
@@ -11821,7 +11832,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11821
11832
  logger.debug(`[PgInstrumentation] PG query error (hasCallback): ${error.message} (${SpanUtils.getTraceInfo()})`);
11822
11833
  try {
11823
11834
  SpanUtils.endSpan(spanInfo.span, {
11824
- code: import_src$26.SpanStatusCode.ERROR,
11835
+ code: import_src$27.SpanStatusCode.ERROR,
11825
11836
  message: error.message
11826
11837
  });
11827
11838
  } catch (error$1) {
@@ -11831,7 +11842,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11831
11842
  logger.debug(`[PgInstrumentation] PG query completed successfully (hasCallback) (${SpanUtils.getTraceInfo()})`);
11832
11843
  try {
11833
11844
  this._addOutputAttributesToSpan(spanInfo, result);
11834
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11845
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11835
11846
  } catch (error$1) {
11836
11847
  logger.error(`[PgInstrumentation] error processing response:`, error$1);
11837
11848
  }
@@ -11858,7 +11869,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11858
11869
  logger.debug(`[PgInstrumentation] PG query completed successfully (${SpanUtils.getTraceInfo()})`);
11859
11870
  try {
11860
11871
  this._addOutputAttributesToSpan(spanInfo, result);
11861
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11872
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11862
11873
  } catch (error) {
11863
11874
  logger.error(`[PgInstrumentation] error processing response:`, error);
11864
11875
  }
@@ -11867,7 +11878,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11867
11878
  logger.debug(`[PgInstrumentation] PG query error: ${error.message} (${SpanUtils.getTraceInfo()})`);
11868
11879
  try {
11869
11880
  SpanUtils.endSpan(spanInfo.span, {
11870
- code: import_src$26.SpanStatusCode.ERROR,
11881
+ code: import_src$27.SpanStatusCode.ERROR,
11871
11882
  message: error.message
11872
11883
  });
11873
11884
  } catch (error$1) {
@@ -11899,7 +11910,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11899
11910
  packageName,
11900
11911
  instrumentationName: this.INSTRUMENTATION_NAME,
11901
11912
  submoduleName: "query",
11902
- kind: import_src$26.SpanKind.CLIENT,
11913
+ kind: import_src$27.SpanKind.CLIENT,
11903
11914
  stackTrace
11904
11915
  },
11905
11916
  tuskDrift: this.tuskDrift
@@ -11943,6 +11954,8 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11943
11954
  * Reference for data type IDs: https://jdbc.postgresql.org/documentation/publicapi/constant-values.html
11944
11955
  */
11945
11956
  convertPostgresTypes(result, rowMode) {
11957
+ if (result && result.isMultiStatement && Array.isArray(result.results)) return result.results.map((singleResult) => this.convertPostgresTypes(singleResult, rowMode));
11958
+ if (Array.isArray(result)) return result.map((singleResult) => this.convertPostgresTypes(singleResult, rowMode));
11946
11959
  if (!result || !result.fields || !result.rows) return result;
11947
11960
  if (rowMode === "array") {
11948
11961
  const convertedRows$1 = result.rows.map((row) => {
@@ -11983,7 +11996,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11983
11996
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
11984
11997
  try {
11985
11998
  SpanUtils.endSpan(spanInfo.span, {
11986
- code: import_src$26.SpanStatusCode.ERROR,
11999
+ code: import_src$27.SpanStatusCode.ERROR,
11987
12000
  message: error.message
11988
12001
  });
11989
12002
  } catch (error$1) {
@@ -11993,7 +12006,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11993
12006
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
11994
12007
  try {
11995
12008
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
11996
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12009
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11997
12010
  } catch (error$1) {
11998
12011
  logger.error(`[PgInstrumentation] error processing connect response:`, error$1);
11999
12012
  }
@@ -12005,7 +12018,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12005
12018
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12006
12019
  try {
12007
12020
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12008
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12021
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12009
12022
  } catch (error) {
12010
12023
  logger.error(`[PgInstrumentation] error processing connect response:`, error);
12011
12024
  }
@@ -12014,7 +12027,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12014
12027
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12015
12028
  try {
12016
12029
  SpanUtils.endSpan(spanInfo.span, {
12017
- code: import_src$26.SpanStatusCode.ERROR,
12030
+ code: import_src$27.SpanStatusCode.ERROR,
12018
12031
  message: error.message
12019
12032
  });
12020
12033
  } catch (error$1) {
@@ -12032,7 +12045,18 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12032
12045
  }
12033
12046
  _addOutputAttributesToSpan(spanInfo, result) {
12034
12047
  if (!result) return;
12035
- const outputValue = {
12048
+ let outputValue;
12049
+ if (Array.isArray(result)) outputValue = {
12050
+ isMultiStatement: true,
12051
+ results: result.map((r) => ({
12052
+ command: r.command,
12053
+ rowCount: r.rowCount,
12054
+ oid: r.oid,
12055
+ rows: r.rows || [],
12056
+ fields: r.fields || []
12057
+ }))
12058
+ };
12059
+ else outputValue = {
12036
12060
  command: result.command,
12037
12061
  rowCount: result.rowCount,
12038
12062
  oid: result.oid,
@@ -12075,7 +12099,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12075
12099
  replayModeHandler: () => {
12076
12100
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12077
12101
  name: `pg-pool.connect`,
12078
- kind: import_src$26.SpanKind.CLIENT,
12102
+ kind: import_src$27.SpanKind.CLIENT,
12079
12103
  submodule: "connect",
12080
12104
  packageName: "pg-pool",
12081
12105
  packageType: PackageType.PG,
@@ -12092,7 +12116,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12092
12116
  recordModeHandler: ({ isPreAppStart }) => {
12093
12117
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12094
12118
  name: `pg-pool.connect`,
12095
- kind: import_src$26.SpanKind.CLIENT,
12119
+ kind: import_src$27.SpanKind.CLIENT,
12096
12120
  submodule: "connect",
12097
12121
  packageName: "pg-pool",
12098
12122
  packageType: PackageType.PG,
@@ -12103,7 +12127,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12103
12127
  return self._handleRecordPoolConnectInSpan(spanInfo, originalConnect, callback, this);
12104
12128
  });
12105
12129
  },
12106
- spanKind: import_src$26.SpanKind.CLIENT
12130
+ spanKind: import_src$27.SpanKind.CLIENT
12107
12131
  });
12108
12132
  else return originalConnect.apply(this, [callback]);
12109
12133
  };
@@ -12116,7 +12140,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12116
12140
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12117
12141
  try {
12118
12142
  SpanUtils.endSpan(spanInfo.span, {
12119
- code: import_src$26.SpanStatusCode.ERROR,
12143
+ code: import_src$27.SpanStatusCode.ERROR,
12120
12144
  message: error.message
12121
12145
  });
12122
12146
  } catch (error$1) {
@@ -12129,7 +12153,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12129
12153
  connected: true,
12130
12154
  hasClient: !!client
12131
12155
  } });
12132
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12156
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12133
12157
  } catch (error$1) {
12134
12158
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error$1);
12135
12159
  }
@@ -12144,7 +12168,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12144
12168
  connected: true,
12145
12169
  hasClient: !!client
12146
12170
  } });
12147
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12171
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12148
12172
  } catch (error) {
12149
12173
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error);
12150
12174
  }
@@ -12153,7 +12177,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12153
12177
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12154
12178
  try {
12155
12179
  SpanUtils.endSpan(spanInfo.span, {
12156
- code: import_src$26.SpanStatusCode.ERROR,
12180
+ code: import_src$27.SpanStatusCode.ERROR,
12157
12181
  message: error.message
12158
12182
  });
12159
12183
  } catch (error$1) {
@@ -12182,68 +12206,114 @@ function isPostgresOutputValueType(value) {
12182
12206
  }
12183
12207
 
12184
12208
  //#endregion
12185
- //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12186
- var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12187
- var PostgresInstrumentation = class extends TdInstrumentationBase {
12188
- constructor(config = {}) {
12189
- super("postgres", config);
12190
- this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12191
- this.mode = config.mode || TuskDriftMode.DISABLED;
12192
- this.tuskDrift = TuskDriftCore.getInstance();
12209
+ //#region src/instrumentation/libraries/postgres/utils/typeConversion.ts
12210
+ /**
12211
+ * Convert PostgreSQL string values back to appropriate JavaScript types
12212
+ * based on field metadata from the recorded response.
12213
+ */
12214
+ function convertPostgresTypes(result) {
12215
+ if (!isPostgresOutputValueType(result)) {
12216
+ logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12217
+ return;
12193
12218
  }
12194
- init() {
12195
- return [new TdInstrumentationNodeModule({
12196
- name: "postgres",
12197
- supportedVersions: ["3.*"],
12198
- patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12199
- })];
12219
+ const { rows, count, command, columns, state, statement } = result;
12220
+ const resultArray = Array.from((rows || []).map((row) => reconstructBuffers(row)));
12221
+ if (count !== void 0) Object.defineProperty(resultArray, "count", {
12222
+ value: count,
12223
+ writable: true,
12224
+ enumerable: false
12225
+ });
12226
+ if (command !== void 0) Object.defineProperty(resultArray, "command", {
12227
+ value: command,
12228
+ writable: true,
12229
+ enumerable: false
12230
+ });
12231
+ if (columns !== void 0) Object.defineProperty(resultArray, "columns", {
12232
+ value: columns,
12233
+ writable: true,
12234
+ enumerable: false
12235
+ });
12236
+ if (state !== void 0) Object.defineProperty(resultArray, "state", {
12237
+ value: state,
12238
+ writable: true,
12239
+ enumerable: false
12240
+ });
12241
+ if (statement !== void 0) Object.defineProperty(resultArray, "statement", {
12242
+ value: statement,
12243
+ writable: true,
12244
+ enumerable: false
12245
+ });
12246
+ return resultArray;
12247
+ }
12248
+ /**
12249
+ * Recursively reconstructs Buffer objects from their JSON-serialized format.
12250
+ * When Buffers are JSON.stringify'd, they become { type: "Buffer", data: [...] }.
12251
+ * This method converts them back to actual Buffer instances.
12252
+ */
12253
+ function reconstructBuffers(value) {
12254
+ if (value === null || value === void 0) return value;
12255
+ if (typeof value === "object" && value.type === "Buffer" && Array.isArray(value.data)) return Buffer.from(value.data);
12256
+ if (Array.isArray(value)) return value.map((item) => reconstructBuffers(item));
12257
+ if (typeof value === "object") {
12258
+ const result = {};
12259
+ for (const key of Object.keys(value)) result[key] = reconstructBuffers(value[key]);
12260
+ return result;
12200
12261
  }
12201
- _patchPostgresModule(postgresModule) {
12202
- logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12203
- if (this.isModulePatched(postgresModule)) {
12204
- logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12205
- return postgresModule;
12206
- }
12207
- const self = this;
12208
- if (isEsm(postgresModule)) {
12209
- logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12210
- this._wrap(postgresModule, "default", (originalFunction) => {
12211
- return function(...args) {
12212
- return self._handlePostgresConnection(originalFunction, args);
12213
- };
12214
- });
12215
- } else {
12216
- logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12217
- const originalFunction = postgresModule;
12218
- const wrappedFunction = function(...args) {
12219
- logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12220
- return self._handlePostgresConnection(originalFunction, args);
12221
- };
12222
- Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12223
- Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12224
- for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12225
- Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12226
- if (key !== "prototype" && key !== "length" && key !== "name") {
12227
- const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12228
- if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12229
- }
12230
- });
12231
- postgresModule = wrappedFunction;
12232
- }
12233
- if (postgresModule.sql && typeof postgresModule.sql === "function") {
12234
- this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12235
- logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12236
- }
12237
- this.markModuleAsPatched(postgresModule);
12238
- logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12239
- return postgresModule;
12262
+ return value;
12263
+ }
12264
+ /**
12265
+ * Add output attributes to span for PostgreSQL results.
12266
+ */
12267
+ function addOutputAttributesToSpan(spanInfo, result) {
12268
+ if (!result) return;
12269
+ const isArray$1 = Array.isArray(result);
12270
+ logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12271
+ const normalizeValue = (val) => {
12272
+ if (Buffer.isBuffer(val)) return val.toString("utf8");
12273
+ else if (Array.isArray(val)) return val.map(normalizeValue);
12274
+ else if (val && typeof val === "object" && val.type === "Buffer" && Array.isArray(val.data)) return Buffer.from(val.data).toString("utf8");
12275
+ return val;
12276
+ };
12277
+ const outputValue = {
12278
+ rows: isArray$1 ? Array.from(result).map(normalizeValue) : (result.rows || []).map(normalizeValue),
12279
+ count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12280
+ command: result.command || void 0,
12281
+ columns: result.columns || void 0,
12282
+ state: result.state || void 0,
12283
+ statement: result.statement || void 0
12284
+ };
12285
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12286
+ }
12287
+
12288
+ //#endregion
12289
+ //#region src/instrumentation/libraries/postgres/utils/queryUtils.ts
12290
+ /**
12291
+ * Reconstruct a parameterized query string from template strings array and values.
12292
+ * Converts values to $1, $2, etc. placeholders.
12293
+ */
12294
+ function reconstructQueryString(strings, values) {
12295
+ let queryString = "";
12296
+ for (let i = 0; i < strings.length; i++) {
12297
+ queryString += strings[i];
12298
+ if (i < values.length) queryString += `$${i + 1}`;
12240
12299
  }
12241
- _handlePostgresConnection(originalFunction, args) {
12242
- const connectionString = typeof args[0] === "string" ? args[0] : void 0;
12243
- const options = typeof args[0] === "string" ? args[1] : args[0];
12300
+ return queryString;
12301
+ }
12302
+
12303
+ //#endregion
12304
+ //#region src/instrumentation/libraries/postgres/handlers/ConnectionHandler.ts
12305
+ var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12306
+ var ConnectionHandler = class {
12307
+ constructor(mode, instrumentationName, isAppReady, wrapSqlInstance) {
12308
+ this.mode = mode;
12309
+ this.instrumentationName = instrumentationName;
12310
+ this.isAppReady = isAppReady;
12311
+ this.wrapSqlInstance = wrapSqlInstance;
12312
+ }
12313
+ handlePostgresConnection(originalFunction, args) {
12244
12314
  const inputValue = {
12245
- connectionString: connectionString ? this._sanitizeConnectionString(connectionString) : void 0,
12246
- options: options ? this._sanitizeConnectionOptions(options) : void 0
12315
+ connectionString: typeof args[0] === "string" ? args[0] : void 0,
12316
+ options: typeof args[0] === "string" ? args[1] : args[0]
12247
12317
  };
12248
12318
  if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
12249
12319
  noOpRequestHandler: () => {
@@ -12257,96 +12327,148 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12257
12327
  }));
12258
12328
  mockSql.begin = () => Promise.resolve();
12259
12329
  mockSql.end = () => Promise.resolve();
12330
+ mockSql.file = () => Promise.resolve(Object.assign([], {
12331
+ count: 0,
12332
+ command: null
12333
+ }));
12334
+ mockSql.reserve = () => Promise.resolve(mockSql);
12335
+ mockSql.listen = () => Promise.resolve({
12336
+ state: { state: "I" },
12337
+ unlisten: async () => {}
12338
+ });
12339
+ mockSql.notify = () => Promise.resolve();
12260
12340
  return mockSql;
12261
12341
  },
12262
12342
  isServerRequest: false,
12263
12343
  replayModeHandler: () => {
12264
12344
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12265
12345
  const sqlInstance = originalFunction(...args);
12266
- return this._wrapSqlInstance(sqlInstance);
12346
+ return this.wrapSqlInstance(sqlInstance);
12267
12347
  }, {
12268
12348
  name: "postgres.connect",
12269
- kind: import_src$25.SpanKind.CLIENT,
12349
+ kind: import_src$26.SpanKind.CLIENT,
12270
12350
  submodule: "connect",
12271
12351
  packageType: PackageType.PG,
12272
12352
  packageName: "postgres",
12273
- instrumentationName: this.INSTRUMENTATION_NAME,
12353
+ instrumentationName: this.instrumentationName,
12274
12354
  inputValue,
12275
- isPreAppStart: false
12355
+ isPreAppStart: this.isAppReady() ? false : true
12276
12356
  }, (spanInfo) => {
12277
- return this._handleReplayConnect(originalFunction, args);
12357
+ return this.handleReplayConnect(originalFunction, args);
12278
12358
  });
12279
12359
  }
12280
12360
  });
12281
12361
  else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
12282
12362
  originalFunctionCall: () => {
12283
12363
  const sqlInstance = originalFunction(...args);
12284
- return this._wrapSqlInstance(sqlInstance);
12364
+ return this.wrapSqlInstance(sqlInstance);
12285
12365
  },
12286
12366
  recordModeHandler: ({ isPreAppStart }) => {
12287
12367
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12288
12368
  const sqlInstance = originalFunction(...args);
12289
- return this._wrapSqlInstance(sqlInstance);
12369
+ return this.wrapSqlInstance(sqlInstance);
12290
12370
  }, {
12291
12371
  name: "postgres.connect",
12292
- kind: import_src$25.SpanKind.CLIENT,
12372
+ kind: import_src$26.SpanKind.CLIENT,
12293
12373
  submodule: "connect",
12294
12374
  packageType: PackageType.PG,
12295
12375
  packageName: "postgres",
12296
- instrumentationName: this.INSTRUMENTATION_NAME,
12376
+ instrumentationName: this.instrumentationName,
12297
12377
  inputValue,
12298
12378
  isPreAppStart
12299
12379
  }, (spanInfo) => {
12300
- return this._handleRecordConnect(spanInfo, originalFunction, args);
12380
+ return this.handleRecordConnect(spanInfo, originalFunction, args);
12301
12381
  });
12302
12382
  },
12303
- spanKind: import_src$25.SpanKind.CLIENT
12383
+ spanKind: import_src$26.SpanKind.CLIENT
12304
12384
  });
12305
12385
  else return originalFunction(...args);
12306
12386
  }
12307
- _sanitizeConnectionString(connectionString) {
12308
- try {
12309
- const url = new URL(connectionString);
12310
- if (url.password) url.password = "***";
12311
- return url.toString();
12312
- } catch {
12313
- return "[INVALID_URL]";
12314
- }
12315
- }
12316
- _sanitizeConnectionOptions(options) {
12317
- if (!options || typeof options !== "object") return options;
12318
- const sanitized = { ...options };
12319
- if (sanitized.password) sanitized.password = "***";
12320
- if (sanitized.ssl && typeof sanitized.ssl === "object") {
12321
- sanitized.ssl = { ...sanitized.ssl };
12322
- if (sanitized.ssl.key) sanitized.ssl.key = "***";
12323
- if (sanitized.ssl.cert) sanitized.ssl.cert = "***";
12324
- if (sanitized.ssl.ca) sanitized.ssl.ca = "***";
12325
- }
12326
- return sanitized;
12327
- }
12328
- _handleRecordConnect(spanInfo, originalFunction, args) {
12387
+ handleRecordConnect(spanInfo, originalFunction, args) {
12329
12388
  const sqlInstance = originalFunction(...args);
12330
- const wrappedInstance = this._wrapSqlInstance(sqlInstance);
12389
+ const wrappedInstance = this.wrapSqlInstance(sqlInstance);
12331
12390
  try {
12332
12391
  logger.debug(`[PostgresInstrumentation] Postgres connection created successfully (${SpanUtils.getTraceInfo()})`);
12333
12392
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12334
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12393
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12335
12394
  } catch (error) {
12336
12395
  logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12337
12396
  }
12338
12397
  return wrappedInstance;
12339
12398
  }
12340
- _handleReplayConnect(originalFunction, args) {
12399
+ handleReplayConnect(originalFunction, args) {
12341
12400
  logger.debug(`[PostgresInstrumentation] Replaying Postgres connection`);
12342
12401
  try {
12343
12402
  const sqlInstance = originalFunction(...args);
12344
- return this._wrapSqlInstance(sqlInstance);
12403
+ return this.wrapSqlInstance(sqlInstance);
12345
12404
  } catch (error) {
12346
12405
  logger.debug(`[PostgresInstrumentation] Postgres connection error in replay: ${error.message}`);
12347
12406
  throw error;
12348
12407
  }
12349
12408
  }
12409
+ };
12410
+
12411
+ //#endregion
12412
+ //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12413
+ var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12414
+ var PostgresInstrumentation = class extends TdInstrumentationBase {
12415
+ constructor(config = {}) {
12416
+ super("postgres", config);
12417
+ this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12418
+ this.mode = config.mode || TuskDriftMode.DISABLED;
12419
+ this.tuskDrift = TuskDriftCore.getInstance();
12420
+ this.connectionHandler = new ConnectionHandler(this.mode, this.INSTRUMENTATION_NAME, () => this.tuskDrift.isAppReady(), (sqlInstance) => this._wrapSqlInstance(sqlInstance));
12421
+ }
12422
+ init() {
12423
+ return [new TdInstrumentationNodeModule({
12424
+ name: "postgres",
12425
+ supportedVersions: ["3.*"],
12426
+ patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12427
+ })];
12428
+ }
12429
+ _patchPostgresModule(postgresModule) {
12430
+ logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12431
+ if (this.isModulePatched(postgresModule)) {
12432
+ logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12433
+ return postgresModule;
12434
+ }
12435
+ const self = this;
12436
+ if (isEsm(postgresModule)) {
12437
+ logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12438
+ this._wrap(postgresModule, "default", (originalFunction) => {
12439
+ return function(...args) {
12440
+ return self._handlePostgresConnection(originalFunction, args);
12441
+ };
12442
+ });
12443
+ } else {
12444
+ logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12445
+ const originalFunction = postgresModule;
12446
+ const wrappedFunction = function(...args) {
12447
+ logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12448
+ return self._handlePostgresConnection(originalFunction, args);
12449
+ };
12450
+ Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12451
+ Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12452
+ for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12453
+ Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12454
+ if (key !== "prototype" && key !== "length" && key !== "name") {
12455
+ const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12456
+ if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12457
+ }
12458
+ });
12459
+ postgresModule = wrappedFunction;
12460
+ }
12461
+ if (postgresModule.sql && typeof postgresModule.sql === "function") {
12462
+ this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12463
+ logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12464
+ }
12465
+ this.markModuleAsPatched(postgresModule);
12466
+ logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12467
+ return postgresModule;
12468
+ }
12469
+ _handlePostgresConnection(originalFunction, args) {
12470
+ return this.connectionHandler.handlePostgresConnection(originalFunction, args);
12471
+ }
12350
12472
  _wrapSqlInstance(sqlInstance) {
12351
12473
  if (!sqlInstance || typeof sqlInstance !== "function") return sqlInstance;
12352
12474
  const self = this;
@@ -12362,11 +12484,34 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12362
12484
  logger.debug(`[PostgresInstrumentation] Wrapped unsafe method on sql instance`);
12363
12485
  }
12364
12486
  if (typeof originalSql.begin === "function") {
12365
- wrappedSql.begin = self._wrapBeginMethod(originalSql);
12366
- logger.debug(`[PostgresInstrumentation] Wrapped begin method on sql instance`);
12487
+ const wrappedBegin = self._wrapBeginMethod(originalSql);
12488
+ originalSql.begin = wrappedBegin;
12489
+ wrappedSql.begin = wrappedBegin;
12490
+ }
12491
+ if (typeof originalSql.file === "function") {
12492
+ wrappedSql.file = self._wrapFileMethod(originalSql);
12493
+ logger.debug(`[PostgresInstrumentation] Wrapped file method on sql instance`);
12494
+ }
12495
+ if (typeof originalSql.reserve === "function") {
12496
+ wrappedSql.reserve = self._wrapReserveMethod(originalSql);
12497
+ logger.debug(`[PostgresInstrumentation] Wrapped reserve method on sql instance`);
12498
+ }
12499
+ if (typeof originalSql.listen === "function") {
12500
+ wrappedSql.listen = self._wrapListenMethod(originalSql);
12501
+ logger.debug(`[PostgresInstrumentation] Wrapped listen method on sql instance`);
12502
+ }
12503
+ if (typeof originalSql.notify === "function") {
12504
+ wrappedSql.notify = self._wrapNotifyMethod(wrappedSql);
12505
+ logger.debug(`[PostgresInstrumentation] Wrapped notify method on sql instance`);
12367
12506
  }
12368
12507
  return wrappedSql;
12369
12508
  }
12509
+ _wrapNotifyMethod(wrappedSqlInstance) {
12510
+ return async function notify(channel, payload) {
12511
+ logger.debug(`[PostgresInstrumentation] notify() called for channel ${channel}`);
12512
+ return wrappedSqlInstance`select pg_notify(${channel}, ${String(payload)})`;
12513
+ };
12514
+ }
12370
12515
  _wrapUnsafeMethod(sqlInstance) {
12371
12516
  const self = this;
12372
12517
  const originalUnsafe = sqlInstance.unsafe;
@@ -12383,6 +12528,175 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12383
12528
  return self._handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback);
12384
12529
  };
12385
12530
  }
12531
+ _wrapFileMethod(sqlInstance) {
12532
+ const self = this;
12533
+ const originalFile = sqlInstance.file;
12534
+ return function file(path$2, parameters, queryOptions) {
12535
+ return self._handleFileQuery(sqlInstance, originalFile, path$2, parameters, queryOptions);
12536
+ };
12537
+ }
12538
+ _wrapReserveMethod(sqlInstance) {
12539
+ const self = this;
12540
+ const originalReserve = sqlInstance.reserve;
12541
+ return async function reserve() {
12542
+ if (self.mode === TuskDriftMode.REPLAY) {
12543
+ logger.debug(`[PostgresInstrumentation] REPLAY mode: Creating mock reserved connection without TCP`);
12544
+ const mockReservedSql = self._wrapSqlInstance(sqlInstance);
12545
+ if (typeof mockReservedSql === "function") mockReservedSql.release = function() {
12546
+ logger.debug(`[PostgresInstrumentation] Mock reserved connection released`);
12547
+ };
12548
+ return mockReservedSql;
12549
+ }
12550
+ const reservedSql = await originalReserve.call(sqlInstance);
12551
+ const wrappedReservedSql = self._wrapSqlInstance(reservedSql);
12552
+ logger.debug(`[PostgresInstrumentation] Reserved connection obtained and wrapped`);
12553
+ return wrappedReservedSql;
12554
+ };
12555
+ }
12556
+ _wrapListenMethod(sqlInstance) {
12557
+ const self = this;
12558
+ const originalListen = sqlInstance.listen;
12559
+ return async function listen(channelName, callback, onlisten) {
12560
+ return self._handleListenMethod(sqlInstance, originalListen, channelName, callback, onlisten);
12561
+ };
12562
+ }
12563
+ async _handleListenMethod(sqlInstance, originalListen, channelName, callback, onlisten) {
12564
+ const inputValue = {
12565
+ operation: "listen",
12566
+ channel: channelName
12567
+ };
12568
+ if (this.mode === TuskDriftMode.REPLAY) return this._handleReplayListen(channelName, callback, onlisten, inputValue);
12569
+ else if (this.mode === TuskDriftMode.RECORD) return this._handleRecordListen(sqlInstance, originalListen, channelName, callback, onlisten, inputValue);
12570
+ else return originalListen.call(sqlInstance, channelName, callback, onlisten);
12571
+ }
12572
+ async _handleRecordListen(sqlInstance, originalListen, channelName, callback, onlisten, inputValue) {
12573
+ const receivedPayloads = [];
12574
+ const wrappedCallback = (payload) => {
12575
+ logger.debug(`[PostgresInstrumentation] RECORD: Captured notification payload on channel ${channelName}: ${payload}`);
12576
+ receivedPayloads.push(payload);
12577
+ callback(payload);
12578
+ };
12579
+ return handleRecordMode({
12580
+ originalFunctionCall: () => originalListen.call(sqlInstance, channelName, callback, onlisten),
12581
+ recordModeHandler: ({ isPreAppStart }) => {
12582
+ return SpanUtils.createAndExecuteSpan(this.mode, () => originalListen.call(sqlInstance, channelName, callback, onlisten), {
12583
+ name: "postgres.listen",
12584
+ kind: import_src$25.SpanKind.CLIENT,
12585
+ submodule: "listen",
12586
+ packageType: PackageType.PG,
12587
+ packageName: "postgres",
12588
+ instrumentationName: this.INSTRUMENTATION_NAME,
12589
+ inputValue,
12590
+ isPreAppStart
12591
+ }, async (spanInfo) => {
12592
+ try {
12593
+ const result = await originalListen.call(sqlInstance, channelName, wrappedCallback, onlisten);
12594
+ try {
12595
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12596
+ channel: channelName,
12597
+ state: result.state
12598
+ } });
12599
+ } catch (error) {
12600
+ logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12601
+ }
12602
+ const originalUnlisten = result.unlisten;
12603
+ const wrappedUnlisten = async () => {
12604
+ logger.debug(`[PostgresInstrumentation] RECORD: Unlisten called, captured ${receivedPayloads.length} payloads`);
12605
+ try {
12606
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12607
+ channel: channelName,
12608
+ state: result.state,
12609
+ payloads: receivedPayloads
12610
+ } });
12611
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12612
+ } catch (error) {
12613
+ logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12614
+ }
12615
+ return originalUnlisten();
12616
+ };
12617
+ return {
12618
+ state: result.state,
12619
+ unlisten: wrappedUnlisten
12620
+ };
12621
+ } catch (error) {
12622
+ logger.error(`[PostgresInstrumentation] RECORD listen error: ${error.message}`);
12623
+ try {
12624
+ SpanUtils.endSpan(spanInfo.span, {
12625
+ code: import_src$25.SpanStatusCode.ERROR,
12626
+ message: error.message
12627
+ });
12628
+ } catch (error$1) {
12629
+ logger.error(`[PostgresInstrumentation] error ending span:`, error$1);
12630
+ }
12631
+ throw error;
12632
+ }
12633
+ });
12634
+ },
12635
+ spanKind: import_src$25.SpanKind.CLIENT
12636
+ });
12637
+ }
12638
+ async _handleReplayListen(channelName, callback, onlisten, inputValue) {
12639
+ logger.debug(`[PostgresInstrumentation] REPLAY: Mocking listen for channel ${channelName} without TCP`);
12640
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12641
+ return handleReplayMode({
12642
+ noOpRequestHandler: () => Promise.resolve({
12643
+ state: { state: "I" },
12644
+ unlisten: async () => {}
12645
+ }),
12646
+ isServerRequest: false,
12647
+ replayModeHandler: () => {
12648
+ return SpanUtils.createAndExecuteSpan(this.mode, () => Promise.resolve({
12649
+ state: { state: "I" },
12650
+ unlisten: async () => {}
12651
+ }), {
12652
+ name: "postgres.listen",
12653
+ kind: import_src$25.SpanKind.CLIENT,
12654
+ submodule: "listen",
12655
+ packageType: PackageType.PG,
12656
+ packageName: "postgres",
12657
+ instrumentationName: this.INSTRUMENTATION_NAME,
12658
+ inputValue,
12659
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12660
+ }, async (spanInfo) => {
12661
+ try {
12662
+ const mockData = await this._findMockData({
12663
+ spanInfo,
12664
+ name: "postgres.listen",
12665
+ inputValue,
12666
+ submoduleName: "listen",
12667
+ stackTrace
12668
+ });
12669
+ if (!mockData) {
12670
+ logger.warn(`[PostgresInstrumentation] No mock data found for listen channel: ${channelName}`);
12671
+ throw new Error(`No mock data found for listen channel: ${channelName}`);
12672
+ }
12673
+ logger.debug(`[PostgresInstrumentation] Found mock data for listen: ${JSON.stringify(mockData)}`);
12674
+ const recordedPayloads = mockData.result?.payloads || [];
12675
+ const recordedState = mockData.result?.state || { state: "I" };
12676
+ if (onlisten) onlisten();
12677
+ for (const payload of recordedPayloads) {
12678
+ logger.debug(`[PostgresInstrumentation] REPLAY: Invoking callback with recorded payload: ${payload}`);
12679
+ callback(payload);
12680
+ }
12681
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12682
+ return {
12683
+ state: recordedState,
12684
+ unlisten: async () => {
12685
+ logger.debug(`[PostgresInstrumentation] REPLAY: Mock unlisten called`);
12686
+ }
12687
+ };
12688
+ } catch (error) {
12689
+ logger.error(`[PostgresInstrumentation] REPLAY listen error: ${error.message}`);
12690
+ SpanUtils.endSpan(spanInfo.span, {
12691
+ code: import_src$25.SpanStatusCode.ERROR,
12692
+ message: error.message
12693
+ });
12694
+ throw error;
12695
+ }
12696
+ });
12697
+ }
12698
+ });
12699
+ }
12386
12700
  _getSqlPatchFn() {
12387
12701
  const self = this;
12388
12702
  return (originalSql) => {
@@ -12395,93 +12709,19 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12395
12709
  if (!strings || !Array.isArray(strings.raw)) return originalSql.call(this, strings, ...values);
12396
12710
  const creationContext = import_src$25.context.active();
12397
12711
  const query = originalSql.call(this, strings, ...values);
12712
+ const inputValue = {
12713
+ query: reconstructQueryString(strings, values).trim(),
12714
+ parameters: values
12715
+ };
12398
12716
  const originalThen = query.then.bind(query);
12399
- const self = this;
12400
- query.then = function(onFulfilled, onRejected) {
12401
- let queryString = "";
12402
- for (let i = 0; i < strings.length; i++) {
12403
- queryString += strings[i];
12404
- if (i < values.length) queryString += `$${i + 1}`;
12405
- }
12406
- const inputValue = {
12407
- query: queryString.trim(),
12408
- parameters: values
12409
- };
12410
- return import_src$25.context.with(creationContext, () => {
12411
- if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12412
- originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12413
- recordModeHandler: ({ isPreAppStart }) => {
12414
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12415
- name: "postgres.query",
12416
- kind: import_src$25.SpanKind.CLIENT,
12417
- submodule: "query",
12418
- packageType: PackageType.PG,
12419
- instrumentationName: self.INSTRUMENTATION_NAME,
12420
- packageName: "postgres",
12421
- inputValue,
12422
- isPreAppStart
12423
- }, (spanInfo) => {
12424
- const wrappedOnFulfilled = (result) => {
12425
- try {
12426
- logger.debug(`[PostgresInstrumentation] Postgres query completed successfully`, result);
12427
- self._addOutputAttributesToSpan(spanInfo, result);
12428
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12429
- } catch (error) {
12430
- logger.error(`[PostgresInstrumentation] error processing query response:`, error);
12431
- }
12432
- return onFulfilled ? onFulfilled(result) : result;
12433
- };
12434
- const wrappedOnRejected = (error) => {
12435
- try {
12436
- logger.debug(`[PostgresInstrumentation] Postgres query error`, error);
12437
- SpanUtils.endSpan(spanInfo.span, {
12438
- code: import_src$25.SpanStatusCode.ERROR,
12439
- message: error.message
12440
- });
12441
- } catch (spanError) {
12442
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12443
- }
12444
- if (onRejected) return onRejected(error);
12445
- throw error;
12446
- };
12447
- return originalThen(wrappedOnFulfilled, wrappedOnRejected);
12448
- });
12449
- },
12450
- spanKind: import_src$25.SpanKind.CLIENT
12451
- });
12452
- else if (self.mode === TuskDriftMode.REPLAY) {
12453
- const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12454
- return handleReplayMode({
12455
- noOpRequestHandler: () => Promise.resolve(Object.assign([], {
12456
- count: 0,
12457
- command: null
12458
- })),
12459
- isServerRequest: false,
12460
- replayModeHandler: () => {
12461
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12462
- name: "postgres.query",
12463
- kind: import_src$25.SpanKind.CLIENT,
12464
- submodule: "query",
12465
- packageType: PackageType.PG,
12466
- packageName: "postgres",
12467
- instrumentationName: self.INSTRUMENTATION_NAME,
12468
- inputValue,
12469
- isPreAppStart: false
12470
- }, async (spanInfo) => {
12471
- const mockedResult = await self.handleReplaySqlQuery({
12472
- inputValue,
12473
- spanInfo,
12474
- submodule: "query",
12475
- name: "postgres.query",
12476
- stackTrace
12477
- });
12478
- return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12479
- });
12480
- }
12481
- });
12482
- } else return originalThen(onFulfilled, onRejected);
12483
- });
12484
- };
12717
+ this._wrapThenMethod(query, originalThen, inputValue, creationContext, {
12718
+ name: "postgres.query",
12719
+ submodule: "query",
12720
+ operationType: "sql"
12721
+ });
12722
+ this._wrapExecuteMethod(query);
12723
+ this._wrapCursorMethod(query, inputValue, creationContext);
12724
+ this._wrapForEachMethod(query, inputValue, creationContext);
12485
12725
  return query;
12486
12726
  }
12487
12727
  _handleUnsafeQuery(sqlInstance, originalUnsafe, query, parameters, queryOptions) {
@@ -12492,21 +12732,46 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12492
12732
  })();
12493
12733
  const creationContext = import_src$25.context.active();
12494
12734
  const originalThen = unsafeQuery.then.bind(unsafeQuery);
12495
- const self = this;
12496
12735
  const inputValue = {
12497
12736
  query: query.trim(),
12498
12737
  parameters: parameters || [],
12499
12738
  options: queryOptions
12500
12739
  };
12501
- unsafeQuery.then = function(onFulfilled, onRejected) {
12740
+ this._wrapThenMethod(unsafeQuery, originalThen, inputValue, creationContext, {
12741
+ name: "postgres.unsafe",
12742
+ submodule: "unsafe",
12743
+ operationType: "unsafe"
12744
+ });
12745
+ this._wrapExecuteMethod(unsafeQuery);
12746
+ this._wrapCursorMethod(unsafeQuery, inputValue, creationContext);
12747
+ this._wrapForEachMethod(unsafeQuery, inputValue, creationContext);
12748
+ return unsafeQuery;
12749
+ }
12750
+ _handleFileQuery(sqlInstance, originalFile, path$2, parameters, queryOptions) {
12751
+ const fileQuery = (() => {
12752
+ if (queryOptions !== void 0) return originalFile.call(sqlInstance, path$2, parameters, queryOptions);
12753
+ else if (parameters !== void 0) return originalFile.call(sqlInstance, path$2, parameters);
12754
+ else return originalFile.call(sqlInstance, path$2);
12755
+ })();
12756
+ const creationContext = import_src$25.context.active();
12757
+ const originalThen = fileQuery.then.bind(fileQuery);
12758
+ const self = this;
12759
+ const inputValue = {
12760
+ query: path$2,
12761
+ parameters: parameters || [],
12762
+ options: queryOptions
12763
+ };
12764
+ fileQuery.then = function(onFulfilled, onRejected) {
12765
+ if (fileQuery._tuskRecorded) return originalThen(onFulfilled, onRejected);
12766
+ fileQuery._tuskRecorded = true;
12502
12767
  return import_src$25.context.with(creationContext, () => {
12503
12768
  if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12504
12769
  originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12505
12770
  recordModeHandler: ({ isPreAppStart }) => {
12506
12771
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12507
- name: "postgres.unsafe",
12772
+ name: "postgres.file",
12508
12773
  kind: import_src$25.SpanKind.CLIENT,
12509
- submodule: "unsafe",
12774
+ submodule: "file",
12510
12775
  packageType: PackageType.PG,
12511
12776
  packageName: "postgres",
12512
12777
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -12515,17 +12780,17 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12515
12780
  }, (spanInfo) => {
12516
12781
  const wrappedOnFulfilled = (result) => {
12517
12782
  try {
12518
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query completed successfully (${SpanUtils.getTraceInfo()})`);
12519
- self._addOutputAttributesToSpan(spanInfo, result);
12783
+ logger.debug(`[PostgresInstrumentation] Postgres file query completed successfully (${SpanUtils.getTraceInfo()})`);
12784
+ addOutputAttributesToSpan(spanInfo, result);
12520
12785
  SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12521
12786
  } catch (error) {
12522
- logger.error(`[PostgresInstrumentation] error processing unsafe query response:`, error);
12787
+ logger.error(`[PostgresInstrumentation] error processing file query response:`, error);
12523
12788
  }
12524
12789
  return onFulfilled ? onFulfilled(result) : result;
12525
12790
  };
12526
12791
  const wrappedOnRejected = (error) => {
12527
12792
  try {
12528
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query error: ${error.message}`);
12793
+ logger.debug(`[PostgresInstrumentation] Postgres file query error: ${error.message}`);
12529
12794
  SpanUtils.endSpan(spanInfo.span, {
12530
12795
  code: import_src$25.SpanStatusCode.ERROR,
12531
12796
  message: error.message
@@ -12551,22 +12816,24 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12551
12816
  isServerRequest: false,
12552
12817
  replayModeHandler: () => {
12553
12818
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12554
- name: "postgres.unsafe",
12819
+ name: "postgres.file",
12555
12820
  kind: import_src$25.SpanKind.CLIENT,
12556
- submodule: "unsafe",
12821
+ submodule: "file",
12557
12822
  packageType: PackageType.PG,
12558
12823
  packageName: "postgres",
12559
12824
  instrumentationName: self.INSTRUMENTATION_NAME,
12560
12825
  inputValue,
12561
- isPreAppStart: false
12826
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
12562
12827
  }, async (spanInfo) => {
12563
- const mockedResult = await self.handleReplayUnsafeQuery({
12828
+ const mockedResult = await self._handleReplayQueryOperation({
12564
12829
  inputValue,
12565
12830
  spanInfo,
12566
- submodule: "unsafe",
12567
- name: "postgres.unsafe",
12568
- stackTrace
12831
+ submodule: "file",
12832
+ name: "postgres.file",
12833
+ stackTrace,
12834
+ operationType: "file"
12569
12835
  });
12836
+ if (!mockedResult) throw new Error(`No mock data found for Postgres file query: ${inputValue.query}`);
12570
12837
  return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12571
12838
  });
12572
12839
  }
@@ -12574,16 +12841,45 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12574
12841
  } else return originalThen(onFulfilled, onRejected);
12575
12842
  });
12576
12843
  };
12577
- return unsafeQuery;
12844
+ const originalExecute = fileQuery.execute ? fileQuery.execute.bind(fileQuery) : void 0;
12845
+ if (originalExecute) fileQuery.execute = function() {
12846
+ if (self.mode === TuskDriftMode.REPLAY) return this;
12847
+ else return originalExecute.call(this);
12848
+ };
12849
+ return fileQuery;
12850
+ }
12851
+ /**
12852
+ * Wraps a transaction callback to ensure the inner SQL instance is instrumented.
12853
+ * This is necessary because postgres.js creates a new SQL instance inside begin()
12854
+ * that would otherwise bypass instrumentation.
12855
+ */
12856
+ _wrapTransactionCallback(transactionCallback) {
12857
+ const self = this;
12858
+ return (transactionSql) => {
12859
+ const wrappedSql = self._wrapSqlInstance(transactionSql);
12860
+ if (typeof transactionSql.savepoint === "function") {
12861
+ const originalSavepoint = transactionSql.savepoint;
12862
+ wrappedSql.savepoint = function(nameOrFn, fn) {
12863
+ const savepointCallback = typeof nameOrFn === "function" ? nameOrFn : fn;
12864
+ const savepointName = typeof nameOrFn === "string" ? nameOrFn : void 0;
12865
+ const wrappedSavepointCallback = self._wrapTransactionCallback(savepointCallback);
12866
+ if (savepointName) return originalSavepoint.call(transactionSql, savepointName, wrappedSavepointCallback);
12867
+ else return originalSavepoint.call(transactionSql, wrappedSavepointCallback);
12868
+ };
12869
+ }
12870
+ if (typeof transactionSql.prepare === "function") wrappedSql.prepare = transactionSql.prepare.bind(transactionSql);
12871
+ return transactionCallback(wrappedSql);
12872
+ };
12578
12873
  }
12579
12874
  _handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback) {
12580
12875
  const inputValue = {
12581
12876
  query: "BEGIN",
12582
12877
  options: options ? { transactionOptions: options } : void 0
12583
12878
  };
12879
+ const wrappedCallback = transactionCallback ? this._wrapTransactionCallback(transactionCallback) : void 0;
12584
12880
  const executeBegin = () => {
12585
- if (options && transactionCallback) return originalBegin.call(sqlInstance, options, transactionCallback);
12586
- else if (transactionCallback) return originalBegin.call(sqlInstance, transactionCallback);
12881
+ if (options && wrappedCallback) return originalBegin.call(sqlInstance, options, wrappedCallback);
12882
+ else if (wrappedCallback) return originalBegin.call(sqlInstance, wrappedCallback);
12587
12883
  else return originalBegin.call(sqlInstance, options || void 0);
12588
12884
  };
12589
12885
  if (this.mode === TuskDriftMode.REPLAY) {
@@ -12600,9 +12896,9 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12600
12896
  packageName: "postgres",
12601
12897
  instrumentationName: this.INSTRUMENTATION_NAME,
12602
12898
  inputValue,
12603
- isPreAppStart: false
12899
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12604
12900
  }, (spanInfo) => {
12605
- return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
12901
+ return this._handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback);
12606
12902
  });
12607
12903
  }
12608
12904
  });
@@ -12627,151 +12923,672 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12627
12923
  else return executeBegin();
12628
12924
  }
12629
12925
  _handleRecordBeginTransaction(spanInfo, executeBegin) {
12630
- const promise = executeBegin();
12631
- promise.finally(() => {
12632
- promise.then((result) => {
12633
- logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12634
- try {
12635
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12636
- status: "committed",
12637
- result
12638
- } });
12639
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12640
- } catch (error) {
12641
- logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12926
+ return executeBegin().then((result) => {
12927
+ logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12928
+ try {
12929
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12930
+ status: "committed",
12931
+ result
12932
+ } });
12933
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12934
+ } catch (error) {
12935
+ logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12936
+ }
12937
+ return result;
12938
+ }).catch((error) => {
12939
+ logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12940
+ try {
12941
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12942
+ status: "rolled_back",
12943
+ error: error.message
12944
+ } });
12945
+ SpanUtils.endSpan(spanInfo.span, {
12946
+ code: import_src$25.SpanStatusCode.ERROR,
12947
+ message: error.message
12948
+ });
12949
+ } catch (spanError) {
12950
+ logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12951
+ }
12952
+ throw error;
12953
+ });
12954
+ }
12955
+ async _handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback) {
12956
+ logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
12957
+ const transactionInputValue = {
12958
+ query: "BEGIN",
12959
+ options: options ? { transactionOptions: options } : void 0
12960
+ };
12961
+ const mockData = await this._findMockData({
12962
+ spanInfo,
12963
+ name: "postgres.begin",
12964
+ inputValue: transactionInputValue,
12965
+ submoduleName: "transaction",
12966
+ stackTrace
12967
+ });
12968
+ if (!mockData) {
12969
+ logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
12970
+ throw new Error(`[PostgresInstrumentation] No matching mock found for transaction BEGIN`);
12971
+ }
12972
+ logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
12973
+ const transactionResult = mockData.result;
12974
+ const wasCommitted = transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed";
12975
+ if (!wrappedCallback) if (wasCommitted) return transactionResult.result;
12976
+ else {
12977
+ const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
12978
+ throw new Error(errorMessage);
12979
+ }
12980
+ try {
12981
+ const result = await wrappedCallback(this._createMockTransactionSql());
12982
+ logger.debug(`[PostgresInstrumentation] Replay transaction callback completed with result`);
12983
+ return result;
12984
+ } catch (error) {
12985
+ if (!wasCommitted) throw error;
12986
+ logger.error(`[PostgresInstrumentation] Unexpected error during transaction replay: ${error.message}`);
12987
+ throw error;
12988
+ }
12989
+ }
12990
+ /**
12991
+ * Creates a minimal mock SQL instance for transaction replay.
12992
+ * _wrapSqlInstance will wrap this and handle all the actual REPLAY logic.
12993
+ * The mock just needs to return objects with .then() methods that can be wrapped.
12994
+ */
12995
+ _createMockTransactionSql() {
12996
+ const self = this;
12997
+ const createThenable = () => ({ then: (onFulfilled, onRejected) => Promise.resolve([]).then(onFulfilled, onRejected) });
12998
+ const mockSql = function() {
12999
+ return createThenable();
13000
+ };
13001
+ mockSql.unsafe = function() {
13002
+ return createThenable();
13003
+ };
13004
+ mockSql.savepoint = function(nameOrFn, fn) {
13005
+ const callback = typeof nameOrFn === "function" ? nameOrFn : fn;
13006
+ const nestedMockSql = self._createMockTransactionSql();
13007
+ return Promise.resolve(callback(nestedMockSql));
13008
+ };
13009
+ return mockSql;
13010
+ }
13011
+ /**
13012
+ * Generic helper to find mock data for replay operations.
13013
+ * Consolidates the common findMockResponseAsync pattern used across multiple handlers.
13014
+ */
13015
+ async _findMockData({ spanInfo, name, inputValue, submoduleName, stackTrace }) {
13016
+ return findMockResponseAsync({
13017
+ mockRequestData: {
13018
+ traceId: spanInfo.traceId,
13019
+ spanId: spanInfo.spanId,
13020
+ name,
13021
+ inputValue: createMockInputValue(inputValue),
13022
+ packageName: "postgres",
13023
+ instrumentationName: this.INSTRUMENTATION_NAME,
13024
+ submoduleName,
13025
+ kind: import_src$25.SpanKind.CLIENT,
13026
+ stackTrace
13027
+ },
13028
+ tuskDrift: this.tuskDrift
13029
+ });
13030
+ }
13031
+ /**
13032
+ * Helper to end a cursor span with collected rows.
13033
+ * Consolidates common span ending logic used in cursor and forEach operations.
13034
+ */
13035
+ _endCursorSpan(spanInfo, allRows, result, operation = "Cursor") {
13036
+ addOutputAttributesToSpan(spanInfo, Object.assign(allRows, {
13037
+ count: allRows.length,
13038
+ columns: result?.columns,
13039
+ state: result?.state,
13040
+ statement: result?.statement
13041
+ }));
13042
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13043
+ logger.debug(`[PostgresInstrumentation] ${operation} completed, recorded ${allRows.length} rows`);
13044
+ }
13045
+ /**
13046
+ * Generic helper to handle replay for query operations (sql, unsafe, file).
13047
+ * Consolidates common logic for finding mock data and processing results.
13048
+ */
13049
+ async _handleReplayQueryOperation({ inputValue, spanInfo, submodule, name, stackTrace, operationType }) {
13050
+ logger.debug(`[PostgresInstrumentation] Replaying Postgres ${operationType} query`);
13051
+ const mockData = await this._findMockData({
13052
+ spanInfo,
13053
+ name,
13054
+ inputValue,
13055
+ submoduleName: submodule,
13056
+ stackTrace
13057
+ });
13058
+ if (!mockData) {
13059
+ const errorMsg = `[PostgresInstrumentation] No matching mock found for Postgres ${operationType} query: ${inputValue.query || "UNKNOWN_QUERY"}`;
13060
+ logger.warn(errorMsg);
13061
+ throw new Error(errorMsg);
13062
+ }
13063
+ logger.debug(`[PostgresInstrumentation] Found mock data for Postgres ${operationType} query: ${JSON.stringify(mockData)}`);
13064
+ const processedResult = convertPostgresTypes(mockData.result);
13065
+ logger.debug(`[PostgresInstrumentation] ${operationType} query processed result: ${JSON.stringify(processedResult)}`);
13066
+ return processedResult;
13067
+ }
13068
+ _handleCursorCallbackRecord({ originalCursor, rows, inputValue, creationContext, userCallback }) {
13069
+ const self = this;
13070
+ return import_src$25.context.with(creationContext, () => {
13071
+ return handleRecordMode({
13072
+ originalFunctionCall: () => originalCursor(rows, userCallback),
13073
+ recordModeHandler: ({ isPreAppStart }) => {
13074
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalCursor(rows, userCallback), {
13075
+ name: "postgres.cursor",
13076
+ kind: import_src$25.SpanKind.CLIENT,
13077
+ submodule: "cursor",
13078
+ packageType: PackageType.PG,
13079
+ packageName: "postgres",
13080
+ instrumentationName: self.INSTRUMENTATION_NAME,
13081
+ inputValue,
13082
+ isPreAppStart
13083
+ }, (spanInfo) => {
13084
+ return self._executeAndRecordCursorCallback({
13085
+ originalCursor,
13086
+ rows,
13087
+ userCallback,
13088
+ spanInfo
13089
+ });
13090
+ });
13091
+ },
13092
+ spanKind: import_src$25.SpanKind.CLIENT
13093
+ });
13094
+ });
13095
+ }
13096
+ async _executeAndRecordCursorCallback({ originalCursor, rows, userCallback, spanInfo }) {
13097
+ const allRows = [];
13098
+ try {
13099
+ const wrappedCallback = (batchRows) => {
13100
+ allRows.push(...batchRows);
13101
+ return userCallback(batchRows);
13102
+ };
13103
+ const cursorPromise = originalCursor(rows, wrappedCallback);
13104
+ cursorPromise._tuskRecorded = true;
13105
+ const result = await cursorPromise;
13106
+ if (spanInfo) try {
13107
+ this._endCursorSpan(spanInfo, allRows, result, "Cursor callback");
13108
+ } catch (error) {
13109
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13110
+ }
13111
+ } catch (error) {
13112
+ logger.debug(`[PostgresInstrumentation] Cursor callback error: ${error.message}`);
13113
+ if (spanInfo) try {
13114
+ SpanUtils.endSpan(spanInfo.span, {
13115
+ code: import_src$25.SpanStatusCode.ERROR,
13116
+ message: error.message
13117
+ });
13118
+ } catch (error$1) {
13119
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13120
+ }
13121
+ throw error;
13122
+ }
13123
+ }
13124
+ _handleCursorCallbackReplay({ inputValue, creationContext, cursorBatchSize, userCallback }) {
13125
+ const self = this;
13126
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13127
+ return import_src$25.context.with(creationContext, () => {
13128
+ return handleReplayMode({
13129
+ noOpRequestHandler: () => Promise.resolve(),
13130
+ isServerRequest: false,
13131
+ replayModeHandler: () => {
13132
+ return SpanUtils.createAndExecuteSpan(self.mode, () => Promise.resolve(), {
13133
+ name: "postgres.cursor",
13134
+ kind: import_src$25.SpanKind.CLIENT,
13135
+ submodule: "cursor",
13136
+ packageType: PackageType.PG,
13137
+ packageName: "postgres",
13138
+ instrumentationName: self.INSTRUMENTATION_NAME,
13139
+ inputValue,
13140
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13141
+ }, async (spanInfo) => {
13142
+ try {
13143
+ const mockData = await this._findMockData({
13144
+ spanInfo,
13145
+ name: "postgres.cursor",
13146
+ inputValue,
13147
+ submoduleName: "cursor",
13148
+ stackTrace
13149
+ });
13150
+ if (!mockData) throw new Error(`[PostgresInstrumentation] No matching mock found for cursor query: ${inputValue.query}`);
13151
+ logger.debug(`[PostgresInstrumentation] Found mock data for cursor query: ${JSON.stringify(mockData)}`);
13152
+ const processedResult = convertPostgresTypes(mockData.result);
13153
+ const mockedData = Array.isArray(processedResult) ? processedResult : [];
13154
+ for (let i = 0; i < mockedData.length; i += cursorBatchSize) {
13155
+ const batch = mockedData.slice(i, i + cursorBatchSize);
13156
+ logger.debug(`[PostgresInstrumentation] Cursor replay calling callback with batch of ${batch.length} rows`);
13157
+ await userCallback(batch);
13158
+ }
13159
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13160
+ } catch (error) {
13161
+ logger.debug(`[PostgresInstrumentation] Cursor callback replay error: ${error.message}`);
13162
+ SpanUtils.endSpan(spanInfo.span, {
13163
+ code: import_src$25.SpanStatusCode.ERROR,
13164
+ message: error.message
13165
+ });
13166
+ throw error;
13167
+ }
13168
+ });
12642
13169
  }
12643
- }).catch((error) => {
12644
- logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12645
- try {
12646
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12647
- status: "rolled_back",
12648
- error: error.message
12649
- } });
12650
- SpanUtils.endSpan(spanInfo.span, {
12651
- code: import_src$25.SpanStatusCode.ERROR,
12652
- message: error.message
13170
+ });
13171
+ });
13172
+ }
13173
+ _handleCursorRecord({ originalCursor, rows, inputValue, creationContext, queryObject }) {
13174
+ const self = this;
13175
+ return { [Symbol.asyncIterator]() {
13176
+ const iterator = originalCursor(rows)[Symbol.asyncIterator]();
13177
+ let allRows = [];
13178
+ let result;
13179
+ let spanInfo = null;
13180
+ let spanStarted = false;
13181
+ return {
13182
+ async next() {
13183
+ return import_src$25.context.with(creationContext, async () => {
13184
+ if (!spanStarted) {
13185
+ spanStarted = true;
13186
+ let spanInputValue;
13187
+ try {
13188
+ spanInputValue = createSpanInputValue(inputValue);
13189
+ } catch (error) {
13190
+ logger.error(`[PostgresInstrumentation] error creating span input value:`, error);
13191
+ spanInputValue = void 0;
13192
+ }
13193
+ spanInfo = SpanUtils.createSpan({
13194
+ name: "postgres.cursor",
13195
+ kind: import_src$25.SpanKind.CLIENT,
13196
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true,
13197
+ attributes: {
13198
+ [TdSpanAttributes.NAME]: "postgres.cursor",
13199
+ [TdSpanAttributes.PACKAGE_NAME]: "postgres",
13200
+ [TdSpanAttributes.SUBMODULE_NAME]: "cursor",
13201
+ [TdSpanAttributes.INSTRUMENTATION_NAME]: self.INSTRUMENTATION_NAME,
13202
+ [TdSpanAttributes.PACKAGE_TYPE]: PackageType.PG,
13203
+ [TdSpanAttributes.INPUT_VALUE]: spanInputValue,
13204
+ [TdSpanAttributes.IS_PRE_APP_START]: self.tuskDrift.isAppReady() ? false : true
13205
+ }
13206
+ });
13207
+ if (!spanInfo) logger.warn(`[PostgresInstrumentation] Failed to create cursor span in RECORD mode`);
13208
+ }
13209
+ try {
13210
+ result = await iterator.next();
13211
+ if (result.done) {
13212
+ if (spanInfo) try {
13213
+ self._endCursorSpan(spanInfo, allRows, queryObject, "Cursor");
13214
+ } catch (error) {
13215
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13216
+ }
13217
+ return {
13218
+ done: true,
13219
+ value: void 0
13220
+ };
13221
+ }
13222
+ if (Array.isArray(result.value)) allRows.push(...result.value);
13223
+ return {
13224
+ done: false,
13225
+ value: result.value
13226
+ };
13227
+ } catch (error) {
13228
+ if (spanInfo) try {
13229
+ SpanUtils.endSpan(spanInfo.span, {
13230
+ code: import_src$25.SpanStatusCode.ERROR,
13231
+ message: error.message
13232
+ });
13233
+ } catch (error$1) {
13234
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13235
+ }
13236
+ throw error;
13237
+ }
13238
+ });
13239
+ },
13240
+ async return() {
13241
+ if (spanInfo) try {
13242
+ self._endCursorSpan(spanInfo, allRows, queryObject, "Cursor terminated early");
13243
+ } catch (error) {
13244
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13245
+ }
13246
+ if (iterator.return) await iterator.return();
13247
+ return {
13248
+ done: true,
13249
+ value: void 0
13250
+ };
13251
+ }
13252
+ };
13253
+ } };
13254
+ }
13255
+ _handleCursorReplay({ inputValue, creationContext, cursorBatchSize }) {
13256
+ const self = this;
13257
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13258
+ return { [Symbol.asyncIterator]() {
13259
+ let mockedData = null;
13260
+ let currentIndex = 0;
13261
+ let spanInfo = null;
13262
+ let dataFetched = false;
13263
+ return {
13264
+ async next() {
13265
+ return import_src$25.context.with(creationContext, async () => {
13266
+ if (!dataFetched) {
13267
+ dataFetched = true;
13268
+ spanInfo = SpanUtils.createSpan({
13269
+ name: "postgres.cursor",
13270
+ kind: import_src$25.SpanKind.CLIENT,
13271
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true,
13272
+ attributes: {
13273
+ [TdSpanAttributes.NAME]: "postgres.cursor",
13274
+ [TdSpanAttributes.PACKAGE_NAME]: "postgres",
13275
+ [TdSpanAttributes.SUBMODULE_NAME]: "cursor",
13276
+ [TdSpanAttributes.INSTRUMENTATION_NAME]: self.INSTRUMENTATION_NAME,
13277
+ [TdSpanAttributes.PACKAGE_TYPE]: PackageType.PG,
13278
+ [TdSpanAttributes.INPUT_VALUE]: createSpanInputValue(inputValue),
13279
+ [TdSpanAttributes.IS_PRE_APP_START]: self.tuskDrift.isAppReady() ? false : true
13280
+ }
13281
+ });
13282
+ if (!spanInfo) throw new Error(`[PostgresInstrumentation] Failed to create cursor span in REPLAY mode`);
13283
+ const mockData = await self._findMockData({
13284
+ spanInfo,
13285
+ name: "postgres.cursor",
13286
+ inputValue,
13287
+ submoduleName: "cursor",
13288
+ stackTrace
13289
+ });
13290
+ if (!mockData) {
13291
+ SpanUtils.endSpan(spanInfo.span, {
13292
+ code: import_src$25.SpanStatusCode.ERROR,
13293
+ message: "No mock data found"
13294
+ });
13295
+ throw new Error(`[PostgresInstrumentation] No matching mock found for cursor query: ${inputValue.query}`);
13296
+ }
13297
+ logger.debug(`[PostgresInstrumentation] Found mock data for cursor query: ${JSON.stringify(mockData)}`);
13298
+ const processedResult = convertPostgresTypes(mockData.result);
13299
+ mockedData = Array.isArray(processedResult) ? processedResult : [];
13300
+ }
13301
+ if (currentIndex >= mockedData.length) {
13302
+ if (spanInfo) SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13303
+ return {
13304
+ done: true,
13305
+ value: void 0
13306
+ };
13307
+ }
13308
+ const batch = mockedData.slice(currentIndex, currentIndex + cursorBatchSize);
13309
+ currentIndex += batch.length;
13310
+ logger.debug(`[PostgresInstrumentation] Cursor replay returning batch of ${batch.length} rows`);
13311
+ return {
13312
+ done: false,
13313
+ value: batch
13314
+ };
13315
+ });
13316
+ },
13317
+ async return() {
13318
+ if (spanInfo) SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13319
+ return {
13320
+ done: true,
13321
+ value: void 0
13322
+ };
13323
+ }
13324
+ };
13325
+ } };
13326
+ }
13327
+ _handleForEachRecord({ originalForEach, inputValue, creationContext, userCallback }) {
13328
+ const self = this;
13329
+ return import_src$25.context.with(creationContext, () => {
13330
+ return handleRecordMode({
13331
+ originalFunctionCall: () => originalForEach(userCallback),
13332
+ recordModeHandler: ({ isPreAppStart }) => {
13333
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalForEach(userCallback), {
13334
+ name: "postgres.query",
13335
+ kind: import_src$25.SpanKind.CLIENT,
13336
+ submodule: "query",
13337
+ packageType: PackageType.PG,
13338
+ packageName: "postgres",
13339
+ instrumentationName: self.INSTRUMENTATION_NAME,
13340
+ inputValue,
13341
+ isPreAppStart
13342
+ }, async (spanInfo) => {
13343
+ const allRows = [];
13344
+ const wrappedCallback = (row, result) => {
13345
+ allRows.push(row);
13346
+ return userCallback(row, result);
13347
+ };
13348
+ try {
13349
+ const result = await originalForEach(wrappedCallback);
13350
+ try {
13351
+ self._endCursorSpan(spanInfo, allRows, result, "forEach");
13352
+ } catch (error) {
13353
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13354
+ }
13355
+ return result;
13356
+ } catch (error) {
13357
+ try {
13358
+ SpanUtils.endSpan(spanInfo.span, {
13359
+ code: import_src$25.SpanStatusCode.ERROR,
13360
+ message: error.message
13361
+ });
13362
+ } catch (error$1) {
13363
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13364
+ }
13365
+ throw error;
13366
+ }
13367
+ });
13368
+ },
13369
+ spanKind: import_src$25.SpanKind.CLIENT
13370
+ });
13371
+ });
13372
+ }
13373
+ _handleForEachReplay({ inputValue, creationContext, userCallback }) {
13374
+ const self = this;
13375
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13376
+ return import_src$25.context.with(creationContext, () => {
13377
+ return handleReplayMode({
13378
+ noOpRequestHandler: () => Promise.resolve(Object.assign([], {
13379
+ count: 0,
13380
+ command: null
13381
+ })),
13382
+ isServerRequest: false,
13383
+ replayModeHandler: () => {
13384
+ return SpanUtils.createAndExecuteSpan(self.mode, () => Promise.resolve(Object.assign([], {
13385
+ count: 0,
13386
+ command: null
13387
+ })), {
13388
+ name: "postgres.query",
13389
+ kind: import_src$25.SpanKind.CLIENT,
13390
+ submodule: "query",
13391
+ packageType: PackageType.PG,
13392
+ packageName: "postgres",
13393
+ instrumentationName: self.INSTRUMENTATION_NAME,
13394
+ inputValue,
13395
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13396
+ }, async (spanInfo) => {
13397
+ try {
13398
+ const mockedResult = await self._handleReplayQueryOperation({
13399
+ inputValue,
13400
+ spanInfo,
13401
+ submodule: "query",
13402
+ name: "postgres.query",
13403
+ stackTrace,
13404
+ operationType: "forEach"
13405
+ });
13406
+ const mockedRows = Array.isArray(mockedResult) ? mockedResult : [];
13407
+ logger.debug(`[PostgresInstrumentation] forEach replay: calling callback with ${mockedRows.length} mocked rows`);
13408
+ for (const row of mockedRows) userCallback(row, mockedResult);
13409
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13410
+ return Object.assign([], {
13411
+ count: mockedRows.length,
13412
+ command: null
13413
+ });
13414
+ } catch (error) {
13415
+ logger.debug(`[PostgresInstrumentation] forEach replay error: ${error.message}`);
13416
+ SpanUtils.endSpan(spanInfo.span, {
13417
+ code: import_src$25.SpanStatusCode.ERROR,
13418
+ message: error.message
13419
+ });
13420
+ throw error;
13421
+ }
13422
+ });
13423
+ }
13424
+ });
13425
+ });
13426
+ }
13427
+ /**
13428
+ * Wraps a query's .then() method to add instrumentation.
13429
+ * This is reusable for both sql template literals and unsafe() queries.
13430
+ */
13431
+ _wrapThenMethod(query, originalThen, inputValue, creationContext, spanConfig) {
13432
+ const self = this;
13433
+ query.then = function(onFulfilled, onRejected) {
13434
+ if (query._forEachCalled) return originalThen(onFulfilled, onRejected);
13435
+ if (query._tuskRecorded) return originalThen(onFulfilled, onRejected);
13436
+ query._tuskRecorded = true;
13437
+ return import_src$25.context.with(creationContext, () => {
13438
+ if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
13439
+ originalFunctionCall: () => originalThen(onFulfilled, onRejected),
13440
+ recordModeHandler: ({ isPreAppStart }) => {
13441
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
13442
+ name: spanConfig.name,
13443
+ kind: import_src$25.SpanKind.CLIENT,
13444
+ submodule: spanConfig.submodule,
13445
+ packageType: PackageType.PG,
13446
+ packageName: "postgres",
13447
+ instrumentationName: self.INSTRUMENTATION_NAME,
13448
+ inputValue,
13449
+ isPreAppStart
13450
+ }, (spanInfo) => {
13451
+ const wrappedOnFulfilled = (result) => {
13452
+ try {
13453
+ logger.debug(`[PostgresInstrumentation] Postgres ${spanConfig.operationType} query completed successfully (${SpanUtils.getTraceInfo()})`);
13454
+ addOutputAttributesToSpan(spanInfo, result);
13455
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13456
+ } catch (error) {
13457
+ logger.error(`[PostgresInstrumentation] error processing ${spanConfig.operationType} query response:`, error);
13458
+ }
13459
+ return onFulfilled ? onFulfilled(result) : result;
13460
+ };
13461
+ const wrappedOnRejected = (error) => {
13462
+ try {
13463
+ logger.debug(`[PostgresInstrumentation] Postgres ${spanConfig.operationType} query error: ${error.message}`);
13464
+ SpanUtils.endSpan(spanInfo.span, {
13465
+ code: import_src$25.SpanStatusCode.ERROR,
13466
+ message: error.message
13467
+ });
13468
+ } catch (spanError) {
13469
+ logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
13470
+ }
13471
+ if (onRejected) return onRejected(error);
13472
+ throw error;
13473
+ };
13474
+ return originalThen(wrappedOnFulfilled, wrappedOnRejected);
13475
+ });
13476
+ },
13477
+ spanKind: import_src$25.SpanKind.CLIENT
13478
+ });
13479
+ else if (self.mode === TuskDriftMode.REPLAY) {
13480
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13481
+ return handleReplayMode({
13482
+ noOpRequestHandler: () => Promise.resolve(Object.assign([], {
13483
+ count: 0,
13484
+ command: null
13485
+ })),
13486
+ isServerRequest: false,
13487
+ replayModeHandler: () => {
13488
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
13489
+ name: spanConfig.name,
13490
+ kind: import_src$25.SpanKind.CLIENT,
13491
+ submodule: spanConfig.submodule,
13492
+ packageType: PackageType.PG,
13493
+ packageName: "postgres",
13494
+ instrumentationName: self.INSTRUMENTATION_NAME,
13495
+ inputValue,
13496
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13497
+ }, async (spanInfo) => {
13498
+ const mockedResult = await self._handleReplayQueryOperation({
13499
+ inputValue,
13500
+ spanInfo,
13501
+ submodule: spanConfig.submodule,
13502
+ name: spanConfig.name,
13503
+ stackTrace,
13504
+ operationType: spanConfig.operationType
13505
+ });
13506
+ return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
13507
+ });
13508
+ }
12653
13509
  });
12654
- } catch (spanError) {
12655
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12656
- }
13510
+ } else return originalThen(onFulfilled, onRejected);
12657
13511
  });
12658
- });
12659
- return promise;
12660
- }
12661
- async _handleReplayBeginTransaction(spanInfo, options, stackTrace) {
12662
- logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
12663
- const mockData = await findMockResponseAsync({
12664
- mockRequestData: {
12665
- traceId: spanInfo.traceId,
12666
- spanId: spanInfo.spanId,
12667
- name: "postgres.begin",
12668
- inputValue: createMockInputValue({
12669
- query: "BEGIN",
12670
- options: options ? { transactionOptions: options } : void 0
12671
- }),
12672
- packageName: "postgres",
12673
- instrumentationName: this.INSTRUMENTATION_NAME,
12674
- submoduleName: "transaction",
12675
- kind: import_src$25.SpanKind.CLIENT,
12676
- stackTrace
12677
- },
12678
- tuskDrift: this.tuskDrift
12679
- });
12680
- if (!mockData) {
12681
- logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
12682
- throw new Error(`[PostgresInstrumentation] No matching mock found for transaction BEGIN`);
12683
- }
12684
- logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
12685
- const transactionResult = mockData.result;
12686
- if (transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed") return transactionResult.result;
12687
- else {
12688
- const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
12689
- throw new Error(errorMessage);
12690
- }
12691
- }
12692
- async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12693
- logger.debug(`[PostgresInstrumentation] Replaying Postgres sql query`);
12694
- const mockData = await findMockResponseAsync({
12695
- mockRequestData: {
12696
- traceId: spanInfo.traceId,
12697
- spanId: spanInfo.spanId,
12698
- name,
12699
- inputValue: createMockInputValue(inputValue),
12700
- packageName: "postgres",
12701
- instrumentationName: this.INSTRUMENTATION_NAME,
12702
- submoduleName: submodule,
12703
- kind: import_src$25.SpanKind.CLIENT,
12704
- stackTrace
12705
- },
12706
- tuskDrift: this.tuskDrift
12707
- });
12708
- if (!mockData) {
12709
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12710
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres sql query: ${queryText}`);
12711
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres sql query: ${queryText}`);
12712
- }
12713
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres sql query: ${JSON.stringify(mockData)}`);
12714
- const processedResult = this.convertPostgresTypes(mockData.result);
12715
- logger.debug(`[PostgresInstrumentation] Sql query processed result: ${JSON.stringify(processedResult)}`);
12716
- return processedResult;
13512
+ };
12717
13513
  }
12718
- async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12719
- logger.debug(`[PostgresInstrumentation] Replaying Postgres unsafe query`);
12720
- const mockData = await findMockResponseAsync({
12721
- mockRequestData: {
12722
- traceId: spanInfo.traceId,
12723
- spanId: spanInfo.spanId,
12724
- name,
12725
- inputValue: createMockInputValue(inputValue),
12726
- packageName: "postgres",
12727
- instrumentationName: this.INSTRUMENTATION_NAME,
12728
- submoduleName: submodule,
12729
- kind: import_src$25.SpanKind.CLIENT,
12730
- stackTrace
12731
- },
12732
- tuskDrift: this.tuskDrift
12733
- });
12734
- if (!mockData) {
12735
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12736
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres unsafe query: ${queryText}`);
12737
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres unsafe query: ${queryText}`);
12738
- }
12739
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres unsafe query: ${JSON.stringify(mockData)}`);
12740
- const processedResult = this.convertPostgresTypes(mockData.result);
12741
- logger.debug(`[PostgresInstrumentation] Unsafe query processed result: ${JSON.stringify(processedResult)}`);
12742
- return processedResult;
13514
+ /**
13515
+ * Wraps a query's .execute() method to prevent TCP calls in REPLAY mode.
13516
+ * This is reusable for both sql template literals and unsafe() queries.
13517
+ */
13518
+ _wrapExecuteMethod(query) {
13519
+ const self = this;
13520
+ const originalExecute = query.execute ? query.execute.bind(query) : void 0;
13521
+ if (originalExecute) query.execute = function() {
13522
+ if (self.mode === TuskDriftMode.REPLAY) return this;
13523
+ else return originalExecute.call(this);
13524
+ };
12743
13525
  }
12744
- convertPostgresTypes(result) {
12745
- if (!isPostgresOutputValueType(result)) {
12746
- logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12747
- return;
12748
- }
12749
- const { rows, count, command } = result;
12750
- const resultArray = Array.from(rows || []);
12751
- Object.defineProperties(resultArray, {
12752
- count: {
12753
- value: count !== void 0 ? count : null,
12754
- writable: true,
12755
- enumerable: false
12756
- },
12757
- command: {
12758
- value: command || null,
12759
- writable: true,
12760
- enumerable: false
12761
- }
12762
- });
12763
- return resultArray;
13526
+ /**
13527
+ * Wraps a query's cursor() method to add instrumentation.
13528
+ * This is reusable for both sql template literals and unsafe() queries.
13529
+ */
13530
+ _wrapCursorMethod(query, inputValue, creationContext) {
13531
+ if (typeof query.cursor !== "function") return;
13532
+ const self = this;
13533
+ const originalCursor = query.cursor.bind(query);
13534
+ query.cursor = function(rows, fn) {
13535
+ if (typeof rows === "function") {
13536
+ fn = rows;
13537
+ rows = 1;
13538
+ }
13539
+ if (!rows) rows = 1;
13540
+ if (typeof fn === "function") if (self.mode === TuskDriftMode.RECORD) return self._handleCursorCallbackRecord({
13541
+ originalCursor,
13542
+ rows,
13543
+ inputValue,
13544
+ creationContext,
13545
+ userCallback: fn
13546
+ });
13547
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleCursorCallbackReplay({
13548
+ inputValue,
13549
+ creationContext,
13550
+ cursorBatchSize: rows,
13551
+ userCallback: fn
13552
+ });
13553
+ else return originalCursor(rows, fn);
13554
+ if (self.mode === TuskDriftMode.RECORD) return self._handleCursorRecord({
13555
+ originalCursor,
13556
+ rows,
13557
+ inputValue,
13558
+ creationContext,
13559
+ queryObject: this
13560
+ });
13561
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleCursorReplay({
13562
+ inputValue,
13563
+ creationContext,
13564
+ cursorBatchSize: rows
13565
+ });
13566
+ else return originalCursor(rows);
13567
+ };
12764
13568
  }
12765
- _addOutputAttributesToSpan(spanInfo, result) {
12766
- if (!result) return;
12767
- const isArray$1 = Array.isArray(result);
12768
- logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12769
- const outputValue = {
12770
- rows: isArray$1 ? Array.from(result) : result.rows || [],
12771
- count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12772
- command: result.command || void 0
13569
+ /**
13570
+ * Wraps a query's forEach() method to add instrumentation.
13571
+ * This is reusable for both sql template literals and unsafe() queries.
13572
+ */
13573
+ _wrapForEachMethod(query, inputValue, creationContext) {
13574
+ if (typeof query.forEach !== "function") return;
13575
+ const self = this;
13576
+ const originalForEach = query.forEach.bind(query);
13577
+ query.forEach = function(fn) {
13578
+ query._forEachCalled = true;
13579
+ if (self.mode === TuskDriftMode.RECORD) return self._handleForEachRecord({
13580
+ originalForEach,
13581
+ inputValue,
13582
+ creationContext,
13583
+ userCallback: fn
13584
+ });
13585
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleForEachReplay({
13586
+ inputValue,
13587
+ creationContext,
13588
+ userCallback: fn
13589
+ });
13590
+ else return originalForEach(fn);
12773
13591
  };
12774
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12775
13592
  }
12776
13593
  _wrap(target, propertyName, wrapper) {
12777
13594
  wrap(target, propertyName, wrapper);
@@ -12794,8 +13611,9 @@ function isMysqlOkPacket(result) {
12794
13611
  * Extends EventEmitter to properly handle all connection methods and events
12795
13612
  */
12796
13613
  var TdMysqlConnectionMock = class extends EventEmitter {
12797
- constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo) {
13614
+ constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo, pool) {
12798
13615
  super();
13616
+ this._pool = null;
12799
13617
  this.threadId = null;
12800
13618
  this.config = {
12801
13619
  host: "localhost",
@@ -12807,6 +13625,7 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12807
13625
  this.spanInfo = spanInfo;
12808
13626
  this.clientType = clientType;
12809
13627
  this.threadId = 1;
13628
+ this._pool = pool;
12810
13629
  }
12811
13630
  query(...args) {
12812
13631
  logger.debug(`[TdMysqlConnectionMock] Mock connection query intercepted in REPLAY mode`);
@@ -12814,7 +13633,13 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12814
13633
  let values;
12815
13634
  let callback;
12816
13635
  let options = {};
12817
- if (typeof args[0] === "string") {
13636
+ const firstArg = args[0];
13637
+ if (firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function") {
13638
+ sql = firstArg.sql;
13639
+ values = firstArg.values;
13640
+ callback = firstArg._callback;
13641
+ options = { nestTables: firstArg.nestTables };
13642
+ } else if (typeof args[0] === "string") {
12818
13643
  sql = args[0];
12819
13644
  if (typeof args[1] === "function") callback = args[1];
12820
13645
  else if (Array.isArray(args[1])) {
@@ -12866,6 +13691,7 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12866
13691
  }
12867
13692
  }
12868
13693
  release() {
13694
+ if (this._pool) this._pool.emit("release", this);
12869
13695
  this.emit("end");
12870
13696
  }
12871
13697
  destroy() {
@@ -12890,19 +13716,22 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12890
13716
  return;
12891
13717
  }
12892
13718
  }
12893
- beginTransaction(callback) {
13719
+ beginTransaction(optionsOrCallback, callbackArg) {
13720
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
12894
13721
  if (callback) {
12895
13722
  process.nextTick(() => callback(null));
12896
13723
  return;
12897
13724
  }
12898
13725
  }
12899
- commit(callback) {
13726
+ commit(optionsOrCallback, callbackArg) {
13727
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
12900
13728
  if (callback) {
12901
13729
  process.nextTick(() => callback(null));
12902
13730
  return;
12903
13731
  }
12904
13732
  }
12905
- rollback(callback) {
13733
+ rollback(optionsOrCallback, callbackArg) {
13734
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
12906
13735
  if (callback) {
12907
13736
  process.nextTick(() => callback(null));
12908
13737
  return;
@@ -13098,6 +13927,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13098
13927
  name: "mysql/lib/Pool.js",
13099
13928
  supportedVersions: ["2.*"],
13100
13929
  patch: (moduleExports) => this._patchPoolFile(moduleExports)
13930
+ }),
13931
+ new TdInstrumentationNodeModuleFile({
13932
+ name: "mysql/lib/PoolNamespace.js",
13933
+ supportedVersions: ["2.*"],
13934
+ patch: (moduleExports) => this._patchPoolNamespaceFile(moduleExports)
13101
13935
  })
13102
13936
  ]
13103
13937
  })];
@@ -13237,12 +14071,40 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13237
14071
  return PoolClass;
13238
14072
  }
13239
14073
  /**
14074
+ * Patch PoolNamespace.prototype methods at the file level
14075
+ * This handles queries made via poolCluster.of("pattern").query()
14076
+ */
14077
+ _patchPoolNamespaceFile(PoolNamespaceClass) {
14078
+ logger.debug(`[MysqlInstrumentation] Patching PoolNamespace class (file-based)`);
14079
+ if (this.isModulePatched(PoolNamespaceClass)) {
14080
+ logger.debug(`[MysqlInstrumentation] PoolNamespace class already patched, skipping`);
14081
+ return PoolNamespaceClass;
14082
+ }
14083
+ if (PoolNamespaceClass.prototype && PoolNamespaceClass.prototype.query) {
14084
+ if (!isWrapped$1(PoolNamespaceClass.prototype.query)) {
14085
+ this._wrap(PoolNamespaceClass.prototype, "query", this._getPoolNamespaceQueryPatchFn());
14086
+ logger.debug(`[MysqlInstrumentation] Wrapped PoolNamespace.prototype.query`);
14087
+ }
14088
+ }
14089
+ if (PoolNamespaceClass.prototype && PoolNamespaceClass.prototype.getConnection) {
14090
+ if (!isWrapped$1(PoolNamespaceClass.prototype.getConnection)) {
14091
+ this._wrap(PoolNamespaceClass.prototype, "getConnection", this._getPoolNamespaceGetConnectionPatchFn());
14092
+ logger.debug(`[MysqlInstrumentation] Wrapped PoolNamespace.prototype.getConnection`);
14093
+ }
14094
+ }
14095
+ this.markModuleAsPatched(PoolNamespaceClass);
14096
+ logger.debug(`[MysqlInstrumentation] PoolNamespace class patching complete`);
14097
+ return PoolNamespaceClass;
14098
+ }
14099
+ /**
13240
14100
  * Get wrapper function for query method (prototype-level patching)
13241
14101
  */
13242
14102
  _getQueryPatchFn() {
13243
14103
  const self = this;
13244
14104
  return (originalQuery) => {
13245
14105
  return function query(...args) {
14106
+ const firstArg = args[0];
14107
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13246
14108
  let sql;
13247
14109
  let values;
13248
14110
  let callback;
@@ -13253,6 +14115,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13253
14115
  values = queryObj.values;
13254
14116
  options = { nestTables: queryObj.nestTables };
13255
14117
  callback = args.find((arg) => typeof arg === "function");
14118
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13256
14119
  } catch (error) {
13257
14120
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13258
14121
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13263,7 +14126,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13263
14126
  values,
13264
14127
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13265
14128
  };
13266
- const isEventEmitterMode = !callback;
14129
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13267
14130
  if (self.mode === TuskDriftMode.REPLAY) {
13268
14131
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13269
14132
  return handleReplayMode({
@@ -13359,11 +14222,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13359
14222
  _getBeginTransactionPatchFn() {
13360
14223
  const self = this;
13361
14224
  return (originalBeginTransaction) => {
13362
- return function beginTransaction(callback) {
14225
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14226
+ let actualCallback;
14227
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14228
+ else actualCallback = callbackArg;
13363
14229
  const inputValue = { query: "BEGIN" };
13364
14230
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13365
14231
  noOpRequestHandler: () => {
13366
- if (callback) setImmediate(() => callback(null));
14232
+ if (actualCallback) setImmediate(() => actualCallback(null));
13367
14233
  },
13368
14234
  isServerRequest: false,
13369
14235
  replayModeHandler: () => {
@@ -13377,7 +14243,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13377
14243
  inputValue,
13378
14244
  isPreAppStart: false
13379
14245
  }, (spanInfo) => {
13380
- return self._handleReplayTransaction(inputValue, callback);
14246
+ return self._handleReplayTransaction(inputValue, actualCallback);
13381
14247
  });
13382
14248
  }
13383
14249
  });
@@ -13394,7 +14260,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13394
14260
  inputValue,
13395
14261
  isPreAppStart
13396
14262
  }, (spanInfo) => {
13397
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, callback);
14263
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, actualCallback);
13398
14264
  });
13399
14265
  },
13400
14266
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13409,11 +14275,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13409
14275
  _getCommitPatchFn() {
13410
14276
  const self = this;
13411
14277
  return (originalCommit) => {
13412
- return function commit(callback) {
14278
+ return function commit(optionsOrCallback, callbackArg) {
14279
+ let actualCallback;
14280
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14281
+ else actualCallback = callbackArg;
13413
14282
  const inputValue = { query: "COMMIT" };
13414
14283
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13415
14284
  noOpRequestHandler: () => {
13416
- if (callback) setImmediate(() => callback(null));
14285
+ if (actualCallback) setImmediate(() => actualCallback(null));
13417
14286
  },
13418
14287
  isServerRequest: false,
13419
14288
  replayModeHandler: () => {
@@ -13427,7 +14296,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13427
14296
  inputValue,
13428
14297
  isPreAppStart: false
13429
14298
  }, (spanInfo) => {
13430
- return self._handleReplayTransaction(inputValue, callback);
14299
+ return self._handleReplayTransaction(inputValue, actualCallback);
13431
14300
  });
13432
14301
  }
13433
14302
  });
@@ -13444,7 +14313,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13444
14313
  inputValue,
13445
14314
  isPreAppStart
13446
14315
  }, (spanInfo) => {
13447
- return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, callback);
14316
+ return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, actualCallback);
13448
14317
  });
13449
14318
  },
13450
14319
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13459,11 +14328,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13459
14328
  _getRollbackPatchFn() {
13460
14329
  const self = this;
13461
14330
  return (originalRollback) => {
13462
- return function rollback(callback) {
14331
+ return function rollback(optionsOrCallback, callbackArg) {
14332
+ let actualCallback;
14333
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14334
+ else actualCallback = callbackArg;
13463
14335
  const inputValue = { query: "ROLLBACK" };
13464
14336
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13465
14337
  noOpRequestHandler: () => {
13466
- if (callback) setImmediate(() => callback(null));
14338
+ if (actualCallback) setImmediate(() => actualCallback(null));
13467
14339
  },
13468
14340
  isServerRequest: false,
13469
14341
  replayModeHandler: () => {
@@ -13477,7 +14349,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13477
14349
  inputValue,
13478
14350
  isPreAppStart: false
13479
14351
  }, (spanInfo) => {
13480
- return self._handleReplayTransaction(inputValue, callback);
14352
+ return self._handleReplayTransaction(inputValue, actualCallback);
13481
14353
  });
13482
14354
  }
13483
14355
  });
@@ -13494,7 +14366,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13494
14366
  inputValue,
13495
14367
  isPreAppStart
13496
14368
  }, (spanInfo) => {
13497
- return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, callback);
14369
+ return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, actualCallback);
13498
14370
  });
13499
14371
  },
13500
14372
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13662,9 +14534,10 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13662
14534
  return (originalGetConnection) => {
13663
14535
  return function getConnection(callback) {
13664
14536
  const inputValue = { clientType: "pool" };
14537
+ const pool = this;
13665
14538
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13666
14539
  noOpRequestHandler: () => {
13667
- return self._handleNoOpReplayGetConnection(callback);
14540
+ return self._handleNoOpReplayGetConnection(pool, callback);
13668
14541
  },
13669
14542
  isServerRequest: false,
13670
14543
  replayModeHandler: () => {
@@ -13678,7 +14551,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13678
14551
  inputValue,
13679
14552
  isPreAppStart: false
13680
14553
  }, (spanInfo) => {
13681
- return self._handleReplayPoolGetConnection(spanInfo, callback);
14554
+ return self._handleReplayPoolGetConnection(pool, spanInfo, callback);
13682
14555
  });
13683
14556
  }
13684
14557
  });
@@ -13708,6 +14581,8 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13708
14581
  const self = this;
13709
14582
  return (originalQuery) => {
13710
14583
  return function query(...args) {
14584
+ const firstArg = args[0];
14585
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13711
14586
  let sql;
13712
14587
  let values;
13713
14588
  let callback;
@@ -13718,6 +14593,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13718
14593
  values = queryObj.values;
13719
14594
  options = { nestTables: queryObj.nestTables };
13720
14595
  callback = args.find((arg) => typeof arg === "function");
14596
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13721
14597
  } catch (error) {
13722
14598
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13723
14599
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13728,7 +14604,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13728
14604
  values,
13729
14605
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13730
14606
  };
13731
- const isEventEmitterMode = !callback;
14607
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13732
14608
  if (self.mode === TuskDriftMode.REPLAY) {
13733
14609
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13734
14610
  return handleReplayMode({
@@ -13830,6 +14706,33 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13830
14706
  });
13831
14707
  return queryEmitter;
13832
14708
  } else {
14709
+ const queryObject = args[0];
14710
+ if (queryObject && typeof queryObject === "object" && typeof queryObject._callback === "function") {
14711
+ const originalCallback$1 = queryObject._callback;
14712
+ queryObject._callback = function(err, results, fields) {
14713
+ if (err) try {
14714
+ SpanUtils.endSpan(spanInfo.span, {
14715
+ code: import_src$23.SpanStatusCode.ERROR,
14716
+ message: err.message
14717
+ });
14718
+ } catch (error) {
14719
+ logger.error(`[MysqlInstrumentation] error ending span:`, error);
14720
+ }
14721
+ else try {
14722
+ const outputValue = {
14723
+ results,
14724
+ fields
14725
+ };
14726
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
14727
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14728
+ } catch (error) {
14729
+ logger.error(`[MysqlInstrumentation] error ending span:`, error);
14730
+ }
14731
+ logger.debug(`[MysqlInstrumentation] Query completed`);
14732
+ originalCallback$1.call(this, err, results, fields);
14733
+ };
14734
+ return originalQuery.apply(connection, args);
14735
+ }
13833
14736
  const originalCallback = callback;
13834
14737
  const callbackIndex = args.findIndex((arg) => typeof arg === "function");
13835
14738
  args[callbackIndex] = function(err, results, fields) {
@@ -13884,11 +14787,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13884
14787
  _patchBeginTransaction(connection) {
13885
14788
  const self = this;
13886
14789
  return (originalBeginTransaction) => {
13887
- return function beginTransaction(callback) {
14790
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14791
+ let actualCallback;
14792
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14793
+ else actualCallback = callbackArg;
13888
14794
  const inputValue = { query: "BEGIN" };
13889
14795
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13890
14796
  noOpRequestHandler: () => {
13891
- if (callback) setImmediate(() => callback(null));
14797
+ if (actualCallback) setImmediate(() => actualCallback(null));
13892
14798
  },
13893
14799
  isServerRequest: false,
13894
14800
  replayModeHandler: () => {
@@ -13902,7 +14808,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13902
14808
  inputValue,
13903
14809
  isPreAppStart: false
13904
14810
  }, (spanInfo) => {
13905
- return self._handleReplayTransaction(inputValue, callback);
14811
+ return self._handleReplayTransaction(inputValue, actualCallback);
13906
14812
  });
13907
14813
  }
13908
14814
  });
@@ -13919,7 +14825,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13919
14825
  inputValue,
13920
14826
  isPreAppStart
13921
14827
  }, (spanInfo) => {
13922
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, callback);
14828
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, actualCallback);
13923
14829
  });
13924
14830
  },
13925
14831
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13931,11 +14837,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13931
14837
  _patchCommit(connection) {
13932
14838
  const self = this;
13933
14839
  return (originalCommit) => {
13934
- return function commit(callback) {
14840
+ return function commit(optionsOrCallback, callbackArg) {
14841
+ let actualCallback;
14842
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14843
+ else actualCallback = callbackArg;
13935
14844
  const inputValue = { query: "COMMIT" };
13936
14845
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13937
14846
  noOpRequestHandler: () => {
13938
- if (callback) setImmediate(() => callback(null));
14847
+ if (actualCallback) setImmediate(() => actualCallback(null));
13939
14848
  },
13940
14849
  isServerRequest: false,
13941
14850
  replayModeHandler: () => {
@@ -13949,7 +14858,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13949
14858
  inputValue,
13950
14859
  isPreAppStart: false
13951
14860
  }, (spanInfo) => {
13952
- return self._handleReplayTransaction(inputValue, callback);
14861
+ return self._handleReplayTransaction(inputValue, actualCallback);
13953
14862
  });
13954
14863
  }
13955
14864
  });
@@ -13966,7 +14875,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13966
14875
  inputValue,
13967
14876
  isPreAppStart
13968
14877
  }, (spanInfo) => {
13969
- return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, callback);
14878
+ return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, actualCallback);
13970
14879
  });
13971
14880
  },
13972
14881
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13978,11 +14887,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13978
14887
  _patchRollback(connection) {
13979
14888
  const self = this;
13980
14889
  return (originalRollback) => {
13981
- return function rollback(callback) {
14890
+ return function rollback(optionsOrCallback, callbackArg) {
14891
+ let actualCallback;
14892
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14893
+ else actualCallback = callbackArg;
13982
14894
  const inputValue = { query: "ROLLBACK" };
13983
14895
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13984
14896
  noOpRequestHandler: () => {
13985
- if (callback) setImmediate(() => callback(null));
14897
+ if (actualCallback) setImmediate(() => actualCallback(null));
13986
14898
  },
13987
14899
  isServerRequest: false,
13988
14900
  replayModeHandler: () => {
@@ -13996,7 +14908,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13996
14908
  inputValue,
13997
14909
  isPreAppStart: false
13998
14910
  }, (spanInfo) => {
13999
- return self._handleReplayTransaction(inputValue, callback);
14911
+ return self._handleReplayTransaction(inputValue, actualCallback);
14000
14912
  });
14001
14913
  }
14002
14914
  });
@@ -14013,7 +14925,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14013
14925
  inputValue,
14014
14926
  isPreAppStart
14015
14927
  }, (spanInfo) => {
14016
- return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, callback);
14928
+ return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, actualCallback);
14017
14929
  });
14018
14930
  },
14019
14931
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14046,7 +14958,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14046
14958
  const argsArray = Array.from(args);
14047
14959
  const callbackIndex = argsArray.findIndex((arg) => typeof arg === "function");
14048
14960
  if (callbackIndex !== -1) {
14049
- const originalCallback = callback;
14961
+ const originalCallback = argsArray[callbackIndex];
14050
14962
  argsArray[callbackIndex] = function(err) {
14051
14963
  if (err) try {
14052
14964
  SpanUtils.endSpan(spanInfo.span, {
@@ -14075,7 +14987,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14075
14987
  callback(null);
14076
14988
  });
14077
14989
  }
14078
- _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$6) {
14990
+ _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, poolContext) {
14079
14991
  const self = this;
14080
14992
  if (callback) {
14081
14993
  const wrappedCallback = (error, connection) => {
@@ -14100,11 +15012,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14100
15012
  } });
14101
15013
  SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14102
15014
  }
14103
- return callback(error, connection);
15015
+ return import_src$23.context.bind(spanInfo.context, callback)(error, connection);
14104
15016
  };
14105
- return originalGetConnection.call(context$6, wrappedCallback);
15017
+ return originalGetConnection.call(poolContext, wrappedCallback);
14106
15018
  } else try {
14107
- const result = originalGetConnection.call(context$6);
15019
+ const result = originalGetConnection.call(poolContext);
14108
15020
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
14109
15021
  connected: true,
14110
15022
  hasConnection: true
@@ -14119,20 +15031,28 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14119
15031
  throw error;
14120
15032
  }
14121
15033
  }
14122
- _handleNoOpReplayGetConnection(callback) {
15034
+ _handleNoOpReplayGetConnection(pool, callback) {
14123
15035
  logger.debug(`[MysqlInstrumentation] Background getConnection detected, returning mock connection`);
14124
- const mockConnection = new TdMysqlConnectionMock(this, "pool");
15036
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", void 0, pool);
14125
15037
  if (callback) {
14126
- process.nextTick(() => callback(null, mockConnection));
15038
+ process.nextTick(() => {
15039
+ pool.emit("connection", mockConnection);
15040
+ pool.emit("acquire", mockConnection);
15041
+ callback(null, mockConnection);
15042
+ });
14127
15043
  return;
14128
15044
  }
14129
15045
  return mockConnection;
14130
15046
  }
14131
- _handleReplayPoolGetConnection(spanInfo, callback) {
15047
+ _handleReplayPoolGetConnection(pool, spanInfo, callback) {
14132
15048
  logger.debug(`[MysqlInstrumentation] Replaying MySQL Pool getConnection`);
14133
- const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo);
15049
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo, pool);
14134
15050
  if (callback) {
14135
- process.nextTick(() => callback(null, mockConnection));
15051
+ process.nextTick(() => {
15052
+ pool.emit("connection", mockConnection);
15053
+ pool.emit("acquire", mockConnection);
15054
+ callback(null, mockConnection);
15055
+ });
14136
15056
  return;
14137
15057
  }
14138
15058
  return mockConnection;
@@ -14365,6 +15285,122 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14365
15285
  });
14366
15286
  return readableStream;
14367
15287
  }
15288
+ /**
15289
+ * Get wrapper function for PoolNamespace.query method
15290
+ * This handles queries made via poolCluster.of("pattern").query()
15291
+ */
15292
+ _getPoolNamespaceQueryPatchFn() {
15293
+ const self = this;
15294
+ return (originalQuery) => {
15295
+ return function query(...args) {
15296
+ const firstArg = args[0];
15297
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
15298
+ if (self.mode === TuskDriftMode.REPLAY) {
15299
+ let sql;
15300
+ let values;
15301
+ let callback;
15302
+ let options = {};
15303
+ if (self.createQuery) try {
15304
+ const queryObj = self.createQuery(...args);
15305
+ sql = queryObj.sql;
15306
+ values = queryObj.values;
15307
+ options = { nestTables: queryObj.nestTables };
15308
+ callback = args.find((arg) => typeof arg === "function");
15309
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
15310
+ } catch (error) {
15311
+ ({sql, values, callback, options} = self._parseQueryArgs(args));
15312
+ }
15313
+ else ({sql, values, callback, options} = self._parseQueryArgs(args));
15314
+ const inputValue = {
15315
+ sql,
15316
+ values,
15317
+ options: options.nestTables ? { nestTables: options.nestTables } : void 0
15318
+ };
15319
+ const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
15320
+ return handleReplayMode({
15321
+ noOpRequestHandler: () => {
15322
+ return self.queryMock.handleNoOpReplayQuery({
15323
+ sql,
15324
+ values,
15325
+ callback,
15326
+ options
15327
+ });
15328
+ },
15329
+ isServerRequest: false,
15330
+ replayModeHandler: () => {
15331
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
15332
+ name: "mysql.query",
15333
+ kind: import_src$23.SpanKind.CLIENT,
15334
+ submodule: "query",
15335
+ packageType: PackageType.MYSQL,
15336
+ packageName: "mysql",
15337
+ instrumentationName: self.INSTRUMENTATION_NAME,
15338
+ inputValue,
15339
+ isPreAppStart: false
15340
+ }, (spanInfo) => {
15341
+ const queryEmitter = self.queryMock.handleReplayQuery({
15342
+ sql,
15343
+ values,
15344
+ callback,
15345
+ options
15346
+ }, inputValue, spanInfo, stackTrace);
15347
+ if (queryEmitter && typeof queryEmitter === "object") queryEmitter.stream = function(streamOptions) {
15348
+ return self._createReplayStreamForQuery(inputValue, spanInfo, stackTrace, queryEmitter, streamOptions);
15349
+ };
15350
+ return queryEmitter;
15351
+ });
15352
+ }
15353
+ });
15354
+ } else if (self.mode === TuskDriftMode.RECORD) return originalQuery.apply(this, args);
15355
+ else return originalQuery.apply(this, args);
15356
+ };
15357
+ };
15358
+ }
15359
+ /**
15360
+ * Get wrapper function for PoolNamespace.getConnection method
15361
+ * This handles connections obtained via poolCluster.of("pattern").getConnection()
15362
+ */
15363
+ _getPoolNamespaceGetConnectionPatchFn() {
15364
+ const self = this;
15365
+ return (originalGetConnection) => {
15366
+ return function getConnection(callback) {
15367
+ const namespace = this;
15368
+ const inputValue = { clientType: "poolNamespace" };
15369
+ if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
15370
+ noOpRequestHandler: () => {
15371
+ const mockConnection = new TdMysqlConnectionMock(self, "pool", void 0, void 0);
15372
+ if (callback) {
15373
+ process.nextTick(() => callback(null, mockConnection));
15374
+ return;
15375
+ }
15376
+ return mockConnection;
15377
+ },
15378
+ isServerRequest: false,
15379
+ replayModeHandler: () => {
15380
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalGetConnection.apply(namespace, [callback]), {
15381
+ name: `mysql.poolNamespace.getConnection`,
15382
+ kind: import_src$23.SpanKind.CLIENT,
15383
+ submodule: "getConnection",
15384
+ packageName: "mysql",
15385
+ packageType: PackageType.MYSQL,
15386
+ instrumentationName: self.INSTRUMENTATION_NAME,
15387
+ inputValue,
15388
+ isPreAppStart: false
15389
+ }, (spanInfo) => {
15390
+ const mockConnection = new TdMysqlConnectionMock(self, "pool", spanInfo, void 0);
15391
+ if (callback) {
15392
+ process.nextTick(() => callback(null, mockConnection));
15393
+ return;
15394
+ }
15395
+ return mockConnection;
15396
+ });
15397
+ }
15398
+ });
15399
+ else if (self.mode === TuskDriftMode.RECORD) return originalGetConnection.apply(namespace, [callback]);
15400
+ else return originalGetConnection.apply(namespace, [callback]);
15401
+ };
15402
+ };
15403
+ }
14368
15404
  _wrap(target, propertyName, wrapper) {
14369
15405
  wrap(target, propertyName, wrapper);
14370
15406
  }
@@ -16571,7 +17607,7 @@ var FetchInstrumentation = class extends TdInstrumentationBase {
16571
17607
  },
16572
17608
  ...spanData.transformMetadata && { transformMetadata: spanData.transformMetadata }
16573
17609
  });
16574
- const status = response.status >= 400 ? {
17610
+ const status = response.status >= 300 ? {
16575
17611
  code: import_src$16.SpanStatusCode.ERROR,
16576
17612
  message: `HTTP ${response.status}`
16577
17613
  } : { code: import_src$16.SpanStatusCode.OK };
@@ -19592,7 +20628,7 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19592
20628
  headers: { matchImportance: 0 }
19593
20629
  }
19594
20630
  });
19595
- const status = (capturedStatusCode || 200) >= 400 ? {
20631
+ const status = (capturedStatusCode || 200) >= 300 ? {
19596
20632
  code: import_src$11.SpanStatusCode.ERROR,
19597
20633
  message: `HTTP ${capturedStatusCode}`
19598
20634
  } : { code: import_src$11.SpanStatusCode.OK };
@@ -19640,8 +20676,8 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19640
20676
  kind: import_src$11.SpanKind.SERVER,
19641
20677
  packageType: PackageType.HTTP,
19642
20678
  status: {
19643
- code: (capturedStatusCode || 200) >= 400 ? StatusCode.ERROR : StatusCode.OK,
19644
- message: (capturedStatusCode || 200) >= 400 ? `HTTP ${capturedStatusCode}` : ""
20679
+ code: (capturedStatusCode || 200) >= 300 ? StatusCode.ERROR : StatusCode.OK,
20680
+ message: (capturedStatusCode || 200) >= 300 ? `HTTP ${capturedStatusCode}` : ""
19645
20681
  },
19646
20682
  timestamp: {
19647
20683
  seconds: Math.floor(now.getTime() / 1e3),
@@ -31935,7 +32971,7 @@ var require_src = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/sdk-
31935
32971
  //#endregion
31936
32972
  //#region package.json
31937
32973
  var import_src$1 = /* @__PURE__ */ __toESM(require_src(), 1);
31938
- var version = "0.1.18";
32974
+ var version = "0.1.20";
31939
32975
 
31940
32976
  //#endregion
31941
32977
  //#region src/version.ts