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

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.cjs CHANGED
@@ -4989,31 +4989,31 @@ var require_SamplingResult = /* @__PURE__ */ __commonJS({ "node_modules/@opentel
4989
4989
  var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/span_kind.js": ((exports) => {
4990
4990
  Object.defineProperty(exports, "__esModule", { value: true });
4991
4991
  exports.SpanKind = void 0;
4992
- (function(SpanKind$25) {
4992
+ (function(SpanKind$26) {
4993
4993
  /** Default value. Indicates that the span is used internally. */
4994
- SpanKind$25[SpanKind$25["INTERNAL"] = 0] = "INTERNAL";
4994
+ SpanKind$26[SpanKind$26["INTERNAL"] = 0] = "INTERNAL";
4995
4995
  /**
4996
4996
  * Indicates that the span covers server-side handling of an RPC or other
4997
4997
  * remote request.
4998
4998
  */
4999
- SpanKind$25[SpanKind$25["SERVER"] = 1] = "SERVER";
4999
+ SpanKind$26[SpanKind$26["SERVER"] = 1] = "SERVER";
5000
5000
  /**
5001
5001
  * Indicates that the span covers the client-side wrapper around an RPC or
5002
5002
  * other remote request.
5003
5003
  */
5004
- SpanKind$25[SpanKind$25["CLIENT"] = 2] = "CLIENT";
5004
+ SpanKind$26[SpanKind$26["CLIENT"] = 2] = "CLIENT";
5005
5005
  /**
5006
5006
  * Indicates that the span describes producer sending a message to a
5007
5007
  * broker. Unlike client and server, there is no direct critical path latency
5008
5008
  * relationship between producer and consumer spans.
5009
5009
  */
5010
- SpanKind$25[SpanKind$25["PRODUCER"] = 3] = "PRODUCER";
5010
+ SpanKind$26[SpanKind$26["PRODUCER"] = 3] = "PRODUCER";
5011
5011
  /**
5012
5012
  * Indicates that the span describes consumer receiving a message from a
5013
5013
  * broker. Unlike client and server, there is no direct critical path latency
5014
5014
  * relationship between producer and consumer spans.
5015
5015
  */
5016
- SpanKind$25[SpanKind$25["CONSUMER"] = 4] = "CONSUMER";
5016
+ SpanKind$26[SpanKind$26["CONSUMER"] = 4] = "CONSUMER";
5017
5017
  })(exports.SpanKind || (exports.SpanKind = {}));
5018
5018
  }) });
5019
5019
 
@@ -5022,20 +5022,20 @@ var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetr
5022
5022
  var require_status = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/status.js": ((exports) => {
5023
5023
  Object.defineProperty(exports, "__esModule", { value: true });
5024
5024
  exports.SpanStatusCode = void 0;
5025
- (function(SpanStatusCode$14) {
5025
+ (function(SpanStatusCode$15) {
5026
5026
  /**
5027
5027
  * The default status.
5028
5028
  */
5029
- SpanStatusCode$14[SpanStatusCode$14["UNSET"] = 0] = "UNSET";
5029
+ SpanStatusCode$15[SpanStatusCode$15["UNSET"] = 0] = "UNSET";
5030
5030
  /**
5031
5031
  * The operation has been validated by an Application developer or
5032
5032
  * Operator to have completed successfully.
5033
5033
  */
5034
- SpanStatusCode$14[SpanStatusCode$14["OK"] = 1] = "OK";
5034
+ SpanStatusCode$15[SpanStatusCode$15["OK"] = 1] = "OK";
5035
5035
  /**
5036
5036
  * The operation contains an error.
5037
5037
  */
5038
- SpanStatusCode$14[SpanStatusCode$14["ERROR"] = 2] = "ERROR";
5038
+ SpanStatusCode$15[SpanStatusCode$15["ERROR"] = 2] = "ERROR";
5039
5039
  })(exports.SpanStatusCode || (exports.SpanStatusCode = {}));
5040
5040
  }) });
5041
5041
 
@@ -5684,7 +5684,7 @@ var require_src$7 = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/ap
5684
5684
 
5685
5685
  //#endregion
5686
5686
  //#region node_modules/@use-tusk/drift-schemas/dist/duration-B3fwb4jB.js
5687
- var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
5687
+ var import_src$35 = /* @__PURE__ */ __toESM(require_src$7(), 1);
5688
5688
  var import_commonjs$9 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
5689
5689
  var Duration$Type = class extends import_commonjs$9.MessageType {
5690
5690
  constructor() {
@@ -7008,11 +7008,11 @@ const Trace = new Trace$Type();
7008
7008
  const toStruct = (obj) => obj ? objectToProtobufStruct(obj) : void 0;
7009
7009
  const mapOtToPb = (k) => {
7010
7010
  switch (k) {
7011
- case import_src$34.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
7012
- case import_src$34.SpanKind.SERVER: return SpanKind$1.SERVER;
7013
- case import_src$34.SpanKind.CLIENT: return SpanKind$1.CLIENT;
7014
- case import_src$34.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
7015
- case import_src$34.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
7011
+ case import_src$35.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
7012
+ case import_src$35.SpanKind.SERVER: return SpanKind$1.SERVER;
7013
+ case import_src$35.SpanKind.CLIENT: return SpanKind$1.CLIENT;
7014
+ case import_src$35.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
7015
+ case import_src$35.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
7016
7016
  default: return SpanKind$1.UNSPECIFIED;
7017
7017
  }
7018
7018
  };
@@ -7416,13 +7416,13 @@ var TdInstrumentationNodeModule = class {
7416
7416
 
7417
7417
  //#endregion
7418
7418
  //#region src/core/types.ts
7419
- var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7419
+ var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7420
7420
  const TD_INSTRUMENTATION_LIBRARY_NAME = "tusk-drift-sdk";
7421
- const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.replayTraceId");
7422
- const SPAN_KIND_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.spanKind");
7423
- const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.isPreAppStart");
7424
- const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.stopRecordingChildSpans");
7425
- const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.callingLibrary");
7421
+ const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.replayTraceId");
7422
+ const SPAN_KIND_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.spanKind");
7423
+ const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.isPreAppStart");
7424
+ const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.stopRecordingChildSpans");
7425
+ const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.callingLibrary");
7426
7426
  let TdSpanAttributes = /* @__PURE__ */ function(TdSpanAttributes$1) {
7427
7427
  /**
7428
7428
  * Presentational information:
@@ -7534,7 +7534,7 @@ TraceBlockingManager.instance = null;
7534
7534
 
7535
7535
  //#endregion
7536
7536
  //#region src/core/tracing/SpanUtils.ts
7537
- var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7537
+ var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7538
7538
  var SpanUtils = class SpanUtils {
7539
7539
  /**
7540
7540
  * Creates a new span and returns span info including trace ID and span ID
@@ -7542,8 +7542,8 @@ var SpanUtils = class SpanUtils {
7542
7542
  static createSpan(options) {
7543
7543
  try {
7544
7544
  const tracer = TuskDriftCore.getInstance().getTracer();
7545
- const parentContext = options.parentContext || import_src$32.context.active();
7546
- const activeSpan = import_src$32.trace.getSpan(parentContext);
7545
+ const parentContext = options.parentContext || import_src$33.context.active();
7546
+ const activeSpan = import_src$33.trace.getSpan(parentContext);
7547
7547
  if (activeSpan) {
7548
7548
  const parentTraceId = activeSpan.spanContext().traceId;
7549
7549
  if (TraceBlockingManager.getInstance().isTraceBlocked(parentTraceId)) {
@@ -7552,11 +7552,11 @@ var SpanUtils = class SpanUtils {
7552
7552
  }
7553
7553
  }
7554
7554
  const span = tracer.startSpan(options.name, {
7555
- kind: options.kind || import_src$32.SpanKind.CLIENT,
7555
+ kind: options.kind || import_src$33.SpanKind.CLIENT,
7556
7556
  attributes: options.attributes || {}
7557
7557
  }, parentContext);
7558
7558
  const spanContext = span.spanContext();
7559
- 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);
7559
+ 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);
7560
7560
  return {
7561
7561
  traceId: spanContext.traceId,
7562
7562
  spanId: spanContext.spanId,
@@ -7573,7 +7573,7 @@ var SpanUtils = class SpanUtils {
7573
7573
  * Executes a function within a span context
7574
7574
  */
7575
7575
  static withSpan(spanInfo, fn) {
7576
- return import_src$32.context.with(spanInfo.context, fn);
7576
+ return import_src$33.context.with(spanInfo.context, fn);
7577
7577
  }
7578
7578
  /**
7579
7579
  * Execute a function within a properly configured span
@@ -7590,9 +7590,9 @@ var SpanUtils = class SpanUtils {
7590
7590
  * @returns The result of the function execution
7591
7591
  */
7592
7592
  static createAndExecuteSpan(mode, originalFunctionCall, options, fn) {
7593
- const spanContext = import_src$32.trace.getActiveSpan()?.spanContext();
7593
+ const spanContext = import_src$33.trace.getActiveSpan()?.spanContext();
7594
7594
  if (spanContext) {
7595
- if (import_src$32.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
7595
+ if (import_src$33.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
7596
7596
  logger.debug(`[SpanUtils] Stopping recording of child spans for span ${spanContext.spanId}, packageName: ${options.packageName}, instrumentationName: ${options.instrumentationName}`);
7597
7597
  return originalFunctionCall();
7598
7598
  }
@@ -7631,15 +7631,15 @@ var SpanUtils = class SpanUtils {
7631
7631
  */
7632
7632
  static getCurrentSpanInfo() {
7633
7633
  try {
7634
- const activeSpan = import_src$32.trace.getActiveSpan();
7634
+ const activeSpan = import_src$33.trace.getActiveSpan();
7635
7635
  if (!activeSpan) return null;
7636
7636
  const spanContext = activeSpan.spanContext();
7637
7637
  return {
7638
7638
  traceId: spanContext.traceId,
7639
7639
  spanId: spanContext.spanId,
7640
7640
  span: activeSpan,
7641
- context: import_src$32.context.active(),
7642
- isPreAppStart: import_src$32.context.active().getValue(IS_PRE_APP_START_CONTEXT_KEY)
7641
+ context: import_src$33.context.active(),
7642
+ isPreAppStart: import_src$33.context.active().getValue(IS_PRE_APP_START_CONTEXT_KEY)
7643
7643
  };
7644
7644
  } catch (error) {
7645
7645
  logger.error("SpanUtils error getting current span info:", error);
@@ -7703,7 +7703,7 @@ var SpanUtils = class SpanUtils {
7703
7703
  }
7704
7704
  static setCurrentReplayTraceId(replayTraceId) {
7705
7705
  try {
7706
- return import_src$32.context.active().setValue(REPLAY_TRACE_ID_CONTEXT_KEY, replayTraceId);
7706
+ return import_src$33.context.active().setValue(REPLAY_TRACE_ID_CONTEXT_KEY, replayTraceId);
7707
7707
  } catch (error) {
7708
7708
  logger.error("SpanUtils error setting current replay trace id:", error);
7709
7709
  return null;
@@ -7714,7 +7714,7 @@ var SpanUtils = class SpanUtils {
7714
7714
  */
7715
7715
  static getCurrentReplayTraceId() {
7716
7716
  try {
7717
- return import_src$32.context.active().getValue(REPLAY_TRACE_ID_CONTEXT_KEY);
7717
+ return import_src$33.context.active().getValue(REPLAY_TRACE_ID_CONTEXT_KEY);
7718
7718
  } catch (error) {
7719
7719
  logger.error("SpanUtils error getting current replay trace id:", error);
7720
7720
  return null;
@@ -8363,7 +8363,7 @@ function findMockResponseSync({ mockRequestData, tuskDrift, inputValueSchemaMerg
8363
8363
 
8364
8364
  //#endregion
8365
8365
  //#region src/instrumentation/libraries/http/mocks/TdMockClientRequest.ts
8366
- var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8366
+ var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8367
8367
  let ClientRequest;
8368
8368
  /**
8369
8369
  * Mock ClientRequest implementation for Tusk Drift HTTP replay
@@ -8534,7 +8534,7 @@ var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter
8534
8534
  instrumentationName: this.INSTRUMENTATION_NAME,
8535
8535
  submoduleName: rawInputValue.method,
8536
8536
  inputValue,
8537
- kind: import_src$31.SpanKind.CLIENT,
8537
+ kind: import_src$32.SpanKind.CLIENT,
8538
8538
  stackTrace: this.stackTrace
8539
8539
  },
8540
8540
  tuskDrift: this.tuskDrift,
@@ -8704,7 +8704,7 @@ var HttpReplayHooks = class {
8704
8704
 
8705
8705
  //#endregion
8706
8706
  //#region src/instrumentation/core/utils/modeUtils.ts
8707
- var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8707
+ var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8708
8708
  /**
8709
8709
  * Utility function that abstracts the common record mode pattern of checking for current span context
8710
8710
  * and deciding whether to execute record mode logic or just call the original function.
@@ -8725,7 +8725,7 @@ function handleRecordMode({ originalFunctionCall, recordModeHandler, spanKind })
8725
8725
  return originalFunctionCall();
8726
8726
  }
8727
8727
  if (!isAppReady) return recordModeHandler({ isPreAppStart: true });
8728
- if (!currentSpanInfo && spanKind !== import_src$30.SpanKind.SERVER || currentSpanInfo?.isPreAppStart) return originalFunctionCall();
8728
+ if (!currentSpanInfo && spanKind !== import_src$31.SpanKind.SERVER || currentSpanInfo?.isPreAppStart) return originalFunctionCall();
8729
8729
  else return recordModeHandler({ isPreAppStart: false });
8730
8730
  }
8731
8731
  /**
@@ -10205,7 +10205,7 @@ function captureStackTrace(excludeClassNames = []) {
10205
10205
 
10206
10206
  //#endregion
10207
10207
  //#region src/instrumentation/libraries/http/HttpTransformEngine.ts
10208
- var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10208
+ var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10209
10209
  /**
10210
10210
  * Creates an empty HttpClientInputValue object for dropped spans
10211
10211
  */
@@ -10258,7 +10258,7 @@ var HttpTransformEngine = class {
10258
10258
  const testSpan = {
10259
10259
  traceId: "",
10260
10260
  spanId: "",
10261
- kind: import_src$29.SpanKind.SERVER,
10261
+ kind: import_src$30.SpanKind.SERVER,
10262
10262
  protocol: "http",
10263
10263
  inputValue: {
10264
10264
  method,
@@ -10281,7 +10281,7 @@ var HttpTransformEngine = class {
10281
10281
  const testSpan = {
10282
10282
  traceId: "",
10283
10283
  spanId: "",
10284
- kind: import_src$29.SpanKind.CLIENT,
10284
+ kind: import_src$30.SpanKind.CLIENT,
10285
10285
  protocol: inputValue.protocol || "http",
10286
10286
  inputValue: clonedInputValue
10287
10287
  };
@@ -10308,8 +10308,8 @@ var HttpTransformEngine = class {
10308
10308
  const matcherFunction = this.compileMatcher(matcher);
10309
10309
  if (action.type === "drop") return (span) => {
10310
10310
  if (!matcherFunction(span)) return;
10311
- if (span.inputValue) span.inputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10312
- if (span.outputValue) span.outputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientOutputValue() : createEmptyServerOutputValue();
10311
+ if (span.inputValue) span.inputValue = span.kind === import_src$30.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10312
+ if (span.outputValue) span.outputValue = span.kind === import_src$30.SpanKind.CLIENT ? createEmptyClientOutputValue() : createEmptyServerOutputValue();
10313
10313
  return {
10314
10314
  type: "drop",
10315
10315
  field: "entire_span",
@@ -10339,8 +10339,8 @@ var HttpTransformEngine = class {
10339
10339
  }
10340
10340
  compileMatcher(matcher) {
10341
10341
  const checks = [];
10342
- if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$29.SpanKind.CLIENT);
10343
- else if (matcher.direction === "inbound") checks.push((span) => span.kind === import_src$29.SpanKind.SERVER);
10342
+ if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$30.SpanKind.CLIENT);
10343
+ else if (matcher.direction === "inbound") checks.push((span) => span.kind === import_src$30.SpanKind.SERVER);
10344
10344
  if (matcher.method) if (matcher.method.length === 0) {} else {
10345
10345
  const methods = matcher.method.map((method) => method.toUpperCase());
10346
10346
  checks.push((span) => {
@@ -10568,7 +10568,7 @@ var HttpTransformEngine = class {
10568
10568
 
10569
10569
  //#endregion
10570
10570
  //#region src/instrumentation/libraries/http/Instrumentation.ts
10571
- var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10571
+ var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10572
10572
  var HttpInstrumentation = class extends TdInstrumentationBase {
10573
10573
  constructor(config) {
10574
10574
  super("http", config);
@@ -10655,10 +10655,10 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10655
10655
  logger.debug(`[HttpInstrumentation] Setting replay trace id`, replayTraceId);
10656
10656
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
10657
10657
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
10658
- return import_src$28.context.with(ctxWithReplayTraceId, () => {
10658
+ return import_src$29.context.with(ctxWithReplayTraceId, () => {
10659
10659
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10660
10660
  name: `${target}`,
10661
- kind: import_src$28.SpanKind.SERVER,
10661
+ kind: import_src$29.SpanKind.SERVER,
10662
10662
  packageName: spanProtocol,
10663
10663
  submodule: method,
10664
10664
  packageType: PackageType.HTTP,
@@ -10703,7 +10703,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10703
10703
  logger.debug(`[HttpInstrumentation] Http inbound request arriving, inputValue: ${JSON.stringify(inputValue)}`);
10704
10704
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10705
10705
  name: `${target}`,
10706
- kind: import_src$28.SpanKind.SERVER,
10706
+ kind: import_src$29.SpanKind.SERVER,
10707
10707
  packageName: spanProtocol,
10708
10708
  packageType: PackageType.HTTP,
10709
10709
  submodule: method,
@@ -10723,7 +10723,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10723
10723
  });
10724
10724
  });
10725
10725
  },
10726
- spanKind: import_src$28.SpanKind.SERVER
10726
+ spanKind: import_src$29.SpanKind.SERVER
10727
10727
  });
10728
10728
  } else return originalHandler.call(this);
10729
10729
  }
@@ -10740,8 +10740,8 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10740
10740
  _handleInboundRequestInSpan({ req, res, originalHandler, spanInfo, inputValue, schemaMerges, protocol }) {
10741
10741
  const self = this;
10742
10742
  const spanProtocol = this._normalizeProtocol(protocol, "http");
10743
- import_src$28.context.bind(spanInfo.context, req);
10744
- import_src$28.context.bind(spanInfo.context, res);
10743
+ import_src$29.context.bind(spanInfo.context, req);
10744
+ import_src$29.context.bind(spanInfo.context, res);
10745
10745
  let completeInputValue = inputValue;
10746
10746
  this._captureServerRequestBody(req, spanInfo, inputValue, schemaMerges, (updatedInputValue) => {
10747
10747
  completeInputValue = updatedInputValue;
@@ -10779,7 +10779,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10779
10779
  const spanData = {
10780
10780
  traceId: spanInfo.traceId,
10781
10781
  spanId: spanInfo.spanId,
10782
- kind: import_src$28.SpanKind.SERVER,
10782
+ kind: import_src$29.SpanKind.SERVER,
10783
10783
  protocol: spanProtocol,
10784
10784
  inputValue: completeInputValue,
10785
10785
  outputValue
@@ -10798,9 +10798,9 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10798
10798
  ...spanData.transformMetadata && { transformMetadata: spanData.transformMetadata }
10799
10799
  });
10800
10800
  const status = statusCode >= 400 ? {
10801
- code: import_src$28.SpanStatusCode.ERROR,
10801
+ code: import_src$29.SpanStatusCode.ERROR,
10802
10802
  message: `HTTP ${statusCode}`
10803
- } : { code: import_src$28.SpanStatusCode.OK };
10803
+ } : { code: import_src$29.SpanStatusCode.OK };
10804
10804
  SpanUtils.setStatus(spanInfo.span, status);
10805
10805
  const decodedType = getDecodedType(outputValue.headers?.["content-type"] || "");
10806
10806
  if (decodedType && !ACCEPTABLE_CONTENT_TYPES.has(decodedType)) {
@@ -10850,7 +10850,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10850
10850
  outputSchemaHash: JsonSchemaHelper.generateDeterministicHash(outputSchema),
10851
10851
  inputValueHash,
10852
10852
  outputValueHash,
10853
- kind: import_src$28.SpanKind.SERVER,
10853
+ kind: import_src$29.SpanKind.SERVER,
10854
10854
  packageType: PackageType.HTTP,
10855
10855
  status: {
10856
10856
  code: statusCode >= 400 ? StatusCode.ERROR : StatusCode.OK,
@@ -10879,7 +10879,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10879
10879
  try {
10880
10880
  logger.debug(`[HttpInstrumentation] Server request 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) {
@@ -10890,7 +10890,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10890
10890
  try {
10891
10891
  logger.debug(`[HttpInstrumentation] Server response error: ${error.message} (${SpanUtils.getTraceInfo()})`);
10892
10892
  SpanUtils.endSpan(spanInfo.span, {
10893
- code: import_src$28.SpanStatusCode.ERROR,
10893
+ code: import_src$29.SpanStatusCode.ERROR,
10894
10894
  message: error.message
10895
10895
  });
10896
10896
  } catch (error$1) {
@@ -11095,7 +11095,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11095
11095
  inputValue: completeInputValue
11096
11096
  });
11097
11097
  SpanUtils.endSpan(spanInfo.span, {
11098
- code: import_src$28.SpanStatusCode.ERROR,
11098
+ code: import_src$29.SpanStatusCode.ERROR,
11099
11099
  message: error.message
11100
11100
  });
11101
11101
  } catch (error$1) {
@@ -11112,7 +11112,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11112
11112
  const spanData = {
11113
11113
  traceId: spanInfo.traceId,
11114
11114
  spanId: spanInfo.spanId,
11115
- kind: import_src$28.SpanKind.CLIENT,
11115
+ kind: import_src$29.SpanKind.CLIENT,
11116
11116
  protocol: normalizedProtocol,
11117
11117
  inputValue,
11118
11118
  outputValue
@@ -11125,9 +11125,9 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11125
11125
  transformMetadata: spanData.transformMetadata ? spanData.transformMetadata : void 0
11126
11126
  });
11127
11127
  const status = statusCode >= 400 ? {
11128
- code: import_src$28.SpanStatusCode.ERROR,
11128
+ code: import_src$29.SpanStatusCode.ERROR,
11129
11129
  message: `HTTP ${statusCode}`
11130
- } : { code: import_src$28.SpanStatusCode.OK };
11130
+ } : { code: import_src$29.SpanStatusCode.OK };
11131
11131
  SpanUtils.endSpan(spanInfo.span, status);
11132
11132
  }
11133
11133
  _captureHeadersFromRawHeaders(rawHeaders) {
@@ -11181,7 +11181,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11181
11181
  };
11182
11182
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11183
11183
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11184
- kind: import_src$28.SpanKind.CLIENT,
11184
+ kind: import_src$29.SpanKind.CLIENT,
11185
11185
  packageName: requestProtocol,
11186
11186
  packageType: PackageType.HTTP,
11187
11187
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11216,7 +11216,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11216
11216
  };
11217
11217
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11218
11218
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11219
- kind: import_src$28.SpanKind.CLIENT,
11219
+ kind: import_src$29.SpanKind.CLIENT,
11220
11220
  packageName: requestProtocol,
11221
11221
  packageType: PackageType.HTTP,
11222
11222
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11228,7 +11228,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11228
11228
  return self._handleOutboundRequestInSpan(originalRequest, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11229
11229
  });
11230
11230
  },
11231
- spanKind: import_src$28.SpanKind.CLIENT
11231
+ spanKind: import_src$29.SpanKind.CLIENT
11232
11232
  });
11233
11233
  else return originalRequest.apply(this, args);
11234
11234
  };
@@ -11274,7 +11274,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11274
11274
  };
11275
11275
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11276
11276
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11277
- kind: import_src$28.SpanKind.CLIENT,
11277
+ kind: import_src$29.SpanKind.CLIENT,
11278
11278
  packageName: requestProtocol,
11279
11279
  packageType: PackageType.HTTP,
11280
11280
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11308,7 +11308,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11308
11308
  };
11309
11309
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11310
11310
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11311
- kind: import_src$28.SpanKind.CLIENT,
11311
+ kind: import_src$29.SpanKind.CLIENT,
11312
11312
  packageName: requestProtocol,
11313
11313
  packageType: PackageType.HTTP,
11314
11314
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11320,7 +11320,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11320
11320
  return self._handleOutboundRequestInSpan(originalGet, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11321
11321
  });
11322
11322
  },
11323
- spanKind: import_src$28.SpanKind.CLIENT
11323
+ spanKind: import_src$29.SpanKind.CLIENT
11324
11324
  });
11325
11325
  else return originalGet.apply(this, args);
11326
11326
  };
@@ -11365,7 +11365,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11365
11365
 
11366
11366
  //#endregion
11367
11367
  //#region src/instrumentation/libraries/date/Instrumentation.ts
11368
- var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11368
+ var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11369
11369
  /**
11370
11370
  * Date instrumentation that provides consistent dates in replay mode.
11371
11371
  * In replay mode, new Date() calls return the latest mock response timestamp.
@@ -11404,7 +11404,7 @@ var DateInstrumentation = class DateInstrumentation extends TdInstrumentationBas
11404
11404
  if (this.mode !== TuskDriftMode.REPLAY) return this._callOriginalDate(args, isConstructorCall);
11405
11405
  const currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11406
11406
  if (!currentSpanInfo) return this._callOriginalDate(args, isConstructorCall);
11407
- if (currentSpanInfo.context.getValue(SPAN_KIND_CONTEXT_KEY) !== import_src$27.SpanKind.SERVER) return this._callOriginalDate(args, isConstructorCall);
11407
+ if (currentSpanInfo.context.getValue(SPAN_KIND_CONTEXT_KEY) !== import_src$28.SpanKind.SERVER) return this._callOriginalDate(args, isConstructorCall);
11408
11408
  this.isInPatchedCall = true;
11409
11409
  try {
11410
11410
  return this._handleReplayDate(args, isConstructorCall);
@@ -11650,7 +11650,7 @@ var TdPgClientMock = class extends events.EventEmitter {
11650
11650
 
11651
11651
  //#endregion
11652
11652
  //#region src/instrumentation/libraries/pg/Instrumentation.ts
11653
- var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11653
+ var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11654
11654
  var PgInstrumentation = class extends TdInstrumentationBase {
11655
11655
  constructor(config = {}) {
11656
11656
  super("pg", config);
@@ -11691,6 +11691,10 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11691
11691
  const self = this;
11692
11692
  return (originalQuery) => {
11693
11693
  return function query(...args) {
11694
+ if (self.isSubmittable(args[0])) {
11695
+ logger.debug(`[PgInstrumentation] Submittable query detected, passing through uninstrumented`);
11696
+ return originalQuery.apply(this, args);
11697
+ }
11694
11698
  let queryConfig = null;
11695
11699
  try {
11696
11700
  queryConfig = self.parseQueryArgs(args);
@@ -11719,7 +11723,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11719
11723
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11720
11724
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11721
11725
  name: spanName,
11722
- kind: import_src$26.SpanKind.CLIENT,
11726
+ kind: import_src$27.SpanKind.CLIENT,
11723
11727
  submodule: "query",
11724
11728
  packageType: PackageType.PG,
11725
11729
  packageName,
@@ -11738,7 +11742,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11738
11742
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11739
11743
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11740
11744
  name: spanName,
11741
- kind: import_src$26.SpanKind.CLIENT,
11745
+ kind: import_src$27.SpanKind.CLIENT,
11742
11746
  submodule: "query",
11743
11747
  packageType: PackageType.PG,
11744
11748
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11749,7 +11753,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11749
11753
  return self._handleRecordQueryInSpan(spanInfo, originalQuery, queryConfig, args, this);
11750
11754
  });
11751
11755
  },
11752
- spanKind: import_src$26.SpanKind.CLIENT
11756
+ spanKind: import_src$27.SpanKind.CLIENT
11753
11757
  });
11754
11758
  else return originalQuery.apply(this, args);
11755
11759
  };
@@ -11771,7 +11775,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11771
11775
  replayModeHandler: () => {
11772
11776
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11773
11777
  name: `pg.connect`,
11774
- kind: import_src$26.SpanKind.CLIENT,
11778
+ kind: import_src$27.SpanKind.CLIENT,
11775
11779
  submodule: "connect",
11776
11780
  packageName: "pg",
11777
11781
  packageType: PackageType.PG,
@@ -11788,7 +11792,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11788
11792
  recordModeHandler: ({ isPreAppStart }) => {
11789
11793
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11790
11794
  name: `pg.connect`,
11791
- kind: import_src$26.SpanKind.CLIENT,
11795
+ kind: import_src$27.SpanKind.CLIENT,
11792
11796
  submodule: "connect",
11793
11797
  packageName: "pg",
11794
11798
  packageType: PackageType.PG,
@@ -11799,12 +11803,19 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11799
11803
  return self._handleRecordConnectInSpan(spanInfo, originalConnect, callback, this);
11800
11804
  });
11801
11805
  },
11802
- spanKind: import_src$26.SpanKind.CLIENT
11806
+ spanKind: import_src$27.SpanKind.CLIENT
11803
11807
  });
11804
11808
  else return originalConnect.apply(this, [callback]);
11805
11809
  };
11806
11810
  };
11807
11811
  }
11812
+ /**
11813
+ * Check if an object is a Submittable (Query object with submit method).
11814
+ * This is the same check pg uses internally: typeof config.submit === 'function'
11815
+ */
11816
+ isSubmittable(arg) {
11817
+ return arg && typeof arg.submit === "function";
11818
+ }
11808
11819
  parseQueryArgs(args) {
11809
11820
  if (args.length === 0) return null;
11810
11821
  const firstArg = args[0];
@@ -11832,7 +11843,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11832
11843
  logger.debug(`[PgInstrumentation] PG query error (hasCallback): ${error.message} (${SpanUtils.getTraceInfo()})`);
11833
11844
  try {
11834
11845
  SpanUtils.endSpan(spanInfo.span, {
11835
- code: import_src$26.SpanStatusCode.ERROR,
11846
+ code: import_src$27.SpanStatusCode.ERROR,
11836
11847
  message: error.message
11837
11848
  });
11838
11849
  } catch (error$1) {
@@ -11842,7 +11853,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11842
11853
  logger.debug(`[PgInstrumentation] PG query completed successfully (hasCallback) (${SpanUtils.getTraceInfo()})`);
11843
11854
  try {
11844
11855
  this._addOutputAttributesToSpan(spanInfo, result);
11845
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11856
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11846
11857
  } catch (error$1) {
11847
11858
  logger.error(`[PgInstrumentation] error processing response:`, error$1);
11848
11859
  }
@@ -11869,7 +11880,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11869
11880
  logger.debug(`[PgInstrumentation] PG query completed successfully (${SpanUtils.getTraceInfo()})`);
11870
11881
  try {
11871
11882
  this._addOutputAttributesToSpan(spanInfo, result);
11872
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11883
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11873
11884
  } catch (error) {
11874
11885
  logger.error(`[PgInstrumentation] error processing response:`, error);
11875
11886
  }
@@ -11878,7 +11889,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11878
11889
  logger.debug(`[PgInstrumentation] PG query error: ${error.message} (${SpanUtils.getTraceInfo()})`);
11879
11890
  try {
11880
11891
  SpanUtils.endSpan(spanInfo.span, {
11881
- code: import_src$26.SpanStatusCode.ERROR,
11892
+ code: import_src$27.SpanStatusCode.ERROR,
11882
11893
  message: error.message
11883
11894
  });
11884
11895
  } catch (error$1) {
@@ -11910,7 +11921,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11910
11921
  packageName,
11911
11922
  instrumentationName: this.INSTRUMENTATION_NAME,
11912
11923
  submoduleName: "query",
11913
- kind: import_src$26.SpanKind.CLIENT,
11924
+ kind: import_src$27.SpanKind.CLIENT,
11914
11925
  stackTrace
11915
11926
  },
11916
11927
  tuskDrift: this.tuskDrift
@@ -11954,6 +11965,8 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11954
11965
  * Reference for data type IDs: https://jdbc.postgresql.org/documentation/publicapi/constant-values.html
11955
11966
  */
11956
11967
  convertPostgresTypes(result, rowMode) {
11968
+ if (result && result.isMultiStatement && Array.isArray(result.results)) return result.results.map((singleResult) => this.convertPostgresTypes(singleResult, rowMode));
11969
+ if (Array.isArray(result)) return result.map((singleResult) => this.convertPostgresTypes(singleResult, rowMode));
11957
11970
  if (!result || !result.fields || !result.rows) return result;
11958
11971
  if (rowMode === "array") {
11959
11972
  const convertedRows$1 = result.rows.map((row) => {
@@ -11994,7 +12007,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11994
12007
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
11995
12008
  try {
11996
12009
  SpanUtils.endSpan(spanInfo.span, {
11997
- code: import_src$26.SpanStatusCode.ERROR,
12010
+ code: import_src$27.SpanStatusCode.ERROR,
11998
12011
  message: error.message
11999
12012
  });
12000
12013
  } catch (error$1) {
@@ -12004,7 +12017,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12004
12017
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12005
12018
  try {
12006
12019
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12007
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12020
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12008
12021
  } catch (error$1) {
12009
12022
  logger.error(`[PgInstrumentation] error processing connect response:`, error$1);
12010
12023
  }
@@ -12016,7 +12029,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12016
12029
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12017
12030
  try {
12018
12031
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12019
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12032
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12020
12033
  } catch (error) {
12021
12034
  logger.error(`[PgInstrumentation] error processing connect response:`, error);
12022
12035
  }
@@ -12025,7 +12038,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12025
12038
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12026
12039
  try {
12027
12040
  SpanUtils.endSpan(spanInfo.span, {
12028
- code: import_src$26.SpanStatusCode.ERROR,
12041
+ code: import_src$27.SpanStatusCode.ERROR,
12029
12042
  message: error.message
12030
12043
  });
12031
12044
  } catch (error$1) {
@@ -12043,7 +12056,18 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12043
12056
  }
12044
12057
  _addOutputAttributesToSpan(spanInfo, result) {
12045
12058
  if (!result) return;
12046
- const outputValue = {
12059
+ let outputValue;
12060
+ if (Array.isArray(result)) outputValue = {
12061
+ isMultiStatement: true,
12062
+ results: result.map((r) => ({
12063
+ command: r.command,
12064
+ rowCount: r.rowCount,
12065
+ oid: r.oid,
12066
+ rows: r.rows || [],
12067
+ fields: r.fields || []
12068
+ }))
12069
+ };
12070
+ else outputValue = {
12047
12071
  command: result.command,
12048
12072
  rowCount: result.rowCount,
12049
12073
  oid: result.oid,
@@ -12086,7 +12110,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12086
12110
  replayModeHandler: () => {
12087
12111
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12088
12112
  name: `pg-pool.connect`,
12089
- kind: import_src$26.SpanKind.CLIENT,
12113
+ kind: import_src$27.SpanKind.CLIENT,
12090
12114
  submodule: "connect",
12091
12115
  packageName: "pg-pool",
12092
12116
  packageType: PackageType.PG,
@@ -12103,7 +12127,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12103
12127
  recordModeHandler: ({ isPreAppStart }) => {
12104
12128
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12105
12129
  name: `pg-pool.connect`,
12106
- kind: import_src$26.SpanKind.CLIENT,
12130
+ kind: import_src$27.SpanKind.CLIENT,
12107
12131
  submodule: "connect",
12108
12132
  packageName: "pg-pool",
12109
12133
  packageType: PackageType.PG,
@@ -12114,7 +12138,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12114
12138
  return self._handleRecordPoolConnectInSpan(spanInfo, originalConnect, callback, this);
12115
12139
  });
12116
12140
  },
12117
- spanKind: import_src$26.SpanKind.CLIENT
12141
+ spanKind: import_src$27.SpanKind.CLIENT
12118
12142
  });
12119
12143
  else return originalConnect.apply(this, [callback]);
12120
12144
  };
@@ -12127,7 +12151,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12127
12151
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12128
12152
  try {
12129
12153
  SpanUtils.endSpan(spanInfo.span, {
12130
- code: import_src$26.SpanStatusCode.ERROR,
12154
+ code: import_src$27.SpanStatusCode.ERROR,
12131
12155
  message: error.message
12132
12156
  });
12133
12157
  } catch (error$1) {
@@ -12140,7 +12164,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12140
12164
  connected: true,
12141
12165
  hasClient: !!client
12142
12166
  } });
12143
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12167
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12144
12168
  } catch (error$1) {
12145
12169
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error$1);
12146
12170
  }
@@ -12155,7 +12179,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12155
12179
  connected: true,
12156
12180
  hasClient: !!client
12157
12181
  } });
12158
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12182
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12159
12183
  } catch (error) {
12160
12184
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error);
12161
12185
  }
@@ -12164,7 +12188,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12164
12188
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12165
12189
  try {
12166
12190
  SpanUtils.endSpan(spanInfo.span, {
12167
- code: import_src$26.SpanStatusCode.ERROR,
12191
+ code: import_src$27.SpanStatusCode.ERROR,
12168
12192
  message: error.message
12169
12193
  });
12170
12194
  } catch (error$1) {
@@ -12193,68 +12217,114 @@ function isPostgresOutputValueType(value) {
12193
12217
  }
12194
12218
 
12195
12219
  //#endregion
12196
- //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12197
- var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12198
- var PostgresInstrumentation = class extends TdInstrumentationBase {
12199
- constructor(config = {}) {
12200
- super("postgres", config);
12201
- this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12202
- this.mode = config.mode || TuskDriftMode.DISABLED;
12203
- this.tuskDrift = TuskDriftCore.getInstance();
12220
+ //#region src/instrumentation/libraries/postgres/utils/typeConversion.ts
12221
+ /**
12222
+ * Convert PostgreSQL string values back to appropriate JavaScript types
12223
+ * based on field metadata from the recorded response.
12224
+ */
12225
+ function convertPostgresTypes(result) {
12226
+ if (!isPostgresOutputValueType(result)) {
12227
+ logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12228
+ return;
12204
12229
  }
12205
- init() {
12206
- return [new TdInstrumentationNodeModule({
12207
- name: "postgres",
12208
- supportedVersions: ["3.*"],
12209
- patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12210
- })];
12230
+ const { rows, count, command, columns, state, statement } = result;
12231
+ const resultArray = Array.from((rows || []).map((row) => reconstructBuffers(row)));
12232
+ if (count !== void 0) Object.defineProperty(resultArray, "count", {
12233
+ value: count,
12234
+ writable: true,
12235
+ enumerable: false
12236
+ });
12237
+ if (command !== void 0) Object.defineProperty(resultArray, "command", {
12238
+ value: command,
12239
+ writable: true,
12240
+ enumerable: false
12241
+ });
12242
+ if (columns !== void 0) Object.defineProperty(resultArray, "columns", {
12243
+ value: columns,
12244
+ writable: true,
12245
+ enumerable: false
12246
+ });
12247
+ if (state !== void 0) Object.defineProperty(resultArray, "state", {
12248
+ value: state,
12249
+ writable: true,
12250
+ enumerable: false
12251
+ });
12252
+ if (statement !== void 0) Object.defineProperty(resultArray, "statement", {
12253
+ value: statement,
12254
+ writable: true,
12255
+ enumerable: false
12256
+ });
12257
+ return resultArray;
12258
+ }
12259
+ /**
12260
+ * Recursively reconstructs Buffer objects from their JSON-serialized format.
12261
+ * When Buffers are JSON.stringify'd, they become { type: "Buffer", data: [...] }.
12262
+ * This method converts them back to actual Buffer instances.
12263
+ */
12264
+ function reconstructBuffers(value) {
12265
+ if (value === null || value === void 0) return value;
12266
+ if (typeof value === "object" && value.type === "Buffer" && Array.isArray(value.data)) return Buffer.from(value.data);
12267
+ if (Array.isArray(value)) return value.map((item) => reconstructBuffers(item));
12268
+ if (typeof value === "object") {
12269
+ const result = {};
12270
+ for (const key of Object.keys(value)) result[key] = reconstructBuffers(value[key]);
12271
+ return result;
12211
12272
  }
12212
- _patchPostgresModule(postgresModule) {
12213
- logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12214
- if (this.isModulePatched(postgresModule)) {
12215
- logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12216
- return postgresModule;
12217
- }
12218
- const self = this;
12219
- if (isEsm(postgresModule)) {
12220
- logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12221
- this._wrap(postgresModule, "default", (originalFunction) => {
12222
- return function(...args) {
12223
- return self._handlePostgresConnection(originalFunction, args);
12224
- };
12225
- });
12226
- } else {
12227
- logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12228
- const originalFunction = postgresModule;
12229
- const wrappedFunction = function(...args) {
12230
- logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12231
- return self._handlePostgresConnection(originalFunction, args);
12232
- };
12233
- Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12234
- Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12235
- for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12236
- Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12237
- if (key !== "prototype" && key !== "length" && key !== "name") {
12238
- const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12239
- if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12240
- }
12241
- });
12242
- postgresModule = wrappedFunction;
12243
- }
12244
- if (postgresModule.sql && typeof postgresModule.sql === "function") {
12245
- this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12246
- logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12247
- }
12248
- this.markModuleAsPatched(postgresModule);
12249
- logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12250
- return postgresModule;
12273
+ return value;
12274
+ }
12275
+ /**
12276
+ * Add output attributes to span for PostgreSQL results.
12277
+ */
12278
+ function addOutputAttributesToSpan(spanInfo, result) {
12279
+ if (!result) return;
12280
+ const isArray$1 = Array.isArray(result);
12281
+ logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12282
+ const normalizeValue = (val) => {
12283
+ if (Buffer.isBuffer(val)) return val.toString("utf8");
12284
+ else if (Array.isArray(val)) return val.map(normalizeValue);
12285
+ else if (val && typeof val === "object" && val.type === "Buffer" && Array.isArray(val.data)) return Buffer.from(val.data).toString("utf8");
12286
+ return val;
12287
+ };
12288
+ const outputValue = {
12289
+ rows: isArray$1 ? Array.from(result).map(normalizeValue) : (result.rows || []).map(normalizeValue),
12290
+ count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12291
+ command: result.command || void 0,
12292
+ columns: result.columns || void 0,
12293
+ state: result.state || void 0,
12294
+ statement: result.statement || void 0
12295
+ };
12296
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12297
+ }
12298
+
12299
+ //#endregion
12300
+ //#region src/instrumentation/libraries/postgres/utils/queryUtils.ts
12301
+ /**
12302
+ * Reconstruct a parameterized query string from template strings array and values.
12303
+ * Converts values to $1, $2, etc. placeholders.
12304
+ */
12305
+ function reconstructQueryString(strings, values) {
12306
+ let queryString = "";
12307
+ for (let i = 0; i < strings.length; i++) {
12308
+ queryString += strings[i];
12309
+ if (i < values.length) queryString += `$${i + 1}`;
12251
12310
  }
12252
- _handlePostgresConnection(originalFunction, args) {
12253
- const connectionString = typeof args[0] === "string" ? args[0] : void 0;
12254
- const options = typeof args[0] === "string" ? args[1] : args[0];
12311
+ return queryString;
12312
+ }
12313
+
12314
+ //#endregion
12315
+ //#region src/instrumentation/libraries/postgres/handlers/ConnectionHandler.ts
12316
+ var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12317
+ var ConnectionHandler = class {
12318
+ constructor(mode, instrumentationName, isAppReady, wrapSqlInstance) {
12319
+ this.mode = mode;
12320
+ this.instrumentationName = instrumentationName;
12321
+ this.isAppReady = isAppReady;
12322
+ this.wrapSqlInstance = wrapSqlInstance;
12323
+ }
12324
+ handlePostgresConnection(originalFunction, args) {
12255
12325
  const inputValue = {
12256
- connectionString: connectionString ? this._sanitizeConnectionString(connectionString) : void 0,
12257
- options: options ? this._sanitizeConnectionOptions(options) : void 0
12326
+ connectionString: typeof args[0] === "string" ? args[0] : void 0,
12327
+ options: typeof args[0] === "string" ? args[1] : args[0]
12258
12328
  };
12259
12329
  if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
12260
12330
  noOpRequestHandler: () => {
@@ -12268,96 +12338,148 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12268
12338
  }));
12269
12339
  mockSql.begin = () => Promise.resolve();
12270
12340
  mockSql.end = () => Promise.resolve();
12341
+ mockSql.file = () => Promise.resolve(Object.assign([], {
12342
+ count: 0,
12343
+ command: null
12344
+ }));
12345
+ mockSql.reserve = () => Promise.resolve(mockSql);
12346
+ mockSql.listen = () => Promise.resolve({
12347
+ state: { state: "I" },
12348
+ unlisten: async () => {}
12349
+ });
12350
+ mockSql.notify = () => Promise.resolve();
12271
12351
  return mockSql;
12272
12352
  },
12273
12353
  isServerRequest: false,
12274
12354
  replayModeHandler: () => {
12275
12355
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12276
12356
  const sqlInstance = originalFunction(...args);
12277
- return this._wrapSqlInstance(sqlInstance);
12357
+ return this.wrapSqlInstance(sqlInstance);
12278
12358
  }, {
12279
12359
  name: "postgres.connect",
12280
- kind: import_src$25.SpanKind.CLIENT,
12360
+ kind: import_src$26.SpanKind.CLIENT,
12281
12361
  submodule: "connect",
12282
12362
  packageType: PackageType.PG,
12283
12363
  packageName: "postgres",
12284
- instrumentationName: this.INSTRUMENTATION_NAME,
12364
+ instrumentationName: this.instrumentationName,
12285
12365
  inputValue,
12286
- isPreAppStart: false
12366
+ isPreAppStart: this.isAppReady() ? false : true
12287
12367
  }, (spanInfo) => {
12288
- return this._handleReplayConnect(originalFunction, args);
12368
+ return this.handleReplayConnect(originalFunction, args);
12289
12369
  });
12290
12370
  }
12291
12371
  });
12292
12372
  else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
12293
12373
  originalFunctionCall: () => {
12294
12374
  const sqlInstance = originalFunction(...args);
12295
- return this._wrapSqlInstance(sqlInstance);
12375
+ return this.wrapSqlInstance(sqlInstance);
12296
12376
  },
12297
12377
  recordModeHandler: ({ isPreAppStart }) => {
12298
12378
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12299
12379
  const sqlInstance = originalFunction(...args);
12300
- return this._wrapSqlInstance(sqlInstance);
12380
+ return this.wrapSqlInstance(sqlInstance);
12301
12381
  }, {
12302
12382
  name: "postgres.connect",
12303
- kind: import_src$25.SpanKind.CLIENT,
12383
+ kind: import_src$26.SpanKind.CLIENT,
12304
12384
  submodule: "connect",
12305
12385
  packageType: PackageType.PG,
12306
12386
  packageName: "postgres",
12307
- instrumentationName: this.INSTRUMENTATION_NAME,
12387
+ instrumentationName: this.instrumentationName,
12308
12388
  inputValue,
12309
12389
  isPreAppStart
12310
12390
  }, (spanInfo) => {
12311
- return this._handleRecordConnect(spanInfo, originalFunction, args);
12391
+ return this.handleRecordConnect(spanInfo, originalFunction, args);
12312
12392
  });
12313
12393
  },
12314
- spanKind: import_src$25.SpanKind.CLIENT
12394
+ spanKind: import_src$26.SpanKind.CLIENT
12315
12395
  });
12316
12396
  else return originalFunction(...args);
12317
12397
  }
12318
- _sanitizeConnectionString(connectionString) {
12319
- try {
12320
- const url = new URL(connectionString);
12321
- if (url.password) url.password = "***";
12322
- return url.toString();
12323
- } catch {
12324
- return "[INVALID_URL]";
12325
- }
12326
- }
12327
- _sanitizeConnectionOptions(options) {
12328
- if (!options || typeof options !== "object") return options;
12329
- const sanitized = { ...options };
12330
- if (sanitized.password) sanitized.password = "***";
12331
- if (sanitized.ssl && typeof sanitized.ssl === "object") {
12332
- sanitized.ssl = { ...sanitized.ssl };
12333
- if (sanitized.ssl.key) sanitized.ssl.key = "***";
12334
- if (sanitized.ssl.cert) sanitized.ssl.cert = "***";
12335
- if (sanitized.ssl.ca) sanitized.ssl.ca = "***";
12336
- }
12337
- return sanitized;
12338
- }
12339
- _handleRecordConnect(spanInfo, originalFunction, args) {
12398
+ handleRecordConnect(spanInfo, originalFunction, args) {
12340
12399
  const sqlInstance = originalFunction(...args);
12341
- const wrappedInstance = this._wrapSqlInstance(sqlInstance);
12400
+ const wrappedInstance = this.wrapSqlInstance(sqlInstance);
12342
12401
  try {
12343
12402
  logger.debug(`[PostgresInstrumentation] Postgres connection created successfully (${SpanUtils.getTraceInfo()})`);
12344
12403
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12345
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12404
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12346
12405
  } catch (error) {
12347
12406
  logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12348
12407
  }
12349
12408
  return wrappedInstance;
12350
12409
  }
12351
- _handleReplayConnect(originalFunction, args) {
12410
+ handleReplayConnect(originalFunction, args) {
12352
12411
  logger.debug(`[PostgresInstrumentation] Replaying Postgres connection`);
12353
12412
  try {
12354
12413
  const sqlInstance = originalFunction(...args);
12355
- return this._wrapSqlInstance(sqlInstance);
12414
+ return this.wrapSqlInstance(sqlInstance);
12356
12415
  } catch (error) {
12357
12416
  logger.debug(`[PostgresInstrumentation] Postgres connection error in replay: ${error.message}`);
12358
12417
  throw error;
12359
12418
  }
12360
12419
  }
12420
+ };
12421
+
12422
+ //#endregion
12423
+ //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12424
+ var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12425
+ var PostgresInstrumentation = class extends TdInstrumentationBase {
12426
+ constructor(config = {}) {
12427
+ super("postgres", config);
12428
+ this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12429
+ this.mode = config.mode || TuskDriftMode.DISABLED;
12430
+ this.tuskDrift = TuskDriftCore.getInstance();
12431
+ this.connectionHandler = new ConnectionHandler(this.mode, this.INSTRUMENTATION_NAME, () => this.tuskDrift.isAppReady(), (sqlInstance) => this._wrapSqlInstance(sqlInstance));
12432
+ }
12433
+ init() {
12434
+ return [new TdInstrumentationNodeModule({
12435
+ name: "postgres",
12436
+ supportedVersions: ["3.*"],
12437
+ patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12438
+ })];
12439
+ }
12440
+ _patchPostgresModule(postgresModule) {
12441
+ logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12442
+ if (this.isModulePatched(postgresModule)) {
12443
+ logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12444
+ return postgresModule;
12445
+ }
12446
+ const self = this;
12447
+ if (isEsm(postgresModule)) {
12448
+ logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12449
+ this._wrap(postgresModule, "default", (originalFunction) => {
12450
+ return function(...args) {
12451
+ return self._handlePostgresConnection(originalFunction, args);
12452
+ };
12453
+ });
12454
+ } else {
12455
+ logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12456
+ const originalFunction = postgresModule;
12457
+ const wrappedFunction = function(...args) {
12458
+ logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12459
+ return self._handlePostgresConnection(originalFunction, args);
12460
+ };
12461
+ Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12462
+ Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12463
+ for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12464
+ Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12465
+ if (key !== "prototype" && key !== "length" && key !== "name") {
12466
+ const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12467
+ if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12468
+ }
12469
+ });
12470
+ postgresModule = wrappedFunction;
12471
+ }
12472
+ if (postgresModule.sql && typeof postgresModule.sql === "function") {
12473
+ this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12474
+ logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12475
+ }
12476
+ this.markModuleAsPatched(postgresModule);
12477
+ logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12478
+ return postgresModule;
12479
+ }
12480
+ _handlePostgresConnection(originalFunction, args) {
12481
+ return this.connectionHandler.handlePostgresConnection(originalFunction, args);
12482
+ }
12361
12483
  _wrapSqlInstance(sqlInstance) {
12362
12484
  if (!sqlInstance || typeof sqlInstance !== "function") return sqlInstance;
12363
12485
  const self = this;
@@ -12373,11 +12495,34 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12373
12495
  logger.debug(`[PostgresInstrumentation] Wrapped unsafe method on sql instance`);
12374
12496
  }
12375
12497
  if (typeof originalSql.begin === "function") {
12376
- wrappedSql.begin = self._wrapBeginMethod(originalSql);
12377
- logger.debug(`[PostgresInstrumentation] Wrapped begin method on sql instance`);
12498
+ const wrappedBegin = self._wrapBeginMethod(originalSql);
12499
+ originalSql.begin = wrappedBegin;
12500
+ wrappedSql.begin = wrappedBegin;
12501
+ }
12502
+ if (typeof originalSql.file === "function") {
12503
+ wrappedSql.file = self._wrapFileMethod(originalSql);
12504
+ logger.debug(`[PostgresInstrumentation] Wrapped file method on sql instance`);
12505
+ }
12506
+ if (typeof originalSql.reserve === "function") {
12507
+ wrappedSql.reserve = self._wrapReserveMethod(originalSql);
12508
+ logger.debug(`[PostgresInstrumentation] Wrapped reserve method on sql instance`);
12509
+ }
12510
+ if (typeof originalSql.listen === "function") {
12511
+ wrappedSql.listen = self._wrapListenMethod(originalSql);
12512
+ logger.debug(`[PostgresInstrumentation] Wrapped listen method on sql instance`);
12513
+ }
12514
+ if (typeof originalSql.notify === "function") {
12515
+ wrappedSql.notify = self._wrapNotifyMethod(wrappedSql);
12516
+ logger.debug(`[PostgresInstrumentation] Wrapped notify method on sql instance`);
12378
12517
  }
12379
12518
  return wrappedSql;
12380
12519
  }
12520
+ _wrapNotifyMethod(wrappedSqlInstance) {
12521
+ return async function notify(channel, payload) {
12522
+ logger.debug(`[PostgresInstrumentation] notify() called for channel ${channel}`);
12523
+ return wrappedSqlInstance`select pg_notify(${channel}, ${String(payload)})`;
12524
+ };
12525
+ }
12381
12526
  _wrapUnsafeMethod(sqlInstance) {
12382
12527
  const self = this;
12383
12528
  const originalUnsafe = sqlInstance.unsafe;
@@ -12394,6 +12539,175 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12394
12539
  return self._handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback);
12395
12540
  };
12396
12541
  }
12542
+ _wrapFileMethod(sqlInstance) {
12543
+ const self = this;
12544
+ const originalFile = sqlInstance.file;
12545
+ return function file(path$5, parameters, queryOptions) {
12546
+ return self._handleFileQuery(sqlInstance, originalFile, path$5, parameters, queryOptions);
12547
+ };
12548
+ }
12549
+ _wrapReserveMethod(sqlInstance) {
12550
+ const self = this;
12551
+ const originalReserve = sqlInstance.reserve;
12552
+ return async function reserve() {
12553
+ if (self.mode === TuskDriftMode.REPLAY) {
12554
+ logger.debug(`[PostgresInstrumentation] REPLAY mode: Creating mock reserved connection without TCP`);
12555
+ const mockReservedSql = self._wrapSqlInstance(sqlInstance);
12556
+ if (typeof mockReservedSql === "function") mockReservedSql.release = function() {
12557
+ logger.debug(`[PostgresInstrumentation] Mock reserved connection released`);
12558
+ };
12559
+ return mockReservedSql;
12560
+ }
12561
+ const reservedSql = await originalReserve.call(sqlInstance);
12562
+ const wrappedReservedSql = self._wrapSqlInstance(reservedSql);
12563
+ logger.debug(`[PostgresInstrumentation] Reserved connection obtained and wrapped`);
12564
+ return wrappedReservedSql;
12565
+ };
12566
+ }
12567
+ _wrapListenMethod(sqlInstance) {
12568
+ const self = this;
12569
+ const originalListen = sqlInstance.listen;
12570
+ return async function listen(channelName, callback, onlisten) {
12571
+ return self._handleListenMethod(sqlInstance, originalListen, channelName, callback, onlisten);
12572
+ };
12573
+ }
12574
+ async _handleListenMethod(sqlInstance, originalListen, channelName, callback, onlisten) {
12575
+ const inputValue = {
12576
+ operation: "listen",
12577
+ channel: channelName
12578
+ };
12579
+ if (this.mode === TuskDriftMode.REPLAY) return this._handleReplayListen(channelName, callback, onlisten, inputValue);
12580
+ else if (this.mode === TuskDriftMode.RECORD) return this._handleRecordListen(sqlInstance, originalListen, channelName, callback, onlisten, inputValue);
12581
+ else return originalListen.call(sqlInstance, channelName, callback, onlisten);
12582
+ }
12583
+ async _handleRecordListen(sqlInstance, originalListen, channelName, callback, onlisten, inputValue) {
12584
+ const receivedPayloads = [];
12585
+ const wrappedCallback = (payload) => {
12586
+ logger.debug(`[PostgresInstrumentation] RECORD: Captured notification payload on channel ${channelName}: ${payload}`);
12587
+ receivedPayloads.push(payload);
12588
+ callback(payload);
12589
+ };
12590
+ return handleRecordMode({
12591
+ originalFunctionCall: () => originalListen.call(sqlInstance, channelName, callback, onlisten),
12592
+ recordModeHandler: ({ isPreAppStart }) => {
12593
+ return SpanUtils.createAndExecuteSpan(this.mode, () => originalListen.call(sqlInstance, channelName, callback, onlisten), {
12594
+ name: "postgres.listen",
12595
+ kind: import_src$25.SpanKind.CLIENT,
12596
+ submodule: "listen",
12597
+ packageType: PackageType.PG,
12598
+ packageName: "postgres",
12599
+ instrumentationName: this.INSTRUMENTATION_NAME,
12600
+ inputValue,
12601
+ isPreAppStart
12602
+ }, async (spanInfo) => {
12603
+ try {
12604
+ const result = await originalListen.call(sqlInstance, channelName, wrappedCallback, onlisten);
12605
+ try {
12606
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12607
+ channel: channelName,
12608
+ state: result.state
12609
+ } });
12610
+ } catch (error) {
12611
+ logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12612
+ }
12613
+ const originalUnlisten = result.unlisten;
12614
+ const wrappedUnlisten = async () => {
12615
+ logger.debug(`[PostgresInstrumentation] RECORD: Unlisten called, captured ${receivedPayloads.length} payloads`);
12616
+ try {
12617
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12618
+ channel: channelName,
12619
+ state: result.state,
12620
+ payloads: receivedPayloads
12621
+ } });
12622
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12623
+ } catch (error) {
12624
+ logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12625
+ }
12626
+ return originalUnlisten();
12627
+ };
12628
+ return {
12629
+ state: result.state,
12630
+ unlisten: wrappedUnlisten
12631
+ };
12632
+ } catch (error) {
12633
+ logger.error(`[PostgresInstrumentation] RECORD listen error: ${error.message}`);
12634
+ try {
12635
+ SpanUtils.endSpan(spanInfo.span, {
12636
+ code: import_src$25.SpanStatusCode.ERROR,
12637
+ message: error.message
12638
+ });
12639
+ } catch (error$1) {
12640
+ logger.error(`[PostgresInstrumentation] error ending span:`, error$1);
12641
+ }
12642
+ throw error;
12643
+ }
12644
+ });
12645
+ },
12646
+ spanKind: import_src$25.SpanKind.CLIENT
12647
+ });
12648
+ }
12649
+ async _handleReplayListen(channelName, callback, onlisten, inputValue) {
12650
+ logger.debug(`[PostgresInstrumentation] REPLAY: Mocking listen for channel ${channelName} without TCP`);
12651
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12652
+ return handleReplayMode({
12653
+ noOpRequestHandler: () => Promise.resolve({
12654
+ state: { state: "I" },
12655
+ unlisten: async () => {}
12656
+ }),
12657
+ isServerRequest: false,
12658
+ replayModeHandler: () => {
12659
+ return SpanUtils.createAndExecuteSpan(this.mode, () => Promise.resolve({
12660
+ state: { state: "I" },
12661
+ unlisten: async () => {}
12662
+ }), {
12663
+ name: "postgres.listen",
12664
+ kind: import_src$25.SpanKind.CLIENT,
12665
+ submodule: "listen",
12666
+ packageType: PackageType.PG,
12667
+ packageName: "postgres",
12668
+ instrumentationName: this.INSTRUMENTATION_NAME,
12669
+ inputValue,
12670
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12671
+ }, async (spanInfo) => {
12672
+ try {
12673
+ const mockData = await this._findMockData({
12674
+ spanInfo,
12675
+ name: "postgres.listen",
12676
+ inputValue,
12677
+ submoduleName: "listen",
12678
+ stackTrace
12679
+ });
12680
+ if (!mockData) {
12681
+ logger.warn(`[PostgresInstrumentation] No mock data found for listen channel: ${channelName}`);
12682
+ throw new Error(`No mock data found for listen channel: ${channelName}`);
12683
+ }
12684
+ logger.debug(`[PostgresInstrumentation] Found mock data for listen: ${JSON.stringify(mockData)}`);
12685
+ const recordedPayloads = mockData.result?.payloads || [];
12686
+ const recordedState = mockData.result?.state || { state: "I" };
12687
+ if (onlisten) onlisten();
12688
+ for (const payload of recordedPayloads) {
12689
+ logger.debug(`[PostgresInstrumentation] REPLAY: Invoking callback with recorded payload: ${payload}`);
12690
+ callback(payload);
12691
+ }
12692
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12693
+ return {
12694
+ state: recordedState,
12695
+ unlisten: async () => {
12696
+ logger.debug(`[PostgresInstrumentation] REPLAY: Mock unlisten called`);
12697
+ }
12698
+ };
12699
+ } catch (error) {
12700
+ logger.error(`[PostgresInstrumentation] REPLAY listen error: ${error.message}`);
12701
+ SpanUtils.endSpan(spanInfo.span, {
12702
+ code: import_src$25.SpanStatusCode.ERROR,
12703
+ message: error.message
12704
+ });
12705
+ throw error;
12706
+ }
12707
+ });
12708
+ }
12709
+ });
12710
+ }
12397
12711
  _getSqlPatchFn() {
12398
12712
  const self = this;
12399
12713
  return (originalSql) => {
@@ -12406,93 +12720,19 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12406
12720
  if (!strings || !Array.isArray(strings.raw)) return originalSql.call(this, strings, ...values);
12407
12721
  const creationContext = import_src$25.context.active();
12408
12722
  const query = originalSql.call(this, strings, ...values);
12723
+ const inputValue = {
12724
+ query: reconstructQueryString(strings, values).trim(),
12725
+ parameters: values
12726
+ };
12409
12727
  const originalThen = query.then.bind(query);
12410
- const self = this;
12411
- query.then = function(onFulfilled, onRejected) {
12412
- let queryString = "";
12413
- for (let i = 0; i < strings.length; i++) {
12414
- queryString += strings[i];
12415
- if (i < values.length) queryString += `$${i + 1}`;
12416
- }
12417
- const inputValue = {
12418
- query: queryString.trim(),
12419
- parameters: values
12420
- };
12421
- return import_src$25.context.with(creationContext, () => {
12422
- if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12423
- originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12424
- recordModeHandler: ({ isPreAppStart }) => {
12425
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12426
- name: "postgres.query",
12427
- kind: import_src$25.SpanKind.CLIENT,
12428
- submodule: "query",
12429
- packageType: PackageType.PG,
12430
- instrumentationName: self.INSTRUMENTATION_NAME,
12431
- packageName: "postgres",
12432
- inputValue,
12433
- isPreAppStart
12434
- }, (spanInfo) => {
12435
- const wrappedOnFulfilled = (result) => {
12436
- try {
12437
- logger.debug(`[PostgresInstrumentation] Postgres query completed successfully`, result);
12438
- self._addOutputAttributesToSpan(spanInfo, result);
12439
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12440
- } catch (error) {
12441
- logger.error(`[PostgresInstrumentation] error processing query response:`, error);
12442
- }
12443
- return onFulfilled ? onFulfilled(result) : result;
12444
- };
12445
- const wrappedOnRejected = (error) => {
12446
- try {
12447
- logger.debug(`[PostgresInstrumentation] Postgres query error`, error);
12448
- SpanUtils.endSpan(spanInfo.span, {
12449
- code: import_src$25.SpanStatusCode.ERROR,
12450
- message: error.message
12451
- });
12452
- } catch (spanError) {
12453
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12454
- }
12455
- if (onRejected) return onRejected(error);
12456
- throw error;
12457
- };
12458
- return originalThen(wrappedOnFulfilled, wrappedOnRejected);
12459
- });
12460
- },
12461
- spanKind: import_src$25.SpanKind.CLIENT
12462
- });
12463
- else if (self.mode === TuskDriftMode.REPLAY) {
12464
- const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12465
- return handleReplayMode({
12466
- noOpRequestHandler: () => Promise.resolve(Object.assign([], {
12467
- count: 0,
12468
- command: null
12469
- })),
12470
- isServerRequest: false,
12471
- replayModeHandler: () => {
12472
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12473
- name: "postgres.query",
12474
- kind: import_src$25.SpanKind.CLIENT,
12475
- submodule: "query",
12476
- packageType: PackageType.PG,
12477
- packageName: "postgres",
12478
- instrumentationName: self.INSTRUMENTATION_NAME,
12479
- inputValue,
12480
- isPreAppStart: false
12481
- }, async (spanInfo) => {
12482
- const mockedResult = await self.handleReplaySqlQuery({
12483
- inputValue,
12484
- spanInfo,
12485
- submodule: "query",
12486
- name: "postgres.query",
12487
- stackTrace
12488
- });
12489
- return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12490
- });
12491
- }
12492
- });
12493
- } else return originalThen(onFulfilled, onRejected);
12494
- });
12495
- };
12728
+ this._wrapThenMethod(query, originalThen, inputValue, creationContext, {
12729
+ name: "postgres.query",
12730
+ submodule: "query",
12731
+ operationType: "sql"
12732
+ });
12733
+ this._wrapExecuteMethod(query);
12734
+ this._wrapCursorMethod(query, inputValue, creationContext);
12735
+ this._wrapForEachMethod(query, inputValue, creationContext);
12496
12736
  return query;
12497
12737
  }
12498
12738
  _handleUnsafeQuery(sqlInstance, originalUnsafe, query, parameters, queryOptions) {
@@ -12503,21 +12743,46 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12503
12743
  })();
12504
12744
  const creationContext = import_src$25.context.active();
12505
12745
  const originalThen = unsafeQuery.then.bind(unsafeQuery);
12506
- const self = this;
12507
12746
  const inputValue = {
12508
12747
  query: query.trim(),
12509
12748
  parameters: parameters || [],
12510
12749
  options: queryOptions
12511
12750
  };
12512
- unsafeQuery.then = function(onFulfilled, onRejected) {
12751
+ this._wrapThenMethod(unsafeQuery, originalThen, inputValue, creationContext, {
12752
+ name: "postgres.unsafe",
12753
+ submodule: "unsafe",
12754
+ operationType: "unsafe"
12755
+ });
12756
+ this._wrapExecuteMethod(unsafeQuery);
12757
+ this._wrapCursorMethod(unsafeQuery, inputValue, creationContext);
12758
+ this._wrapForEachMethod(unsafeQuery, inputValue, creationContext);
12759
+ return unsafeQuery;
12760
+ }
12761
+ _handleFileQuery(sqlInstance, originalFile, path$5, parameters, queryOptions) {
12762
+ const fileQuery = (() => {
12763
+ if (queryOptions !== void 0) return originalFile.call(sqlInstance, path$5, parameters, queryOptions);
12764
+ else if (parameters !== void 0) return originalFile.call(sqlInstance, path$5, parameters);
12765
+ else return originalFile.call(sqlInstance, path$5);
12766
+ })();
12767
+ const creationContext = import_src$25.context.active();
12768
+ const originalThen = fileQuery.then.bind(fileQuery);
12769
+ const self = this;
12770
+ const inputValue = {
12771
+ query: path$5,
12772
+ parameters: parameters || [],
12773
+ options: queryOptions
12774
+ };
12775
+ fileQuery.then = function(onFulfilled, onRejected) {
12776
+ if (fileQuery._tuskRecorded) return originalThen(onFulfilled, onRejected);
12777
+ fileQuery._tuskRecorded = true;
12513
12778
  return import_src$25.context.with(creationContext, () => {
12514
12779
  if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12515
12780
  originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12516
12781
  recordModeHandler: ({ isPreAppStart }) => {
12517
12782
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12518
- name: "postgres.unsafe",
12783
+ name: "postgres.file",
12519
12784
  kind: import_src$25.SpanKind.CLIENT,
12520
- submodule: "unsafe",
12785
+ submodule: "file",
12521
12786
  packageType: PackageType.PG,
12522
12787
  packageName: "postgres",
12523
12788
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -12526,17 +12791,17 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12526
12791
  }, (spanInfo) => {
12527
12792
  const wrappedOnFulfilled = (result) => {
12528
12793
  try {
12529
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query completed successfully (${SpanUtils.getTraceInfo()})`);
12530
- self._addOutputAttributesToSpan(spanInfo, result);
12794
+ logger.debug(`[PostgresInstrumentation] Postgres file query completed successfully (${SpanUtils.getTraceInfo()})`);
12795
+ addOutputAttributesToSpan(spanInfo, result);
12531
12796
  SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12532
12797
  } catch (error) {
12533
- logger.error(`[PostgresInstrumentation] error processing unsafe query response:`, error);
12798
+ logger.error(`[PostgresInstrumentation] error processing file query response:`, error);
12534
12799
  }
12535
12800
  return onFulfilled ? onFulfilled(result) : result;
12536
12801
  };
12537
12802
  const wrappedOnRejected = (error) => {
12538
12803
  try {
12539
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query error: ${error.message}`);
12804
+ logger.debug(`[PostgresInstrumentation] Postgres file query error: ${error.message}`);
12540
12805
  SpanUtils.endSpan(spanInfo.span, {
12541
12806
  code: import_src$25.SpanStatusCode.ERROR,
12542
12807
  message: error.message
@@ -12562,22 +12827,24 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12562
12827
  isServerRequest: false,
12563
12828
  replayModeHandler: () => {
12564
12829
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12565
- name: "postgres.unsafe",
12830
+ name: "postgres.file",
12566
12831
  kind: import_src$25.SpanKind.CLIENT,
12567
- submodule: "unsafe",
12832
+ submodule: "file",
12568
12833
  packageType: PackageType.PG,
12569
12834
  packageName: "postgres",
12570
12835
  instrumentationName: self.INSTRUMENTATION_NAME,
12571
12836
  inputValue,
12572
- isPreAppStart: false
12837
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
12573
12838
  }, async (spanInfo) => {
12574
- const mockedResult = await self.handleReplayUnsafeQuery({
12839
+ const mockedResult = await self._handleReplayQueryOperation({
12575
12840
  inputValue,
12576
12841
  spanInfo,
12577
- submodule: "unsafe",
12578
- name: "postgres.unsafe",
12579
- stackTrace
12842
+ submodule: "file",
12843
+ name: "postgres.file",
12844
+ stackTrace,
12845
+ operationType: "file"
12580
12846
  });
12847
+ if (!mockedResult) throw new Error(`No mock data found for Postgres file query: ${inputValue.query}`);
12581
12848
  return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12582
12849
  });
12583
12850
  }
@@ -12585,16 +12852,45 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12585
12852
  } else return originalThen(onFulfilled, onRejected);
12586
12853
  });
12587
12854
  };
12588
- return unsafeQuery;
12855
+ const originalExecute = fileQuery.execute ? fileQuery.execute.bind(fileQuery) : void 0;
12856
+ if (originalExecute) fileQuery.execute = function() {
12857
+ if (self.mode === TuskDriftMode.REPLAY) return this;
12858
+ else return originalExecute.call(this);
12859
+ };
12860
+ return fileQuery;
12861
+ }
12862
+ /**
12863
+ * Wraps a transaction callback to ensure the inner SQL instance is instrumented.
12864
+ * This is necessary because postgres.js creates a new SQL instance inside begin()
12865
+ * that would otherwise bypass instrumentation.
12866
+ */
12867
+ _wrapTransactionCallback(transactionCallback) {
12868
+ const self = this;
12869
+ return (transactionSql) => {
12870
+ const wrappedSql = self._wrapSqlInstance(transactionSql);
12871
+ if (typeof transactionSql.savepoint === "function") {
12872
+ const originalSavepoint = transactionSql.savepoint;
12873
+ wrappedSql.savepoint = function(nameOrFn, fn) {
12874
+ const savepointCallback = typeof nameOrFn === "function" ? nameOrFn : fn;
12875
+ const savepointName = typeof nameOrFn === "string" ? nameOrFn : void 0;
12876
+ const wrappedSavepointCallback = self._wrapTransactionCallback(savepointCallback);
12877
+ if (savepointName) return originalSavepoint.call(transactionSql, savepointName, wrappedSavepointCallback);
12878
+ else return originalSavepoint.call(transactionSql, wrappedSavepointCallback);
12879
+ };
12880
+ }
12881
+ if (typeof transactionSql.prepare === "function") wrappedSql.prepare = transactionSql.prepare.bind(transactionSql);
12882
+ return transactionCallback(wrappedSql);
12883
+ };
12589
12884
  }
12590
12885
  _handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback) {
12591
12886
  const inputValue = {
12592
12887
  query: "BEGIN",
12593
12888
  options: options ? { transactionOptions: options } : void 0
12594
12889
  };
12890
+ const wrappedCallback = transactionCallback ? this._wrapTransactionCallback(transactionCallback) : void 0;
12595
12891
  const executeBegin = () => {
12596
- if (options && transactionCallback) return originalBegin.call(sqlInstance, options, transactionCallback);
12597
- else if (transactionCallback) return originalBegin.call(sqlInstance, transactionCallback);
12892
+ if (options && wrappedCallback) return originalBegin.call(sqlInstance, options, wrappedCallback);
12893
+ else if (wrappedCallback) return originalBegin.call(sqlInstance, wrappedCallback);
12598
12894
  else return originalBegin.call(sqlInstance, options || void 0);
12599
12895
  };
12600
12896
  if (this.mode === TuskDriftMode.REPLAY) {
@@ -12611,9 +12907,9 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12611
12907
  packageName: "postgres",
12612
12908
  instrumentationName: this.INSTRUMENTATION_NAME,
12613
12909
  inputValue,
12614
- isPreAppStart: false
12910
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12615
12911
  }, (spanInfo) => {
12616
- return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
12912
+ return this._handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback);
12617
12913
  });
12618
12914
  }
12619
12915
  });
@@ -12638,151 +12934,672 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12638
12934
  else return executeBegin();
12639
12935
  }
12640
12936
  _handleRecordBeginTransaction(spanInfo, executeBegin) {
12641
- const promise = executeBegin();
12642
- promise.finally(() => {
12643
- promise.then((result) => {
12644
- logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12645
- try {
12646
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12647
- status: "committed",
12648
- result
12649
- } });
12650
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12651
- } catch (error) {
12652
- logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12937
+ return executeBegin().then((result) => {
12938
+ logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12939
+ try {
12940
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12941
+ status: "committed",
12942
+ result
12943
+ } });
12944
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12945
+ } catch (error) {
12946
+ logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12947
+ }
12948
+ return result;
12949
+ }).catch((error) => {
12950
+ logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12951
+ try {
12952
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12953
+ status: "rolled_back",
12954
+ error: error.message
12955
+ } });
12956
+ SpanUtils.endSpan(spanInfo.span, {
12957
+ code: import_src$25.SpanStatusCode.ERROR,
12958
+ message: error.message
12959
+ });
12960
+ } catch (spanError) {
12961
+ logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12962
+ }
12963
+ throw error;
12964
+ });
12965
+ }
12966
+ async _handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback) {
12967
+ logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
12968
+ const transactionInputValue = {
12969
+ query: "BEGIN",
12970
+ options: options ? { transactionOptions: options } : void 0
12971
+ };
12972
+ const mockData = await this._findMockData({
12973
+ spanInfo,
12974
+ name: "postgres.begin",
12975
+ inputValue: transactionInputValue,
12976
+ submoduleName: "transaction",
12977
+ stackTrace
12978
+ });
12979
+ if (!mockData) {
12980
+ logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
12981
+ throw new Error(`[PostgresInstrumentation] No matching mock found for transaction BEGIN`);
12982
+ }
12983
+ logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
12984
+ const transactionResult = mockData.result;
12985
+ const wasCommitted = transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed";
12986
+ if (!wrappedCallback) if (wasCommitted) return transactionResult.result;
12987
+ else {
12988
+ const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
12989
+ throw new Error(errorMessage);
12990
+ }
12991
+ try {
12992
+ const result = await wrappedCallback(this._createMockTransactionSql());
12993
+ logger.debug(`[PostgresInstrumentation] Replay transaction callback completed with result`);
12994
+ return result;
12995
+ } catch (error) {
12996
+ if (!wasCommitted) throw error;
12997
+ logger.error(`[PostgresInstrumentation] Unexpected error during transaction replay: ${error.message}`);
12998
+ throw error;
12999
+ }
13000
+ }
13001
+ /**
13002
+ * Creates a minimal mock SQL instance for transaction replay.
13003
+ * _wrapSqlInstance will wrap this and handle all the actual REPLAY logic.
13004
+ * The mock just needs to return objects with .then() methods that can be wrapped.
13005
+ */
13006
+ _createMockTransactionSql() {
13007
+ const self = this;
13008
+ const createThenable = () => ({ then: (onFulfilled, onRejected) => Promise.resolve([]).then(onFulfilled, onRejected) });
13009
+ const mockSql = function() {
13010
+ return createThenable();
13011
+ };
13012
+ mockSql.unsafe = function() {
13013
+ return createThenable();
13014
+ };
13015
+ mockSql.savepoint = function(nameOrFn, fn) {
13016
+ const callback = typeof nameOrFn === "function" ? nameOrFn : fn;
13017
+ const nestedMockSql = self._createMockTransactionSql();
13018
+ return Promise.resolve(callback(nestedMockSql));
13019
+ };
13020
+ return mockSql;
13021
+ }
13022
+ /**
13023
+ * Generic helper to find mock data for replay operations.
13024
+ * Consolidates the common findMockResponseAsync pattern used across multiple handlers.
13025
+ */
13026
+ async _findMockData({ spanInfo, name, inputValue, submoduleName, stackTrace }) {
13027
+ return findMockResponseAsync({
13028
+ mockRequestData: {
13029
+ traceId: spanInfo.traceId,
13030
+ spanId: spanInfo.spanId,
13031
+ name,
13032
+ inputValue: createMockInputValue(inputValue),
13033
+ packageName: "postgres",
13034
+ instrumentationName: this.INSTRUMENTATION_NAME,
13035
+ submoduleName,
13036
+ kind: import_src$25.SpanKind.CLIENT,
13037
+ stackTrace
13038
+ },
13039
+ tuskDrift: this.tuskDrift
13040
+ });
13041
+ }
13042
+ /**
13043
+ * Helper to end a cursor span with collected rows.
13044
+ * Consolidates common span ending logic used in cursor and forEach operations.
13045
+ */
13046
+ _endCursorSpan(spanInfo, allRows, result, operation = "Cursor") {
13047
+ addOutputAttributesToSpan(spanInfo, Object.assign(allRows, {
13048
+ count: allRows.length,
13049
+ columns: result?.columns,
13050
+ state: result?.state,
13051
+ statement: result?.statement
13052
+ }));
13053
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13054
+ logger.debug(`[PostgresInstrumentation] ${operation} completed, recorded ${allRows.length} rows`);
13055
+ }
13056
+ /**
13057
+ * Generic helper to handle replay for query operations (sql, unsafe, file).
13058
+ * Consolidates common logic for finding mock data and processing results.
13059
+ */
13060
+ async _handleReplayQueryOperation({ inputValue, spanInfo, submodule, name, stackTrace, operationType }) {
13061
+ logger.debug(`[PostgresInstrumentation] Replaying Postgres ${operationType} query`);
13062
+ const mockData = await this._findMockData({
13063
+ spanInfo,
13064
+ name,
13065
+ inputValue,
13066
+ submoduleName: submodule,
13067
+ stackTrace
13068
+ });
13069
+ if (!mockData) {
13070
+ const errorMsg = `[PostgresInstrumentation] No matching mock found for Postgres ${operationType} query: ${inputValue.query || "UNKNOWN_QUERY"}`;
13071
+ logger.warn(errorMsg);
13072
+ throw new Error(errorMsg);
13073
+ }
13074
+ logger.debug(`[PostgresInstrumentation] Found mock data for Postgres ${operationType} query: ${JSON.stringify(mockData)}`);
13075
+ const processedResult = convertPostgresTypes(mockData.result);
13076
+ logger.debug(`[PostgresInstrumentation] ${operationType} query processed result: ${JSON.stringify(processedResult)}`);
13077
+ return processedResult;
13078
+ }
13079
+ _handleCursorCallbackRecord({ originalCursor, rows, inputValue, creationContext, userCallback }) {
13080
+ const self = this;
13081
+ return import_src$25.context.with(creationContext, () => {
13082
+ return handleRecordMode({
13083
+ originalFunctionCall: () => originalCursor(rows, userCallback),
13084
+ recordModeHandler: ({ isPreAppStart }) => {
13085
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalCursor(rows, userCallback), {
13086
+ name: "postgres.cursor",
13087
+ kind: import_src$25.SpanKind.CLIENT,
13088
+ submodule: "cursor",
13089
+ packageType: PackageType.PG,
13090
+ packageName: "postgres",
13091
+ instrumentationName: self.INSTRUMENTATION_NAME,
13092
+ inputValue,
13093
+ isPreAppStart
13094
+ }, (spanInfo) => {
13095
+ return self._executeAndRecordCursorCallback({
13096
+ originalCursor,
13097
+ rows,
13098
+ userCallback,
13099
+ spanInfo
13100
+ });
13101
+ });
13102
+ },
13103
+ spanKind: import_src$25.SpanKind.CLIENT
13104
+ });
13105
+ });
13106
+ }
13107
+ async _executeAndRecordCursorCallback({ originalCursor, rows, userCallback, spanInfo }) {
13108
+ const allRows = [];
13109
+ try {
13110
+ const wrappedCallback = (batchRows) => {
13111
+ allRows.push(...batchRows);
13112
+ return userCallback(batchRows);
13113
+ };
13114
+ const cursorPromise = originalCursor(rows, wrappedCallback);
13115
+ cursorPromise._tuskRecorded = true;
13116
+ const result = await cursorPromise;
13117
+ if (spanInfo) try {
13118
+ this._endCursorSpan(spanInfo, allRows, result, "Cursor callback");
13119
+ } catch (error) {
13120
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13121
+ }
13122
+ } catch (error) {
13123
+ logger.debug(`[PostgresInstrumentation] Cursor callback error: ${error.message}`);
13124
+ if (spanInfo) try {
13125
+ SpanUtils.endSpan(spanInfo.span, {
13126
+ code: import_src$25.SpanStatusCode.ERROR,
13127
+ message: error.message
13128
+ });
13129
+ } catch (error$1) {
13130
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13131
+ }
13132
+ throw error;
13133
+ }
13134
+ }
13135
+ _handleCursorCallbackReplay({ inputValue, creationContext, cursorBatchSize, userCallback }) {
13136
+ const self = this;
13137
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13138
+ return import_src$25.context.with(creationContext, () => {
13139
+ return handleReplayMode({
13140
+ noOpRequestHandler: () => Promise.resolve(),
13141
+ isServerRequest: false,
13142
+ replayModeHandler: () => {
13143
+ return SpanUtils.createAndExecuteSpan(self.mode, () => Promise.resolve(), {
13144
+ name: "postgres.cursor",
13145
+ kind: import_src$25.SpanKind.CLIENT,
13146
+ submodule: "cursor",
13147
+ packageType: PackageType.PG,
13148
+ packageName: "postgres",
13149
+ instrumentationName: self.INSTRUMENTATION_NAME,
13150
+ inputValue,
13151
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13152
+ }, async (spanInfo) => {
13153
+ try {
13154
+ const mockData = await this._findMockData({
13155
+ spanInfo,
13156
+ name: "postgres.cursor",
13157
+ inputValue,
13158
+ submoduleName: "cursor",
13159
+ stackTrace
13160
+ });
13161
+ if (!mockData) throw new Error(`[PostgresInstrumentation] No matching mock found for cursor query: ${inputValue.query}`);
13162
+ logger.debug(`[PostgresInstrumentation] Found mock data for cursor query: ${JSON.stringify(mockData)}`);
13163
+ const processedResult = convertPostgresTypes(mockData.result);
13164
+ const mockedData = Array.isArray(processedResult) ? processedResult : [];
13165
+ for (let i = 0; i < mockedData.length; i += cursorBatchSize) {
13166
+ const batch = mockedData.slice(i, i + cursorBatchSize);
13167
+ logger.debug(`[PostgresInstrumentation] Cursor replay calling callback with batch of ${batch.length} rows`);
13168
+ await userCallback(batch);
13169
+ }
13170
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13171
+ } catch (error) {
13172
+ logger.debug(`[PostgresInstrumentation] Cursor callback replay error: ${error.message}`);
13173
+ SpanUtils.endSpan(spanInfo.span, {
13174
+ code: import_src$25.SpanStatusCode.ERROR,
13175
+ message: error.message
13176
+ });
13177
+ throw error;
13178
+ }
13179
+ });
12653
13180
  }
12654
- }).catch((error) => {
12655
- logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12656
- try {
12657
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12658
- status: "rolled_back",
12659
- error: error.message
12660
- } });
12661
- SpanUtils.endSpan(spanInfo.span, {
12662
- code: import_src$25.SpanStatusCode.ERROR,
12663
- message: error.message
13181
+ });
13182
+ });
13183
+ }
13184
+ _handleCursorRecord({ originalCursor, rows, inputValue, creationContext, queryObject }) {
13185
+ const self = this;
13186
+ return { [Symbol.asyncIterator]() {
13187
+ const iterator = originalCursor(rows)[Symbol.asyncIterator]();
13188
+ let allRows = [];
13189
+ let result;
13190
+ let spanInfo = null;
13191
+ let spanStarted = false;
13192
+ return {
13193
+ async next() {
13194
+ return import_src$25.context.with(creationContext, async () => {
13195
+ if (!spanStarted) {
13196
+ spanStarted = true;
13197
+ let spanInputValue;
13198
+ try {
13199
+ spanInputValue = createSpanInputValue(inputValue);
13200
+ } catch (error) {
13201
+ logger.error(`[PostgresInstrumentation] error creating span input value:`, error);
13202
+ spanInputValue = void 0;
13203
+ }
13204
+ spanInfo = SpanUtils.createSpan({
13205
+ name: "postgres.cursor",
13206
+ kind: import_src$25.SpanKind.CLIENT,
13207
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true,
13208
+ attributes: {
13209
+ [TdSpanAttributes.NAME]: "postgres.cursor",
13210
+ [TdSpanAttributes.PACKAGE_NAME]: "postgres",
13211
+ [TdSpanAttributes.SUBMODULE_NAME]: "cursor",
13212
+ [TdSpanAttributes.INSTRUMENTATION_NAME]: self.INSTRUMENTATION_NAME,
13213
+ [TdSpanAttributes.PACKAGE_TYPE]: PackageType.PG,
13214
+ [TdSpanAttributes.INPUT_VALUE]: spanInputValue,
13215
+ [TdSpanAttributes.IS_PRE_APP_START]: self.tuskDrift.isAppReady() ? false : true
13216
+ }
13217
+ });
13218
+ if (!spanInfo) logger.warn(`[PostgresInstrumentation] Failed to create cursor span in RECORD mode`);
13219
+ }
13220
+ try {
13221
+ result = await iterator.next();
13222
+ if (result.done) {
13223
+ if (spanInfo) try {
13224
+ self._endCursorSpan(spanInfo, allRows, queryObject, "Cursor");
13225
+ } catch (error) {
13226
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13227
+ }
13228
+ return {
13229
+ done: true,
13230
+ value: void 0
13231
+ };
13232
+ }
13233
+ if (Array.isArray(result.value)) allRows.push(...result.value);
13234
+ return {
13235
+ done: false,
13236
+ value: result.value
13237
+ };
13238
+ } catch (error) {
13239
+ if (spanInfo) try {
13240
+ SpanUtils.endSpan(spanInfo.span, {
13241
+ code: import_src$25.SpanStatusCode.ERROR,
13242
+ message: error.message
13243
+ });
13244
+ } catch (error$1) {
13245
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13246
+ }
13247
+ throw error;
13248
+ }
13249
+ });
13250
+ },
13251
+ async return() {
13252
+ if (spanInfo) try {
13253
+ self._endCursorSpan(spanInfo, allRows, queryObject, "Cursor terminated early");
13254
+ } catch (error) {
13255
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13256
+ }
13257
+ if (iterator.return) await iterator.return();
13258
+ return {
13259
+ done: true,
13260
+ value: void 0
13261
+ };
13262
+ }
13263
+ };
13264
+ } };
13265
+ }
13266
+ _handleCursorReplay({ inputValue, creationContext, cursorBatchSize }) {
13267
+ const self = this;
13268
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13269
+ return { [Symbol.asyncIterator]() {
13270
+ let mockedData = null;
13271
+ let currentIndex = 0;
13272
+ let spanInfo = null;
13273
+ let dataFetched = false;
13274
+ return {
13275
+ async next() {
13276
+ return import_src$25.context.with(creationContext, async () => {
13277
+ if (!dataFetched) {
13278
+ dataFetched = true;
13279
+ spanInfo = SpanUtils.createSpan({
13280
+ name: "postgres.cursor",
13281
+ kind: import_src$25.SpanKind.CLIENT,
13282
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true,
13283
+ attributes: {
13284
+ [TdSpanAttributes.NAME]: "postgres.cursor",
13285
+ [TdSpanAttributes.PACKAGE_NAME]: "postgres",
13286
+ [TdSpanAttributes.SUBMODULE_NAME]: "cursor",
13287
+ [TdSpanAttributes.INSTRUMENTATION_NAME]: self.INSTRUMENTATION_NAME,
13288
+ [TdSpanAttributes.PACKAGE_TYPE]: PackageType.PG,
13289
+ [TdSpanAttributes.INPUT_VALUE]: createSpanInputValue(inputValue),
13290
+ [TdSpanAttributes.IS_PRE_APP_START]: self.tuskDrift.isAppReady() ? false : true
13291
+ }
13292
+ });
13293
+ if (!spanInfo) throw new Error(`[PostgresInstrumentation] Failed to create cursor span in REPLAY mode`);
13294
+ const mockData = await self._findMockData({
13295
+ spanInfo,
13296
+ name: "postgres.cursor",
13297
+ inputValue,
13298
+ submoduleName: "cursor",
13299
+ stackTrace
13300
+ });
13301
+ if (!mockData) {
13302
+ SpanUtils.endSpan(spanInfo.span, {
13303
+ code: import_src$25.SpanStatusCode.ERROR,
13304
+ message: "No mock data found"
13305
+ });
13306
+ throw new Error(`[PostgresInstrumentation] No matching mock found for cursor query: ${inputValue.query}`);
13307
+ }
13308
+ logger.debug(`[PostgresInstrumentation] Found mock data for cursor query: ${JSON.stringify(mockData)}`);
13309
+ const processedResult = convertPostgresTypes(mockData.result);
13310
+ mockedData = Array.isArray(processedResult) ? processedResult : [];
13311
+ }
13312
+ if (currentIndex >= mockedData.length) {
13313
+ if (spanInfo) SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13314
+ return {
13315
+ done: true,
13316
+ value: void 0
13317
+ };
13318
+ }
13319
+ const batch = mockedData.slice(currentIndex, currentIndex + cursorBatchSize);
13320
+ currentIndex += batch.length;
13321
+ logger.debug(`[PostgresInstrumentation] Cursor replay returning batch of ${batch.length} rows`);
13322
+ return {
13323
+ done: false,
13324
+ value: batch
13325
+ };
13326
+ });
13327
+ },
13328
+ async return() {
13329
+ if (spanInfo) SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13330
+ return {
13331
+ done: true,
13332
+ value: void 0
13333
+ };
13334
+ }
13335
+ };
13336
+ } };
13337
+ }
13338
+ _handleForEachRecord({ originalForEach, inputValue, creationContext, userCallback }) {
13339
+ const self = this;
13340
+ return import_src$25.context.with(creationContext, () => {
13341
+ return handleRecordMode({
13342
+ originalFunctionCall: () => originalForEach(userCallback),
13343
+ recordModeHandler: ({ isPreAppStart }) => {
13344
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalForEach(userCallback), {
13345
+ name: "postgres.query",
13346
+ kind: import_src$25.SpanKind.CLIENT,
13347
+ submodule: "query",
13348
+ packageType: PackageType.PG,
13349
+ packageName: "postgres",
13350
+ instrumentationName: self.INSTRUMENTATION_NAME,
13351
+ inputValue,
13352
+ isPreAppStart
13353
+ }, async (spanInfo) => {
13354
+ const allRows = [];
13355
+ const wrappedCallback = (row, result) => {
13356
+ allRows.push(row);
13357
+ return userCallback(row, result);
13358
+ };
13359
+ try {
13360
+ const result = await originalForEach(wrappedCallback);
13361
+ try {
13362
+ self._endCursorSpan(spanInfo, allRows, result, "forEach");
13363
+ } catch (error) {
13364
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13365
+ }
13366
+ return result;
13367
+ } catch (error) {
13368
+ try {
13369
+ SpanUtils.endSpan(spanInfo.span, {
13370
+ code: import_src$25.SpanStatusCode.ERROR,
13371
+ message: error.message
13372
+ });
13373
+ } catch (error$1) {
13374
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13375
+ }
13376
+ throw error;
13377
+ }
13378
+ });
13379
+ },
13380
+ spanKind: import_src$25.SpanKind.CLIENT
13381
+ });
13382
+ });
13383
+ }
13384
+ _handleForEachReplay({ inputValue, creationContext, userCallback }) {
13385
+ const self = this;
13386
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13387
+ return import_src$25.context.with(creationContext, () => {
13388
+ return handleReplayMode({
13389
+ noOpRequestHandler: () => Promise.resolve(Object.assign([], {
13390
+ count: 0,
13391
+ command: null
13392
+ })),
13393
+ isServerRequest: false,
13394
+ replayModeHandler: () => {
13395
+ return SpanUtils.createAndExecuteSpan(self.mode, () => Promise.resolve(Object.assign([], {
13396
+ count: 0,
13397
+ command: null
13398
+ })), {
13399
+ name: "postgres.query",
13400
+ kind: import_src$25.SpanKind.CLIENT,
13401
+ submodule: "query",
13402
+ packageType: PackageType.PG,
13403
+ packageName: "postgres",
13404
+ instrumentationName: self.INSTRUMENTATION_NAME,
13405
+ inputValue,
13406
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13407
+ }, async (spanInfo) => {
13408
+ try {
13409
+ const mockedResult = await self._handleReplayQueryOperation({
13410
+ inputValue,
13411
+ spanInfo,
13412
+ submodule: "query",
13413
+ name: "postgres.query",
13414
+ stackTrace,
13415
+ operationType: "forEach"
13416
+ });
13417
+ const mockedRows = Array.isArray(mockedResult) ? mockedResult : [];
13418
+ logger.debug(`[PostgresInstrumentation] forEach replay: calling callback with ${mockedRows.length} mocked rows`);
13419
+ for (const row of mockedRows) userCallback(row, mockedResult);
13420
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13421
+ return Object.assign([], {
13422
+ count: mockedRows.length,
13423
+ command: null
13424
+ });
13425
+ } catch (error) {
13426
+ logger.debug(`[PostgresInstrumentation] forEach replay error: ${error.message}`);
13427
+ SpanUtils.endSpan(spanInfo.span, {
13428
+ code: import_src$25.SpanStatusCode.ERROR,
13429
+ message: error.message
13430
+ });
13431
+ throw error;
13432
+ }
13433
+ });
13434
+ }
13435
+ });
13436
+ });
13437
+ }
13438
+ /**
13439
+ * Wraps a query's .then() method to add instrumentation.
13440
+ * This is reusable for both sql template literals and unsafe() queries.
13441
+ */
13442
+ _wrapThenMethod(query, originalThen, inputValue, creationContext, spanConfig) {
13443
+ const self = this;
13444
+ query.then = function(onFulfilled, onRejected) {
13445
+ if (query._forEachCalled) return originalThen(onFulfilled, onRejected);
13446
+ if (query._tuskRecorded) return originalThen(onFulfilled, onRejected);
13447
+ query._tuskRecorded = true;
13448
+ return import_src$25.context.with(creationContext, () => {
13449
+ if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
13450
+ originalFunctionCall: () => originalThen(onFulfilled, onRejected),
13451
+ recordModeHandler: ({ isPreAppStart }) => {
13452
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
13453
+ name: spanConfig.name,
13454
+ kind: import_src$25.SpanKind.CLIENT,
13455
+ submodule: spanConfig.submodule,
13456
+ packageType: PackageType.PG,
13457
+ packageName: "postgres",
13458
+ instrumentationName: self.INSTRUMENTATION_NAME,
13459
+ inputValue,
13460
+ isPreAppStart
13461
+ }, (spanInfo) => {
13462
+ const wrappedOnFulfilled = (result) => {
13463
+ try {
13464
+ logger.debug(`[PostgresInstrumentation] Postgres ${spanConfig.operationType} query completed successfully (${SpanUtils.getTraceInfo()})`);
13465
+ addOutputAttributesToSpan(spanInfo, result);
13466
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13467
+ } catch (error) {
13468
+ logger.error(`[PostgresInstrumentation] error processing ${spanConfig.operationType} query response:`, error);
13469
+ }
13470
+ return onFulfilled ? onFulfilled(result) : result;
13471
+ };
13472
+ const wrappedOnRejected = (error) => {
13473
+ try {
13474
+ logger.debug(`[PostgresInstrumentation] Postgres ${spanConfig.operationType} query error: ${error.message}`);
13475
+ SpanUtils.endSpan(spanInfo.span, {
13476
+ code: import_src$25.SpanStatusCode.ERROR,
13477
+ message: error.message
13478
+ });
13479
+ } catch (spanError) {
13480
+ logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
13481
+ }
13482
+ if (onRejected) return onRejected(error);
13483
+ throw error;
13484
+ };
13485
+ return originalThen(wrappedOnFulfilled, wrappedOnRejected);
13486
+ });
13487
+ },
13488
+ spanKind: import_src$25.SpanKind.CLIENT
13489
+ });
13490
+ else if (self.mode === TuskDriftMode.REPLAY) {
13491
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13492
+ return handleReplayMode({
13493
+ noOpRequestHandler: () => Promise.resolve(Object.assign([], {
13494
+ count: 0,
13495
+ command: null
13496
+ })),
13497
+ isServerRequest: false,
13498
+ replayModeHandler: () => {
13499
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
13500
+ name: spanConfig.name,
13501
+ kind: import_src$25.SpanKind.CLIENT,
13502
+ submodule: spanConfig.submodule,
13503
+ packageType: PackageType.PG,
13504
+ packageName: "postgres",
13505
+ instrumentationName: self.INSTRUMENTATION_NAME,
13506
+ inputValue,
13507
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13508
+ }, async (spanInfo) => {
13509
+ const mockedResult = await self._handleReplayQueryOperation({
13510
+ inputValue,
13511
+ spanInfo,
13512
+ submodule: spanConfig.submodule,
13513
+ name: spanConfig.name,
13514
+ stackTrace,
13515
+ operationType: spanConfig.operationType
13516
+ });
13517
+ return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
13518
+ });
13519
+ }
12664
13520
  });
12665
- } catch (spanError) {
12666
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12667
- }
13521
+ } else return originalThen(onFulfilled, onRejected);
12668
13522
  });
12669
- });
12670
- return promise;
12671
- }
12672
- async _handleReplayBeginTransaction(spanInfo, options, stackTrace) {
12673
- logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
12674
- const mockData = await findMockResponseAsync({
12675
- mockRequestData: {
12676
- traceId: spanInfo.traceId,
12677
- spanId: spanInfo.spanId,
12678
- name: "postgres.begin",
12679
- inputValue: createMockInputValue({
12680
- query: "BEGIN",
12681
- options: options ? { transactionOptions: options } : void 0
12682
- }),
12683
- packageName: "postgres",
12684
- instrumentationName: this.INSTRUMENTATION_NAME,
12685
- submoduleName: "transaction",
12686
- kind: import_src$25.SpanKind.CLIENT,
12687
- stackTrace
12688
- },
12689
- tuskDrift: this.tuskDrift
12690
- });
12691
- if (!mockData) {
12692
- logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
12693
- throw new Error(`[PostgresInstrumentation] No matching mock found for transaction BEGIN`);
12694
- }
12695
- logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
12696
- const transactionResult = mockData.result;
12697
- if (transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed") return transactionResult.result;
12698
- else {
12699
- const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
12700
- throw new Error(errorMessage);
12701
- }
12702
- }
12703
- async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12704
- logger.debug(`[PostgresInstrumentation] Replaying Postgres sql query`);
12705
- const mockData = await findMockResponseAsync({
12706
- mockRequestData: {
12707
- traceId: spanInfo.traceId,
12708
- spanId: spanInfo.spanId,
12709
- name,
12710
- inputValue: createMockInputValue(inputValue),
12711
- packageName: "postgres",
12712
- instrumentationName: this.INSTRUMENTATION_NAME,
12713
- submoduleName: submodule,
12714
- kind: import_src$25.SpanKind.CLIENT,
12715
- stackTrace
12716
- },
12717
- tuskDrift: this.tuskDrift
12718
- });
12719
- if (!mockData) {
12720
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12721
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres sql query: ${queryText}`);
12722
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres sql query: ${queryText}`);
12723
- }
12724
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres sql query: ${JSON.stringify(mockData)}`);
12725
- const processedResult = this.convertPostgresTypes(mockData.result);
12726
- logger.debug(`[PostgresInstrumentation] Sql query processed result: ${JSON.stringify(processedResult)}`);
12727
- return processedResult;
13523
+ };
12728
13524
  }
12729
- async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12730
- logger.debug(`[PostgresInstrumentation] Replaying Postgres unsafe query`);
12731
- const mockData = await findMockResponseAsync({
12732
- mockRequestData: {
12733
- traceId: spanInfo.traceId,
12734
- spanId: spanInfo.spanId,
12735
- name,
12736
- inputValue: createMockInputValue(inputValue),
12737
- packageName: "postgres",
12738
- instrumentationName: this.INSTRUMENTATION_NAME,
12739
- submoduleName: submodule,
12740
- kind: import_src$25.SpanKind.CLIENT,
12741
- stackTrace
12742
- },
12743
- tuskDrift: this.tuskDrift
12744
- });
12745
- if (!mockData) {
12746
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12747
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres unsafe query: ${queryText}`);
12748
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres unsafe query: ${queryText}`);
12749
- }
12750
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres unsafe query: ${JSON.stringify(mockData)}`);
12751
- const processedResult = this.convertPostgresTypes(mockData.result);
12752
- logger.debug(`[PostgresInstrumentation] Unsafe query processed result: ${JSON.stringify(processedResult)}`);
12753
- return processedResult;
13525
+ /**
13526
+ * Wraps a query's .execute() method to prevent TCP calls in REPLAY mode.
13527
+ * This is reusable for both sql template literals and unsafe() queries.
13528
+ */
13529
+ _wrapExecuteMethod(query) {
13530
+ const self = this;
13531
+ const originalExecute = query.execute ? query.execute.bind(query) : void 0;
13532
+ if (originalExecute) query.execute = function() {
13533
+ if (self.mode === TuskDriftMode.REPLAY) return this;
13534
+ else return originalExecute.call(this);
13535
+ };
12754
13536
  }
12755
- convertPostgresTypes(result) {
12756
- if (!isPostgresOutputValueType(result)) {
12757
- logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12758
- return;
12759
- }
12760
- const { rows, count, command } = result;
12761
- const resultArray = Array.from(rows || []);
12762
- Object.defineProperties(resultArray, {
12763
- count: {
12764
- value: count !== void 0 ? count : null,
12765
- writable: true,
12766
- enumerable: false
12767
- },
12768
- command: {
12769
- value: command || null,
12770
- writable: true,
12771
- enumerable: false
12772
- }
12773
- });
12774
- return resultArray;
13537
+ /**
13538
+ * Wraps a query's cursor() method to add instrumentation.
13539
+ * This is reusable for both sql template literals and unsafe() queries.
13540
+ */
13541
+ _wrapCursorMethod(query, inputValue, creationContext) {
13542
+ if (typeof query.cursor !== "function") return;
13543
+ const self = this;
13544
+ const originalCursor = query.cursor.bind(query);
13545
+ query.cursor = function(rows, fn) {
13546
+ if (typeof rows === "function") {
13547
+ fn = rows;
13548
+ rows = 1;
13549
+ }
13550
+ if (!rows) rows = 1;
13551
+ if (typeof fn === "function") if (self.mode === TuskDriftMode.RECORD) return self._handleCursorCallbackRecord({
13552
+ originalCursor,
13553
+ rows,
13554
+ inputValue,
13555
+ creationContext,
13556
+ userCallback: fn
13557
+ });
13558
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleCursorCallbackReplay({
13559
+ inputValue,
13560
+ creationContext,
13561
+ cursorBatchSize: rows,
13562
+ userCallback: fn
13563
+ });
13564
+ else return originalCursor(rows, fn);
13565
+ if (self.mode === TuskDriftMode.RECORD) return self._handleCursorRecord({
13566
+ originalCursor,
13567
+ rows,
13568
+ inputValue,
13569
+ creationContext,
13570
+ queryObject: this
13571
+ });
13572
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleCursorReplay({
13573
+ inputValue,
13574
+ creationContext,
13575
+ cursorBatchSize: rows
13576
+ });
13577
+ else return originalCursor(rows);
13578
+ };
12775
13579
  }
12776
- _addOutputAttributesToSpan(spanInfo, result) {
12777
- if (!result) return;
12778
- const isArray$1 = Array.isArray(result);
12779
- logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12780
- const outputValue = {
12781
- rows: isArray$1 ? Array.from(result) : result.rows || [],
12782
- count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12783
- command: result.command || void 0
13580
+ /**
13581
+ * Wraps a query's forEach() method to add instrumentation.
13582
+ * This is reusable for both sql template literals and unsafe() queries.
13583
+ */
13584
+ _wrapForEachMethod(query, inputValue, creationContext) {
13585
+ if (typeof query.forEach !== "function") return;
13586
+ const self = this;
13587
+ const originalForEach = query.forEach.bind(query);
13588
+ query.forEach = function(fn) {
13589
+ query._forEachCalled = true;
13590
+ if (self.mode === TuskDriftMode.RECORD) return self._handleForEachRecord({
13591
+ originalForEach,
13592
+ inputValue,
13593
+ creationContext,
13594
+ userCallback: fn
13595
+ });
13596
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleForEachReplay({
13597
+ inputValue,
13598
+ creationContext,
13599
+ userCallback: fn
13600
+ });
13601
+ else return originalForEach(fn);
12784
13602
  };
12785
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12786
13603
  }
12787
13604
  _wrap(target, propertyName, wrapper) {
12788
13605
  wrap(target, propertyName, wrapper);
@@ -12805,8 +13622,9 @@ function isMysqlOkPacket(result) {
12805
13622
  * Extends EventEmitter to properly handle all connection methods and events
12806
13623
  */
12807
13624
  var TdMysqlConnectionMock = class extends events.EventEmitter {
12808
- constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo) {
13625
+ constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo, pool) {
12809
13626
  super();
13627
+ this._pool = null;
12810
13628
  this.threadId = null;
12811
13629
  this.config = {
12812
13630
  host: "localhost",
@@ -12818,6 +13636,7 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12818
13636
  this.spanInfo = spanInfo;
12819
13637
  this.clientType = clientType;
12820
13638
  this.threadId = 1;
13639
+ this._pool = pool;
12821
13640
  }
12822
13641
  query(...args) {
12823
13642
  logger.debug(`[TdMysqlConnectionMock] Mock connection query intercepted in REPLAY mode`);
@@ -12825,7 +13644,13 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12825
13644
  let values;
12826
13645
  let callback;
12827
13646
  let options = {};
12828
- if (typeof args[0] === "string") {
13647
+ const firstArg = args[0];
13648
+ if (firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function") {
13649
+ sql = firstArg.sql;
13650
+ values = firstArg.values;
13651
+ callback = firstArg._callback;
13652
+ options = { nestTables: firstArg.nestTables };
13653
+ } else if (typeof args[0] === "string") {
12829
13654
  sql = args[0];
12830
13655
  if (typeof args[1] === "function") callback = args[1];
12831
13656
  else if (Array.isArray(args[1])) {
@@ -12877,6 +13702,7 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12877
13702
  }
12878
13703
  }
12879
13704
  release() {
13705
+ if (this._pool) this._pool.emit("release", this);
12880
13706
  this.emit("end");
12881
13707
  }
12882
13708
  destroy() {
@@ -12901,19 +13727,22 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12901
13727
  return;
12902
13728
  }
12903
13729
  }
12904
- beginTransaction(callback) {
13730
+ beginTransaction(optionsOrCallback, callbackArg) {
13731
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
12905
13732
  if (callback) {
12906
13733
  process.nextTick(() => callback(null));
12907
13734
  return;
12908
13735
  }
12909
13736
  }
12910
- commit(callback) {
13737
+ commit(optionsOrCallback, callbackArg) {
13738
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
12911
13739
  if (callback) {
12912
13740
  process.nextTick(() => callback(null));
12913
13741
  return;
12914
13742
  }
12915
13743
  }
12916
- rollback(callback) {
13744
+ rollback(optionsOrCallback, callbackArg) {
13745
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
12917
13746
  if (callback) {
12918
13747
  process.nextTick(() => callback(null));
12919
13748
  return;
@@ -13109,6 +13938,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13109
13938
  name: "mysql/lib/Pool.js",
13110
13939
  supportedVersions: ["2.*"],
13111
13940
  patch: (moduleExports) => this._patchPoolFile(moduleExports)
13941
+ }),
13942
+ new TdInstrumentationNodeModuleFile({
13943
+ name: "mysql/lib/PoolNamespace.js",
13944
+ supportedVersions: ["2.*"],
13945
+ patch: (moduleExports) => this._patchPoolNamespaceFile(moduleExports)
13112
13946
  })
13113
13947
  ]
13114
13948
  })];
@@ -13248,12 +14082,40 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13248
14082
  return PoolClass;
13249
14083
  }
13250
14084
  /**
14085
+ * Patch PoolNamespace.prototype methods at the file level
14086
+ * This handles queries made via poolCluster.of("pattern").query()
14087
+ */
14088
+ _patchPoolNamespaceFile(PoolNamespaceClass) {
14089
+ logger.debug(`[MysqlInstrumentation] Patching PoolNamespace class (file-based)`);
14090
+ if (this.isModulePatched(PoolNamespaceClass)) {
14091
+ logger.debug(`[MysqlInstrumentation] PoolNamespace class already patched, skipping`);
14092
+ return PoolNamespaceClass;
14093
+ }
14094
+ if (PoolNamespaceClass.prototype && PoolNamespaceClass.prototype.query) {
14095
+ if (!isWrapped$1(PoolNamespaceClass.prototype.query)) {
14096
+ this._wrap(PoolNamespaceClass.prototype, "query", this._getPoolNamespaceQueryPatchFn());
14097
+ logger.debug(`[MysqlInstrumentation] Wrapped PoolNamespace.prototype.query`);
14098
+ }
14099
+ }
14100
+ if (PoolNamespaceClass.prototype && PoolNamespaceClass.prototype.getConnection) {
14101
+ if (!isWrapped$1(PoolNamespaceClass.prototype.getConnection)) {
14102
+ this._wrap(PoolNamespaceClass.prototype, "getConnection", this._getPoolNamespaceGetConnectionPatchFn());
14103
+ logger.debug(`[MysqlInstrumentation] Wrapped PoolNamespace.prototype.getConnection`);
14104
+ }
14105
+ }
14106
+ this.markModuleAsPatched(PoolNamespaceClass);
14107
+ logger.debug(`[MysqlInstrumentation] PoolNamespace class patching complete`);
14108
+ return PoolNamespaceClass;
14109
+ }
14110
+ /**
13251
14111
  * Get wrapper function for query method (prototype-level patching)
13252
14112
  */
13253
14113
  _getQueryPatchFn() {
13254
14114
  const self = this;
13255
14115
  return (originalQuery) => {
13256
14116
  return function query(...args) {
14117
+ const firstArg = args[0];
14118
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13257
14119
  let sql;
13258
14120
  let values;
13259
14121
  let callback;
@@ -13264,6 +14126,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13264
14126
  values = queryObj.values;
13265
14127
  options = { nestTables: queryObj.nestTables };
13266
14128
  callback = args.find((arg) => typeof arg === "function");
14129
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13267
14130
  } catch (error) {
13268
14131
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13269
14132
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13274,7 +14137,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13274
14137
  values,
13275
14138
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13276
14139
  };
13277
- const isEventEmitterMode = !callback;
14140
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13278
14141
  if (self.mode === TuskDriftMode.REPLAY) {
13279
14142
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13280
14143
  return handleReplayMode({
@@ -13370,11 +14233,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13370
14233
  _getBeginTransactionPatchFn() {
13371
14234
  const self = this;
13372
14235
  return (originalBeginTransaction) => {
13373
- return function beginTransaction(callback) {
14236
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14237
+ let actualCallback;
14238
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14239
+ else actualCallback = callbackArg;
13374
14240
  const inputValue = { query: "BEGIN" };
13375
14241
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13376
14242
  noOpRequestHandler: () => {
13377
- if (callback) setImmediate(() => callback(null));
14243
+ if (actualCallback) setImmediate(() => actualCallback(null));
13378
14244
  },
13379
14245
  isServerRequest: false,
13380
14246
  replayModeHandler: () => {
@@ -13388,7 +14254,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13388
14254
  inputValue,
13389
14255
  isPreAppStart: false
13390
14256
  }, (spanInfo) => {
13391
- return self._handleReplayTransaction(inputValue, callback);
14257
+ return self._handleReplayTransaction(inputValue, actualCallback);
13392
14258
  });
13393
14259
  }
13394
14260
  });
@@ -13405,7 +14271,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13405
14271
  inputValue,
13406
14272
  isPreAppStart
13407
14273
  }, (spanInfo) => {
13408
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, callback);
14274
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, actualCallback);
13409
14275
  });
13410
14276
  },
13411
14277
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13420,11 +14286,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13420
14286
  _getCommitPatchFn() {
13421
14287
  const self = this;
13422
14288
  return (originalCommit) => {
13423
- return function commit(callback) {
14289
+ return function commit(optionsOrCallback, callbackArg) {
14290
+ let actualCallback;
14291
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14292
+ else actualCallback = callbackArg;
13424
14293
  const inputValue = { query: "COMMIT" };
13425
14294
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13426
14295
  noOpRequestHandler: () => {
13427
- if (callback) setImmediate(() => callback(null));
14296
+ if (actualCallback) setImmediate(() => actualCallback(null));
13428
14297
  },
13429
14298
  isServerRequest: false,
13430
14299
  replayModeHandler: () => {
@@ -13438,7 +14307,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13438
14307
  inputValue,
13439
14308
  isPreAppStart: false
13440
14309
  }, (spanInfo) => {
13441
- return self._handleReplayTransaction(inputValue, callback);
14310
+ return self._handleReplayTransaction(inputValue, actualCallback);
13442
14311
  });
13443
14312
  }
13444
14313
  });
@@ -13455,7 +14324,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13455
14324
  inputValue,
13456
14325
  isPreAppStart
13457
14326
  }, (spanInfo) => {
13458
- return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, callback);
14327
+ return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, actualCallback);
13459
14328
  });
13460
14329
  },
13461
14330
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13470,11 +14339,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13470
14339
  _getRollbackPatchFn() {
13471
14340
  const self = this;
13472
14341
  return (originalRollback) => {
13473
- return function rollback(callback) {
14342
+ return function rollback(optionsOrCallback, callbackArg) {
14343
+ let actualCallback;
14344
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14345
+ else actualCallback = callbackArg;
13474
14346
  const inputValue = { query: "ROLLBACK" };
13475
14347
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13476
14348
  noOpRequestHandler: () => {
13477
- if (callback) setImmediate(() => callback(null));
14349
+ if (actualCallback) setImmediate(() => actualCallback(null));
13478
14350
  },
13479
14351
  isServerRequest: false,
13480
14352
  replayModeHandler: () => {
@@ -13488,7 +14360,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13488
14360
  inputValue,
13489
14361
  isPreAppStart: false
13490
14362
  }, (spanInfo) => {
13491
- return self._handleReplayTransaction(inputValue, callback);
14363
+ return self._handleReplayTransaction(inputValue, actualCallback);
13492
14364
  });
13493
14365
  }
13494
14366
  });
@@ -13505,7 +14377,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13505
14377
  inputValue,
13506
14378
  isPreAppStart
13507
14379
  }, (spanInfo) => {
13508
- return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, callback);
14380
+ return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, actualCallback);
13509
14381
  });
13510
14382
  },
13511
14383
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13673,9 +14545,10 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13673
14545
  return (originalGetConnection) => {
13674
14546
  return function getConnection(callback) {
13675
14547
  const inputValue = { clientType: "pool" };
14548
+ const pool = this;
13676
14549
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13677
14550
  noOpRequestHandler: () => {
13678
- return self._handleNoOpReplayGetConnection(callback);
14551
+ return self._handleNoOpReplayGetConnection(pool, callback);
13679
14552
  },
13680
14553
  isServerRequest: false,
13681
14554
  replayModeHandler: () => {
@@ -13689,7 +14562,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13689
14562
  inputValue,
13690
14563
  isPreAppStart: false
13691
14564
  }, (spanInfo) => {
13692
- return self._handleReplayPoolGetConnection(spanInfo, callback);
14565
+ return self._handleReplayPoolGetConnection(pool, spanInfo, callback);
13693
14566
  });
13694
14567
  }
13695
14568
  });
@@ -13719,6 +14592,8 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13719
14592
  const self = this;
13720
14593
  return (originalQuery) => {
13721
14594
  return function query(...args) {
14595
+ const firstArg = args[0];
14596
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13722
14597
  let sql;
13723
14598
  let values;
13724
14599
  let callback;
@@ -13729,6 +14604,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13729
14604
  values = queryObj.values;
13730
14605
  options = { nestTables: queryObj.nestTables };
13731
14606
  callback = args.find((arg) => typeof arg === "function");
14607
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13732
14608
  } catch (error) {
13733
14609
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13734
14610
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13739,7 +14615,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13739
14615
  values,
13740
14616
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13741
14617
  };
13742
- const isEventEmitterMode = !callback;
14618
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13743
14619
  if (self.mode === TuskDriftMode.REPLAY) {
13744
14620
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13745
14621
  return handleReplayMode({
@@ -13841,6 +14717,33 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13841
14717
  });
13842
14718
  return queryEmitter;
13843
14719
  } else {
14720
+ const queryObject = args[0];
14721
+ if (queryObject && typeof queryObject === "object" && typeof queryObject._callback === "function") {
14722
+ const originalCallback$1 = queryObject._callback;
14723
+ queryObject._callback = function(err, results, fields) {
14724
+ if (err) try {
14725
+ SpanUtils.endSpan(spanInfo.span, {
14726
+ code: import_src$23.SpanStatusCode.ERROR,
14727
+ message: err.message
14728
+ });
14729
+ } catch (error) {
14730
+ logger.error(`[MysqlInstrumentation] error ending span:`, error);
14731
+ }
14732
+ else try {
14733
+ const outputValue = {
14734
+ results,
14735
+ fields
14736
+ };
14737
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
14738
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14739
+ } catch (error) {
14740
+ logger.error(`[MysqlInstrumentation] error ending span:`, error);
14741
+ }
14742
+ logger.debug(`[MysqlInstrumentation] Query completed`);
14743
+ originalCallback$1.call(this, err, results, fields);
14744
+ };
14745
+ return originalQuery.apply(connection, args);
14746
+ }
13844
14747
  const originalCallback = callback;
13845
14748
  const callbackIndex = args.findIndex((arg) => typeof arg === "function");
13846
14749
  args[callbackIndex] = function(err, results, fields) {
@@ -13895,11 +14798,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13895
14798
  _patchBeginTransaction(connection) {
13896
14799
  const self = this;
13897
14800
  return (originalBeginTransaction) => {
13898
- return function beginTransaction(callback) {
14801
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14802
+ let actualCallback;
14803
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14804
+ else actualCallback = callbackArg;
13899
14805
  const inputValue = { query: "BEGIN" };
13900
14806
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13901
14807
  noOpRequestHandler: () => {
13902
- if (callback) setImmediate(() => callback(null));
14808
+ if (actualCallback) setImmediate(() => actualCallback(null));
13903
14809
  },
13904
14810
  isServerRequest: false,
13905
14811
  replayModeHandler: () => {
@@ -13913,7 +14819,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13913
14819
  inputValue,
13914
14820
  isPreAppStart: false
13915
14821
  }, (spanInfo) => {
13916
- return self._handleReplayTransaction(inputValue, callback);
14822
+ return self._handleReplayTransaction(inputValue, actualCallback);
13917
14823
  });
13918
14824
  }
13919
14825
  });
@@ -13930,7 +14836,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13930
14836
  inputValue,
13931
14837
  isPreAppStart
13932
14838
  }, (spanInfo) => {
13933
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, callback);
14839
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, actualCallback);
13934
14840
  });
13935
14841
  },
13936
14842
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13942,11 +14848,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13942
14848
  _patchCommit(connection) {
13943
14849
  const self = this;
13944
14850
  return (originalCommit) => {
13945
- return function commit(callback) {
14851
+ return function commit(optionsOrCallback, callbackArg) {
14852
+ let actualCallback;
14853
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14854
+ else actualCallback = callbackArg;
13946
14855
  const inputValue = { query: "COMMIT" };
13947
14856
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13948
14857
  noOpRequestHandler: () => {
13949
- if (callback) setImmediate(() => callback(null));
14858
+ if (actualCallback) setImmediate(() => actualCallback(null));
13950
14859
  },
13951
14860
  isServerRequest: false,
13952
14861
  replayModeHandler: () => {
@@ -13960,7 +14869,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13960
14869
  inputValue,
13961
14870
  isPreAppStart: false
13962
14871
  }, (spanInfo) => {
13963
- return self._handleReplayTransaction(inputValue, callback);
14872
+ return self._handleReplayTransaction(inputValue, actualCallback);
13964
14873
  });
13965
14874
  }
13966
14875
  });
@@ -13977,7 +14886,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13977
14886
  inputValue,
13978
14887
  isPreAppStart
13979
14888
  }, (spanInfo) => {
13980
- return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, callback);
14889
+ return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, actualCallback);
13981
14890
  });
13982
14891
  },
13983
14892
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13989,11 +14898,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13989
14898
  _patchRollback(connection) {
13990
14899
  const self = this;
13991
14900
  return (originalRollback) => {
13992
- return function rollback(callback) {
14901
+ return function rollback(optionsOrCallback, callbackArg) {
14902
+ let actualCallback;
14903
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14904
+ else actualCallback = callbackArg;
13993
14905
  const inputValue = { query: "ROLLBACK" };
13994
14906
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13995
14907
  noOpRequestHandler: () => {
13996
- if (callback) setImmediate(() => callback(null));
14908
+ if (actualCallback) setImmediate(() => actualCallback(null));
13997
14909
  },
13998
14910
  isServerRequest: false,
13999
14911
  replayModeHandler: () => {
@@ -14007,7 +14919,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14007
14919
  inputValue,
14008
14920
  isPreAppStart: false
14009
14921
  }, (spanInfo) => {
14010
- return self._handleReplayTransaction(inputValue, callback);
14922
+ return self._handleReplayTransaction(inputValue, actualCallback);
14011
14923
  });
14012
14924
  }
14013
14925
  });
@@ -14024,7 +14936,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14024
14936
  inputValue,
14025
14937
  isPreAppStart
14026
14938
  }, (spanInfo) => {
14027
- return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, callback);
14939
+ return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, actualCallback);
14028
14940
  });
14029
14941
  },
14030
14942
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14057,7 +14969,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14057
14969
  const argsArray = Array.from(args);
14058
14970
  const callbackIndex = argsArray.findIndex((arg) => typeof arg === "function");
14059
14971
  if (callbackIndex !== -1) {
14060
- const originalCallback = callback;
14972
+ const originalCallback = argsArray[callbackIndex];
14061
14973
  argsArray[callbackIndex] = function(err) {
14062
14974
  if (err) try {
14063
14975
  SpanUtils.endSpan(spanInfo.span, {
@@ -14086,7 +14998,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14086
14998
  callback(null);
14087
14999
  });
14088
15000
  }
14089
- _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$6) {
15001
+ _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, poolContext) {
14090
15002
  const self = this;
14091
15003
  if (callback) {
14092
15004
  const wrappedCallback = (error, connection) => {
@@ -14111,11 +15023,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14111
15023
  } });
14112
15024
  SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14113
15025
  }
14114
- return callback(error, connection);
15026
+ return import_src$23.context.bind(spanInfo.context, callback)(error, connection);
14115
15027
  };
14116
- return originalGetConnection.call(context$6, wrappedCallback);
15028
+ return originalGetConnection.call(poolContext, wrappedCallback);
14117
15029
  } else try {
14118
- const result = originalGetConnection.call(context$6);
15030
+ const result = originalGetConnection.call(poolContext);
14119
15031
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
14120
15032
  connected: true,
14121
15033
  hasConnection: true
@@ -14130,20 +15042,28 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14130
15042
  throw error;
14131
15043
  }
14132
15044
  }
14133
- _handleNoOpReplayGetConnection(callback) {
15045
+ _handleNoOpReplayGetConnection(pool, callback) {
14134
15046
  logger.debug(`[MysqlInstrumentation] Background getConnection detected, returning mock connection`);
14135
- const mockConnection = new TdMysqlConnectionMock(this, "pool");
15047
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", void 0, pool);
14136
15048
  if (callback) {
14137
- process.nextTick(() => callback(null, mockConnection));
15049
+ process.nextTick(() => {
15050
+ pool.emit("connection", mockConnection);
15051
+ pool.emit("acquire", mockConnection);
15052
+ callback(null, mockConnection);
15053
+ });
14138
15054
  return;
14139
15055
  }
14140
15056
  return mockConnection;
14141
15057
  }
14142
- _handleReplayPoolGetConnection(spanInfo, callback) {
15058
+ _handleReplayPoolGetConnection(pool, spanInfo, callback) {
14143
15059
  logger.debug(`[MysqlInstrumentation] Replaying MySQL Pool getConnection`);
14144
- const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo);
15060
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo, pool);
14145
15061
  if (callback) {
14146
- process.nextTick(() => callback(null, mockConnection));
15062
+ process.nextTick(() => {
15063
+ pool.emit("connection", mockConnection);
15064
+ pool.emit("acquire", mockConnection);
15065
+ callback(null, mockConnection);
15066
+ });
14147
15067
  return;
14148
15068
  }
14149
15069
  return mockConnection;
@@ -14376,6 +15296,122 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14376
15296
  });
14377
15297
  return readableStream;
14378
15298
  }
15299
+ /**
15300
+ * Get wrapper function for PoolNamespace.query method
15301
+ * This handles queries made via poolCluster.of("pattern").query()
15302
+ */
15303
+ _getPoolNamespaceQueryPatchFn() {
15304
+ const self = this;
15305
+ return (originalQuery) => {
15306
+ return function query(...args) {
15307
+ const firstArg = args[0];
15308
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
15309
+ if (self.mode === TuskDriftMode.REPLAY) {
15310
+ let sql;
15311
+ let values;
15312
+ let callback;
15313
+ let options = {};
15314
+ if (self.createQuery) try {
15315
+ const queryObj = self.createQuery(...args);
15316
+ sql = queryObj.sql;
15317
+ values = queryObj.values;
15318
+ options = { nestTables: queryObj.nestTables };
15319
+ callback = args.find((arg) => typeof arg === "function");
15320
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
15321
+ } catch (error) {
15322
+ ({sql, values, callback, options} = self._parseQueryArgs(args));
15323
+ }
15324
+ else ({sql, values, callback, options} = self._parseQueryArgs(args));
15325
+ const inputValue = {
15326
+ sql,
15327
+ values,
15328
+ options: options.nestTables ? { nestTables: options.nestTables } : void 0
15329
+ };
15330
+ const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
15331
+ return handleReplayMode({
15332
+ noOpRequestHandler: () => {
15333
+ return self.queryMock.handleNoOpReplayQuery({
15334
+ sql,
15335
+ values,
15336
+ callback,
15337
+ options
15338
+ });
15339
+ },
15340
+ isServerRequest: false,
15341
+ replayModeHandler: () => {
15342
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
15343
+ name: "mysql.query",
15344
+ kind: import_src$23.SpanKind.CLIENT,
15345
+ submodule: "query",
15346
+ packageType: PackageType.MYSQL,
15347
+ packageName: "mysql",
15348
+ instrumentationName: self.INSTRUMENTATION_NAME,
15349
+ inputValue,
15350
+ isPreAppStart: false
15351
+ }, (spanInfo) => {
15352
+ const queryEmitter = self.queryMock.handleReplayQuery({
15353
+ sql,
15354
+ values,
15355
+ callback,
15356
+ options
15357
+ }, inputValue, spanInfo, stackTrace);
15358
+ if (queryEmitter && typeof queryEmitter === "object") queryEmitter.stream = function(streamOptions) {
15359
+ return self._createReplayStreamForQuery(inputValue, spanInfo, stackTrace, queryEmitter, streamOptions);
15360
+ };
15361
+ return queryEmitter;
15362
+ });
15363
+ }
15364
+ });
15365
+ } else if (self.mode === TuskDriftMode.RECORD) return originalQuery.apply(this, args);
15366
+ else return originalQuery.apply(this, args);
15367
+ };
15368
+ };
15369
+ }
15370
+ /**
15371
+ * Get wrapper function for PoolNamespace.getConnection method
15372
+ * This handles connections obtained via poolCluster.of("pattern").getConnection()
15373
+ */
15374
+ _getPoolNamespaceGetConnectionPatchFn() {
15375
+ const self = this;
15376
+ return (originalGetConnection) => {
15377
+ return function getConnection(callback) {
15378
+ const namespace = this;
15379
+ const inputValue = { clientType: "poolNamespace" };
15380
+ if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
15381
+ noOpRequestHandler: () => {
15382
+ const mockConnection = new TdMysqlConnectionMock(self, "pool", void 0, void 0);
15383
+ if (callback) {
15384
+ process.nextTick(() => callback(null, mockConnection));
15385
+ return;
15386
+ }
15387
+ return mockConnection;
15388
+ },
15389
+ isServerRequest: false,
15390
+ replayModeHandler: () => {
15391
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalGetConnection.apply(namespace, [callback]), {
15392
+ name: `mysql.poolNamespace.getConnection`,
15393
+ kind: import_src$23.SpanKind.CLIENT,
15394
+ submodule: "getConnection",
15395
+ packageName: "mysql",
15396
+ packageType: PackageType.MYSQL,
15397
+ instrumentationName: self.INSTRUMENTATION_NAME,
15398
+ inputValue,
15399
+ isPreAppStart: false
15400
+ }, (spanInfo) => {
15401
+ const mockConnection = new TdMysqlConnectionMock(self, "pool", spanInfo, void 0);
15402
+ if (callback) {
15403
+ process.nextTick(() => callback(null, mockConnection));
15404
+ return;
15405
+ }
15406
+ return mockConnection;
15407
+ });
15408
+ }
15409
+ });
15410
+ else if (self.mode === TuskDriftMode.RECORD) return originalGetConnection.apply(namespace, [callback]);
15411
+ else return originalGetConnection.apply(namespace, [callback]);
15412
+ };
15413
+ };
15414
+ }
14379
15415
  _wrap(target, propertyName, wrapper) {
14380
15416
  wrap(target, propertyName, wrapper);
14381
15417
  }
@@ -31946,7 +32982,7 @@ var require_src = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/sdk-
31946
32982
  //#endregion
31947
32983
  //#region package.json
31948
32984
  var import_src$1 = /* @__PURE__ */ __toESM(require_src(), 1);
31949
- var version = "0.1.18";
32985
+ var version = "0.1.19";
31950
32986
 
31951
32987
  //#endregion
31952
32988
  //#region src/version.ts