@use-tusk/drift-node-sdk 0.1.17 → 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$24) {
4992
+ (function(SpanKind$26) {
4993
4993
  /** Default value. Indicates that the span is used internally. */
4994
- SpanKind$24[SpanKind$24["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$24[SpanKind$24["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$24[SpanKind$24["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$24[SpanKind$24["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$24[SpanKind$24["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$13) {
5025
+ (function(SpanStatusCode$15) {
5026
5026
  /**
5027
5027
  * The default status.
5028
5028
  */
5029
- SpanStatusCode$13[SpanStatusCode$13["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$13[SpanStatusCode$13["OK"] = 1] = "OK";
5034
+ SpanStatusCode$15[SpanStatusCode$15["OK"] = 1] = "OK";
5035
5035
  /**
5036
5036
  * The operation contains an error.
5037
5037
  */
5038
- SpanStatusCode$13[SpanStatusCode$13["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() {
@@ -6209,7 +6209,7 @@ var JsonSchema$Type = class extends import_commonjs$7.MessageType {
6209
6209
  const JsonSchema = new JsonSchema$Type();
6210
6210
 
6211
6211
  //#endregion
6212
- //#region node_modules/@use-tusk/drift-schemas/dist/span-BZ89ct3l.js
6212
+ //#region node_modules/@use-tusk/drift-schemas/dist/span-CsBrzhI_.js
6213
6213
  var import_commonjs$6 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
6214
6214
  /**
6215
6215
  * Package type classification enum
@@ -6295,7 +6295,7 @@ let PackageType = /* @__PURE__ */ function(PackageType$1) {
6295
6295
  *
6296
6296
  * @generated from protobuf enum tusk.drift.core.v1.SpanKind
6297
6297
  */
6298
- let SpanKind = /* @__PURE__ */ function(SpanKind$1$1) {
6298
+ let SpanKind$1 = /* @__PURE__ */ function(SpanKind$1$1) {
6299
6299
  /**
6300
6300
  * @generated from protobuf enum value: SPAN_KIND_UNSPECIFIED = 0;
6301
6301
  */
@@ -6465,7 +6465,7 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6465
6465
  kind: "enum",
6466
6466
  T: () => [
6467
6467
  "tusk.drift.core.v1.SpanKind",
6468
- SpanKind,
6468
+ SpanKind$1,
6469
6469
  "SPAN_KIND_"
6470
6470
  ]
6471
6471
  },
@@ -6504,6 +6504,13 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6504
6504
  name: "metadata",
6505
6505
  kind: "message",
6506
6506
  T: () => Struct
6507
+ },
6508
+ {
6509
+ no: 24,
6510
+ name: "environment",
6511
+ kind: "scalar",
6512
+ opt: true,
6513
+ T: 9
6507
6514
  }
6508
6515
  ]);
6509
6516
  }
@@ -6601,6 +6608,9 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6601
6608
  case 23:
6602
6609
  message.metadata = Struct.internalBinaryRead(reader, reader.uint32(), options, message.metadata);
6603
6610
  break;
6611
+ case 24:
6612
+ message.environment = reader.string();
6613
+ break;
6604
6614
  default:
6605
6615
  let u = options.readUnknownField;
6606
6616
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -6634,6 +6644,7 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6634
6644
  if (message.duration) Duration.internalBinaryWrite(message.duration, writer.tag(21, import_commonjs$6.WireType.LengthDelimited).fork(), options).join();
6635
6645
  if (message.isRootSpan !== false) writer.tag(22, import_commonjs$6.WireType.Varint).bool(message.isRootSpan);
6636
6646
  if (message.metadata) Struct.internalBinaryWrite(message.metadata, writer.tag(23, import_commonjs$6.WireType.LengthDelimited).fork(), options).join();
6647
+ if (message.environment !== void 0) writer.tag(24, import_commonjs$6.WireType.LengthDelimited).string(message.environment);
6637
6648
  let u = options.writeUnknownFields;
6638
6649
  if (u !== false) (u == true ? import_commonjs$6.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
6639
6650
  return writer;
@@ -6997,12 +7008,12 @@ const Trace = new Trace$Type();
6997
7008
  const toStruct = (obj) => obj ? objectToProtobufStruct(obj) : void 0;
6998
7009
  const mapOtToPb = (k) => {
6999
7010
  switch (k) {
7000
- case import_src$34.SpanKind.INTERNAL: return SpanKind.INTERNAL;
7001
- case import_src$34.SpanKind.SERVER: return SpanKind.SERVER;
7002
- case import_src$34.SpanKind.CLIENT: return SpanKind.CLIENT;
7003
- case import_src$34.SpanKind.PRODUCER: return SpanKind.PRODUCER;
7004
- case import_src$34.SpanKind.CONSUMER: return SpanKind.CONSUMER;
7005
- default: return SpanKind.UNSPECIFIED;
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
+ default: return SpanKind$1.UNSPECIFIED;
7006
7017
  }
7007
7018
  };
7008
7019
  /**
@@ -7405,13 +7416,13 @@ var TdInstrumentationNodeModule = class {
7405
7416
 
7406
7417
  //#endregion
7407
7418
  //#region src/core/types.ts
7408
- var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7419
+ var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7409
7420
  const TD_INSTRUMENTATION_LIBRARY_NAME = "tusk-drift-sdk";
7410
- const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.replayTraceId");
7411
- const SPAN_KIND_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.spanKind");
7412
- const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.isPreAppStart");
7413
- const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.stopRecordingChildSpans");
7414
- const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.callingLibrary");
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");
7415
7426
  let TdSpanAttributes = /* @__PURE__ */ function(TdSpanAttributes$1) {
7416
7427
  /**
7417
7428
  * Presentational information:
@@ -7523,7 +7534,7 @@ TraceBlockingManager.instance = null;
7523
7534
 
7524
7535
  //#endregion
7525
7536
  //#region src/core/tracing/SpanUtils.ts
7526
- var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7537
+ var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7527
7538
  var SpanUtils = class SpanUtils {
7528
7539
  /**
7529
7540
  * Creates a new span and returns span info including trace ID and span ID
@@ -7531,8 +7542,8 @@ var SpanUtils = class SpanUtils {
7531
7542
  static createSpan(options) {
7532
7543
  try {
7533
7544
  const tracer = TuskDriftCore.getInstance().getTracer();
7534
- const parentContext = options.parentContext || import_src$32.context.active();
7535
- 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);
7536
7547
  if (activeSpan) {
7537
7548
  const parentTraceId = activeSpan.spanContext().traceId;
7538
7549
  if (TraceBlockingManager.getInstance().isTraceBlocked(parentTraceId)) {
@@ -7541,11 +7552,11 @@ var SpanUtils = class SpanUtils {
7541
7552
  }
7542
7553
  }
7543
7554
  const span = tracer.startSpan(options.name, {
7544
- kind: options.kind || import_src$32.SpanKind.CLIENT,
7555
+ kind: options.kind || import_src$33.SpanKind.CLIENT,
7545
7556
  attributes: options.attributes || {}
7546
7557
  }, parentContext);
7547
7558
  const spanContext = span.spanContext();
7548
- const newContext = import_src$32.trace.setSpan(parentContext, span).setValue(SPAN_KIND_CONTEXT_KEY, options.kind).setValue(IS_PRE_APP_START_CONTEXT_KEY, options.isPreAppStart);
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);
7549
7560
  return {
7550
7561
  traceId: spanContext.traceId,
7551
7562
  spanId: spanContext.spanId,
@@ -7562,7 +7573,7 @@ var SpanUtils = class SpanUtils {
7562
7573
  * Executes a function within a span context
7563
7574
  */
7564
7575
  static withSpan(spanInfo, fn) {
7565
- return import_src$32.context.with(spanInfo.context, fn);
7576
+ return import_src$33.context.with(spanInfo.context, fn);
7566
7577
  }
7567
7578
  /**
7568
7579
  * Execute a function within a properly configured span
@@ -7579,14 +7590,14 @@ var SpanUtils = class SpanUtils {
7579
7590
  * @returns The result of the function execution
7580
7591
  */
7581
7592
  static createAndExecuteSpan(mode, originalFunctionCall, options, fn) {
7582
- const spanContext = import_src$32.trace.getActiveSpan()?.spanContext();
7593
+ const spanContext = import_src$33.trace.getActiveSpan()?.spanContext();
7583
7594
  if (spanContext) {
7584
- 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)) {
7585
7596
  logger.debug(`[SpanUtils] Stopping recording of child spans for span ${spanContext.spanId}, packageName: ${options.packageName}, instrumentationName: ${options.instrumentationName}`);
7586
7597
  return originalFunctionCall();
7587
7598
  }
7588
7599
  }
7589
- const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
7600
+ const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, outputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
7590
7601
  let spanInfo = null;
7591
7602
  try {
7592
7603
  spanInfo = SpanUtils.createSpan({
@@ -7600,6 +7611,7 @@ var SpanUtils = class SpanUtils {
7600
7611
  [TdSpanAttributes.INSTRUMENTATION_NAME]: instrumentationName,
7601
7612
  [TdSpanAttributes.PACKAGE_TYPE]: packageType,
7602
7613
  [TdSpanAttributes.INPUT_VALUE]: createSpanInputValue(inputValue),
7614
+ ...outputValue && { [TdSpanAttributes.OUTPUT_VALUE]: JSON.stringify(outputValue) },
7603
7615
  [TdSpanAttributes.IS_PRE_APP_START]: isPreAppStart,
7604
7616
  ...inputSchemaMerges && { [TdSpanAttributes.INPUT_SCHEMA_MERGES]: JSON.stringify(inputSchemaMerges) },
7605
7617
  ...metadata && { [TdSpanAttributes.METADATA]: JSON.stringify(metadata) }
@@ -7619,15 +7631,15 @@ var SpanUtils = class SpanUtils {
7619
7631
  */
7620
7632
  static getCurrentSpanInfo() {
7621
7633
  try {
7622
- const activeSpan = import_src$32.trace.getActiveSpan();
7634
+ const activeSpan = import_src$33.trace.getActiveSpan();
7623
7635
  if (!activeSpan) return null;
7624
7636
  const spanContext = activeSpan.spanContext();
7625
7637
  return {
7626
7638
  traceId: spanContext.traceId,
7627
7639
  spanId: spanContext.spanId,
7628
7640
  span: activeSpan,
7629
- context: import_src$32.context.active(),
7630
- 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)
7631
7643
  };
7632
7644
  } catch (error) {
7633
7645
  logger.error("SpanUtils error getting current span info:", error);
@@ -7691,7 +7703,7 @@ var SpanUtils = class SpanUtils {
7691
7703
  }
7692
7704
  static setCurrentReplayTraceId(replayTraceId) {
7693
7705
  try {
7694
- 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);
7695
7707
  } catch (error) {
7696
7708
  logger.error("SpanUtils error setting current replay trace id:", error);
7697
7709
  return null;
@@ -7702,7 +7714,7 @@ var SpanUtils = class SpanUtils {
7702
7714
  */
7703
7715
  static getCurrentReplayTraceId() {
7704
7716
  try {
7705
- 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);
7706
7718
  } catch (error) {
7707
7719
  logger.error("SpanUtils error getting current replay trace id:", error);
7708
7720
  return null;
@@ -7966,30 +7978,6 @@ var TdHttpMockSocket = class extends events.EventEmitter {
7966
7978
  }
7967
7979
  };
7968
7980
 
7969
- //#endregion
7970
- //#region src/instrumentation/core/trackers/EnvVarTracker.ts
7971
- var EnvVarTracker = class {
7972
- static setEnvVar({ traceId, key, value }) {
7973
- this.envVars.set(traceId, {
7974
- ...this.envVars.get(traceId) || {},
7975
- [key]: value
7976
- });
7977
- }
7978
- static setEnvVars(traceId, envVars) {
7979
- this.envVars.set(traceId, envVars);
7980
- }
7981
- static getEnvVar(traceId, key) {
7982
- return this.envVars.get(traceId)?.[key];
7983
- }
7984
- static getEnvVars(traceId) {
7985
- return this.envVars.get(traceId);
7986
- }
7987
- static clearEnvVars(traceId) {
7988
- this.envVars.delete(traceId);
7989
- }
7990
- };
7991
- EnvVarTracker.envVars = /* @__PURE__ */ new Map();
7992
-
7993
7981
  //#endregion
7994
7982
  //#region src/instrumentation/core/trackers/DateTracker.ts
7995
7983
  /**
@@ -8290,6 +8278,7 @@ function convertMockRequestDataToCleanSpanData(mockRequestData, tuskDrift, input
8290
8278
  return {
8291
8279
  ...mockRequestData,
8292
8280
  parentSpanId: "",
8281
+ environment: tuskDrift.getEnvironment(),
8293
8282
  inputValueHash,
8294
8283
  inputSchema,
8295
8284
  inputSchemaHash,
@@ -8374,7 +8363,7 @@ function findMockResponseSync({ mockRequestData, tuskDrift, inputValueSchemaMerg
8374
8363
 
8375
8364
  //#endregion
8376
8365
  //#region src/instrumentation/libraries/http/mocks/TdMockClientRequest.ts
8377
- var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8366
+ var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8378
8367
  let ClientRequest;
8379
8368
  /**
8380
8369
  * Mock ClientRequest implementation for Tusk Drift HTTP replay
@@ -8545,7 +8534,7 @@ var TdMockClientRequest = class TdMockClientRequest extends events.EventEmitter
8545
8534
  instrumentationName: this.INSTRUMENTATION_NAME,
8546
8535
  submoduleName: rawInputValue.method,
8547
8536
  inputValue,
8548
- kind: import_src$31.SpanKind.CLIENT,
8537
+ kind: import_src$32.SpanKind.CLIENT,
8549
8538
  stackTrace: this.stackTrace
8550
8539
  },
8551
8540
  tuskDrift: this.tuskDrift,
@@ -8686,13 +8675,6 @@ var HttpReplayHooks = class {
8686
8675
  return traceIdHeader ? String(traceIdHeader) : null;
8687
8676
  }
8688
8677
  /**
8689
- * Check if we should fetch env vars from CLI
8690
- */
8691
- extractShouldFetchEnvVars(req) {
8692
- const fetchHeader = req.headers["x-td-fetch-env-vars"] || req.headers["X-TD-FETCH-ENV-VARS"];
8693
- return fetchHeader === "true" || fetchHeader === true;
8694
- }
8695
- /**
8696
8678
  * Handle outbound HTTP requests in replay mode
8697
8679
  * Uses TdMockClientRequest for simplified mocking approach
8698
8680
  */
@@ -8722,7 +8704,7 @@ var HttpReplayHooks = class {
8722
8704
 
8723
8705
  //#endregion
8724
8706
  //#region src/instrumentation/core/utils/modeUtils.ts
8725
- var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8707
+ var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8726
8708
  /**
8727
8709
  * Utility function that abstracts the common record mode pattern of checking for current span context
8728
8710
  * and deciding whether to execute record mode logic or just call the original function.
@@ -8743,7 +8725,7 @@ function handleRecordMode({ originalFunctionCall, recordModeHandler, spanKind })
8743
8725
  return originalFunctionCall();
8744
8726
  }
8745
8727
  if (!isAppReady) return recordModeHandler({ isPreAppStart: true });
8746
- 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();
8747
8729
  else return recordModeHandler({ isPreAppStart: false });
8748
8730
  }
8749
8731
  /**
@@ -9981,7 +9963,7 @@ var require_commonjs$1 = /* @__PURE__ */ __commonJS({ "node_modules/@protobuf-ts
9981
9963
  }) });
9982
9964
 
9983
9965
  //#endregion
9984
- //#region node_modules/@use-tusk/drift-schemas/dist/span_export_service-XwF6hpEK.js
9966
+ //#region node_modules/@use-tusk/drift-schemas/dist/span_export_service-CmkFvTqD.js
9985
9967
  var import_commonjs$4 = /* @__PURE__ */ __toESM(require_commonjs$1(), 1);
9986
9968
  var import_commonjs$5 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
9987
9969
  var ExportSpansRequest$Type = class extends import_commonjs$5.MessageType {
@@ -10223,7 +10205,7 @@ function captureStackTrace(excludeClassNames = []) {
10223
10205
 
10224
10206
  //#endregion
10225
10207
  //#region src/instrumentation/libraries/http/HttpTransformEngine.ts
10226
- var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10208
+ var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10227
10209
  /**
10228
10210
  * Creates an empty HttpClientInputValue object for dropped spans
10229
10211
  */
@@ -10276,7 +10258,7 @@ var HttpTransformEngine = class {
10276
10258
  const testSpan = {
10277
10259
  traceId: "",
10278
10260
  spanId: "",
10279
- kind: import_src$29.SpanKind.SERVER,
10261
+ kind: import_src$30.SpanKind.SERVER,
10280
10262
  protocol: "http",
10281
10263
  inputValue: {
10282
10264
  method,
@@ -10299,7 +10281,7 @@ var HttpTransformEngine = class {
10299
10281
  const testSpan = {
10300
10282
  traceId: "",
10301
10283
  spanId: "",
10302
- kind: import_src$29.SpanKind.CLIENT,
10284
+ kind: import_src$30.SpanKind.CLIENT,
10303
10285
  protocol: inputValue.protocol || "http",
10304
10286
  inputValue: clonedInputValue
10305
10287
  };
@@ -10326,8 +10308,8 @@ var HttpTransformEngine = class {
10326
10308
  const matcherFunction = this.compileMatcher(matcher);
10327
10309
  if (action.type === "drop") return (span) => {
10328
10310
  if (!matcherFunction(span)) return;
10329
- if (span.inputValue) span.inputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10330
- 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();
10331
10313
  return {
10332
10314
  type: "drop",
10333
10315
  field: "entire_span",
@@ -10357,8 +10339,8 @@ var HttpTransformEngine = class {
10357
10339
  }
10358
10340
  compileMatcher(matcher) {
10359
10341
  const checks = [];
10360
- if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$29.SpanKind.CLIENT);
10361
- 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);
10362
10344
  if (matcher.method) if (matcher.method.length === 0) {} else {
10363
10345
  const methods = matcher.method.map((method) => method.toUpperCase());
10364
10346
  checks.push((span) => {
@@ -10586,7 +10568,7 @@ var HttpTransformEngine = class {
10586
10568
 
10587
10569
  //#endregion
10588
10570
  //#region src/instrumentation/libraries/http/Instrumentation.ts
10589
- var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10571
+ var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10590
10572
  var HttpInstrumentation = class extends TdInstrumentationBase {
10591
10573
  constructor(config) {
10592
10574
  super("http", config);
@@ -10671,19 +10653,12 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10671
10653
  return originalHandler.call(this);
10672
10654
  }
10673
10655
  logger.debug(`[HttpInstrumentation] Setting replay trace id`, replayTraceId);
10674
- if (this.replayHooks.extractShouldFetchEnvVars(req)) try {
10675
- const envVars = this.tuskDrift.requestEnvVarsSync(replayTraceId);
10676
- EnvVarTracker.setEnvVars(replayTraceId, envVars);
10677
- logger.debug(`[HttpInstrumentation] Fetched env vars from CLI for trace ${replayTraceId}`);
10678
- } catch (error) {
10679
- logger.error(`[HttpInstrumentation] Failed to fetch env vars from CLI:`, error);
10680
- }
10681
10656
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
10682
10657
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
10683
- return import_src$28.context.with(ctxWithReplayTraceId, () => {
10658
+ return import_src$29.context.with(ctxWithReplayTraceId, () => {
10684
10659
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10685
10660
  name: `${target}`,
10686
- kind: import_src$28.SpanKind.SERVER,
10661
+ kind: import_src$29.SpanKind.SERVER,
10687
10662
  packageName: spanProtocol,
10688
10663
  submodule: method,
10689
10664
  packageType: PackageType.HTTP,
@@ -10728,7 +10703,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10728
10703
  logger.debug(`[HttpInstrumentation] Http inbound request arriving, inputValue: ${JSON.stringify(inputValue)}`);
10729
10704
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10730
10705
  name: `${target}`,
10731
- kind: import_src$28.SpanKind.SERVER,
10706
+ kind: import_src$29.SpanKind.SERVER,
10732
10707
  packageName: spanProtocol,
10733
10708
  packageType: PackageType.HTTP,
10734
10709
  submodule: method,
@@ -10748,7 +10723,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10748
10723
  });
10749
10724
  });
10750
10725
  },
10751
- spanKind: import_src$28.SpanKind.SERVER
10726
+ spanKind: import_src$29.SpanKind.SERVER
10752
10727
  });
10753
10728
  } else return originalHandler.call(this);
10754
10729
  }
@@ -10765,8 +10740,8 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10765
10740
  _handleInboundRequestInSpan({ req, res, originalHandler, spanInfo, inputValue, schemaMerges, protocol }) {
10766
10741
  const self = this;
10767
10742
  const spanProtocol = this._normalizeProtocol(protocol, "http");
10768
- import_src$28.context.bind(spanInfo.context, req);
10769
- 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);
10770
10745
  let completeInputValue = inputValue;
10771
10746
  this._captureServerRequestBody(req, spanInfo, inputValue, schemaMerges, (updatedInputValue) => {
10772
10747
  completeInputValue = updatedInputValue;
@@ -10804,7 +10779,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10804
10779
  const spanData = {
10805
10780
  traceId: spanInfo.traceId,
10806
10781
  spanId: spanInfo.spanId,
10807
- kind: import_src$28.SpanKind.SERVER,
10782
+ kind: import_src$29.SpanKind.SERVER,
10808
10783
  protocol: spanProtocol,
10809
10784
  inputValue: completeInputValue,
10810
10785
  outputValue
@@ -10820,14 +10795,12 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10820
10795
  },
10821
10796
  headers: { matchImportance: 0 }
10822
10797
  },
10823
- metadata: { ENV_VARS: EnvVarTracker.getEnvVars(spanInfo.traceId) },
10824
10798
  ...spanData.transformMetadata && { transformMetadata: spanData.transformMetadata }
10825
10799
  });
10826
- EnvVarTracker.clearEnvVars(spanInfo.traceId);
10827
10800
  const status = statusCode >= 400 ? {
10828
- code: import_src$28.SpanStatusCode.ERROR,
10801
+ code: import_src$29.SpanStatusCode.ERROR,
10829
10802
  message: `HTTP ${statusCode}`
10830
- } : { code: import_src$28.SpanStatusCode.OK };
10803
+ } : { code: import_src$29.SpanStatusCode.OK };
10831
10804
  SpanUtils.setStatus(spanInfo.span, status);
10832
10805
  const decodedType = getDecodedType(outputValue.headers?.["content-type"] || "");
10833
10806
  if (decodedType && !ACCEPTABLE_CONTENT_TYPES.has(decodedType)) {
@@ -10869,6 +10842,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10869
10842
  instrumentationName: "HttpInstrumentation",
10870
10843
  submoduleName: completeInputValue.method || inputValue.method,
10871
10844
  inputValue: completeInputValue,
10845
+ environment: self.tuskDrift.getEnvironment(),
10872
10846
  outputValue,
10873
10847
  inputSchema,
10874
10848
  outputSchema,
@@ -10876,7 +10850,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10876
10850
  outputSchemaHash: JsonSchemaHelper.generateDeterministicHash(outputSchema),
10877
10851
  inputValueHash,
10878
10852
  outputValueHash,
10879
- kind: import_src$28.SpanKind.SERVER,
10853
+ kind: import_src$29.SpanKind.SERVER,
10880
10854
  packageType: PackageType.HTTP,
10881
10855
  status: {
10882
10856
  code: statusCode >= 400 ? StatusCode.ERROR : StatusCode.OK,
@@ -10905,7 +10879,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10905
10879
  try {
10906
10880
  logger.debug(`[HttpInstrumentation] Server request error: ${error.message} (${SpanUtils.getTraceInfo()})`);
10907
10881
  SpanUtils.endSpan(spanInfo.span, {
10908
- code: import_src$28.SpanStatusCode.ERROR,
10882
+ code: import_src$29.SpanStatusCode.ERROR,
10909
10883
  message: error.message
10910
10884
  });
10911
10885
  } catch (error$1) {
@@ -10916,7 +10890,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10916
10890
  try {
10917
10891
  logger.debug(`[HttpInstrumentation] Server response error: ${error.message} (${SpanUtils.getTraceInfo()})`);
10918
10892
  SpanUtils.endSpan(spanInfo.span, {
10919
- code: import_src$28.SpanStatusCode.ERROR,
10893
+ code: import_src$29.SpanStatusCode.ERROR,
10920
10894
  message: error.message
10921
10895
  });
10922
10896
  } catch (error$1) {
@@ -11121,7 +11095,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11121
11095
  inputValue: completeInputValue
11122
11096
  });
11123
11097
  SpanUtils.endSpan(spanInfo.span, {
11124
- code: import_src$28.SpanStatusCode.ERROR,
11098
+ code: import_src$29.SpanStatusCode.ERROR,
11125
11099
  message: error.message
11126
11100
  });
11127
11101
  } catch (error$1) {
@@ -11138,7 +11112,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11138
11112
  const spanData = {
11139
11113
  traceId: spanInfo.traceId,
11140
11114
  spanId: spanInfo.spanId,
11141
- kind: import_src$28.SpanKind.CLIENT,
11115
+ kind: import_src$29.SpanKind.CLIENT,
11142
11116
  protocol: normalizedProtocol,
11143
11117
  inputValue,
11144
11118
  outputValue
@@ -11151,9 +11125,9 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11151
11125
  transformMetadata: spanData.transformMetadata ? spanData.transformMetadata : void 0
11152
11126
  });
11153
11127
  const status = statusCode >= 400 ? {
11154
- code: import_src$28.SpanStatusCode.ERROR,
11128
+ code: import_src$29.SpanStatusCode.ERROR,
11155
11129
  message: `HTTP ${statusCode}`
11156
- } : { code: import_src$28.SpanStatusCode.OK };
11130
+ } : { code: import_src$29.SpanStatusCode.OK };
11157
11131
  SpanUtils.endSpan(spanInfo.span, status);
11158
11132
  }
11159
11133
  _captureHeadersFromRawHeaders(rawHeaders) {
@@ -11207,7 +11181,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11207
11181
  };
11208
11182
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11209
11183
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11210
- kind: import_src$28.SpanKind.CLIENT,
11184
+ kind: import_src$29.SpanKind.CLIENT,
11211
11185
  packageName: requestProtocol,
11212
11186
  packageType: PackageType.HTTP,
11213
11187
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11242,7 +11216,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11242
11216
  };
11243
11217
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11244
11218
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11245
- kind: import_src$28.SpanKind.CLIENT,
11219
+ kind: import_src$29.SpanKind.CLIENT,
11246
11220
  packageName: requestProtocol,
11247
11221
  packageType: PackageType.HTTP,
11248
11222
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11254,7 +11228,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11254
11228
  return self._handleOutboundRequestInSpan(originalRequest, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11255
11229
  });
11256
11230
  },
11257
- spanKind: import_src$28.SpanKind.CLIENT
11231
+ spanKind: import_src$29.SpanKind.CLIENT
11258
11232
  });
11259
11233
  else return originalRequest.apply(this, args);
11260
11234
  };
@@ -11300,7 +11274,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11300
11274
  };
11301
11275
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11302
11276
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11303
- kind: import_src$28.SpanKind.CLIENT,
11277
+ kind: import_src$29.SpanKind.CLIENT,
11304
11278
  packageName: requestProtocol,
11305
11279
  packageType: PackageType.HTTP,
11306
11280
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11334,7 +11308,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11334
11308
  };
11335
11309
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11336
11310
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11337
- kind: import_src$28.SpanKind.CLIENT,
11311
+ kind: import_src$29.SpanKind.CLIENT,
11338
11312
  packageName: requestProtocol,
11339
11313
  packageType: PackageType.HTTP,
11340
11314
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11346,7 +11320,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11346
11320
  return self._handleOutboundRequestInSpan(originalGet, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11347
11321
  });
11348
11322
  },
11349
- spanKind: import_src$28.SpanKind.CLIENT
11323
+ spanKind: import_src$29.SpanKind.CLIENT
11350
11324
  });
11351
11325
  else return originalGet.apply(this, args);
11352
11326
  };
@@ -11389,99 +11363,9 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11389
11363
  }
11390
11364
  };
11391
11365
 
11392
- //#endregion
11393
- //#region src/instrumentation/libraries/env/Instrumentation.ts
11394
- /**
11395
- * Environment variable instrumentation that records and replays process.env access.
11396
- * In record mode, captures environment variable values.
11397
- * In replay mode, returns previously recorded values for deterministic behavior.
11398
- */
11399
- var EnvInstrumentation = class extends TdInstrumentationBase {
11400
- constructor(config = {}) {
11401
- super("env", config);
11402
- this.isInPatchedCall = false;
11403
- this.mode = config.mode || TuskDriftMode.DISABLED;
11404
- }
11405
- init() {
11406
- this.patchProcessEnv();
11407
- return [];
11408
- }
11409
- patchProcessEnv() {
11410
- if (this.mode === TuskDriftMode.DISABLED || !this._config.enabled) return;
11411
- this.originalProcessEnv = process.env;
11412
- const envProxy = new Proxy(this.originalProcessEnv, {
11413
- get: (target, property, receiver) => {
11414
- return this._handleEnvAccess(target, property);
11415
- },
11416
- set: (target, property, value, receiver) => {
11417
- target[property] = value;
11418
- return true;
11419
- },
11420
- deleteProperty: (target, property) => {
11421
- delete target[property];
11422
- return true;
11423
- },
11424
- ownKeys: (target) => {
11425
- return Reflect.ownKeys(target);
11426
- },
11427
- getOwnPropertyDescriptor: (target, property) => {
11428
- return Reflect.getOwnPropertyDescriptor(target, property);
11429
- },
11430
- has: (target, property) => {
11431
- return Reflect.has(target, property);
11432
- }
11433
- });
11434
- process.env = envProxy;
11435
- }
11436
- _handleEnvAccess(target, key) {
11437
- if (this.isInPatchedCall) return target[key];
11438
- if (!TuskDriftCore.getInstance().isAppReady()) return target[key];
11439
- this.isInPatchedCall = true;
11440
- try {
11441
- return this._handleEnvAccessInMode(target, key);
11442
- } finally {
11443
- this.isInPatchedCall = false;
11444
- }
11445
- }
11446
- _handleEnvAccessInMode(target, key) {
11447
- let currentSpanInfo = null;
11448
- try {
11449
- currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11450
- } catch (error) {
11451
- logger.error(`EnvInstrumentation error getting current span info:`, error);
11452
- }
11453
- if (!currentSpanInfo) return target[key];
11454
- if (this.mode === TuskDriftMode.REPLAY) return this._handleReplayMode(target, key);
11455
- else if (this.mode === TuskDriftMode.RECORD) return this._handleRecordMode(currentSpanInfo, target, key);
11456
- else return target[key];
11457
- }
11458
- _handleReplayMode(target, key) {
11459
- const replayTraceId = SpanUtils.getCurrentReplayTraceId();
11460
- if (!replayTraceId) return target[key];
11461
- const envVar = EnvVarTracker.getEnvVar(replayTraceId, key);
11462
- if (envVar) {
11463
- logger.debug(`Returning env var ${key} for trace ${replayTraceId}: ${envVar}`);
11464
- return envVar;
11465
- }
11466
- return target[key];
11467
- }
11468
- _handleRecordMode(spanInfo, target, key) {
11469
- try {
11470
- EnvVarTracker.setEnvVar({
11471
- traceId: spanInfo.traceId,
11472
- key,
11473
- value: target[key] || void 0
11474
- });
11475
- } catch (error) {
11476
- logger.error(`EnvInstrumentation error storing env var:`, error);
11477
- }
11478
- return target[key];
11479
- }
11480
- };
11481
-
11482
11366
  //#endregion
11483
11367
  //#region src/instrumentation/libraries/date/Instrumentation.ts
11484
- var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11368
+ var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11485
11369
  /**
11486
11370
  * Date instrumentation that provides consistent dates in replay mode.
11487
11371
  * In replay mode, new Date() calls return the latest mock response timestamp.
@@ -11520,7 +11404,7 @@ var DateInstrumentation = class DateInstrumentation extends TdInstrumentationBas
11520
11404
  if (this.mode !== TuskDriftMode.REPLAY) return this._callOriginalDate(args, isConstructorCall);
11521
11405
  const currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11522
11406
  if (!currentSpanInfo) return this._callOriginalDate(args, isConstructorCall);
11523
- 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);
11524
11408
  this.isInPatchedCall = true;
11525
11409
  try {
11526
11410
  return this._handleReplayDate(args, isConstructorCall);
@@ -11766,7 +11650,7 @@ var TdPgClientMock = class extends events.EventEmitter {
11766
11650
 
11767
11651
  //#endregion
11768
11652
  //#region src/instrumentation/libraries/pg/Instrumentation.ts
11769
- var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11653
+ var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11770
11654
  var PgInstrumentation = class extends TdInstrumentationBase {
11771
11655
  constructor(config = {}) {
11772
11656
  super("pg", config);
@@ -11807,6 +11691,10 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11807
11691
  const self = this;
11808
11692
  return (originalQuery) => {
11809
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
+ }
11810
11698
  let queryConfig = null;
11811
11699
  try {
11812
11700
  queryConfig = self.parseQueryArgs(args);
@@ -11835,7 +11723,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11835
11723
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11836
11724
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11837
11725
  name: spanName,
11838
- kind: import_src$26.SpanKind.CLIENT,
11726
+ kind: import_src$27.SpanKind.CLIENT,
11839
11727
  submodule: "query",
11840
11728
  packageType: PackageType.PG,
11841
11729
  packageName,
@@ -11854,7 +11742,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11854
11742
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11855
11743
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11856
11744
  name: spanName,
11857
- kind: import_src$26.SpanKind.CLIENT,
11745
+ kind: import_src$27.SpanKind.CLIENT,
11858
11746
  submodule: "query",
11859
11747
  packageType: PackageType.PG,
11860
11748
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11865,7 +11753,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11865
11753
  return self._handleRecordQueryInSpan(spanInfo, originalQuery, queryConfig, args, this);
11866
11754
  });
11867
11755
  },
11868
- spanKind: import_src$26.SpanKind.CLIENT
11756
+ spanKind: import_src$27.SpanKind.CLIENT
11869
11757
  });
11870
11758
  else return originalQuery.apply(this, args);
11871
11759
  };
@@ -11887,7 +11775,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11887
11775
  replayModeHandler: () => {
11888
11776
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11889
11777
  name: `pg.connect`,
11890
- kind: import_src$26.SpanKind.CLIENT,
11778
+ kind: import_src$27.SpanKind.CLIENT,
11891
11779
  submodule: "connect",
11892
11780
  packageName: "pg",
11893
11781
  packageType: PackageType.PG,
@@ -11904,7 +11792,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11904
11792
  recordModeHandler: ({ isPreAppStart }) => {
11905
11793
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11906
11794
  name: `pg.connect`,
11907
- kind: import_src$26.SpanKind.CLIENT,
11795
+ kind: import_src$27.SpanKind.CLIENT,
11908
11796
  submodule: "connect",
11909
11797
  packageName: "pg",
11910
11798
  packageType: PackageType.PG,
@@ -11915,12 +11803,19 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11915
11803
  return self._handleRecordConnectInSpan(spanInfo, originalConnect, callback, this);
11916
11804
  });
11917
11805
  },
11918
- spanKind: import_src$26.SpanKind.CLIENT
11806
+ spanKind: import_src$27.SpanKind.CLIENT
11919
11807
  });
11920
11808
  else return originalConnect.apply(this, [callback]);
11921
11809
  };
11922
11810
  };
11923
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
+ }
11924
11819
  parseQueryArgs(args) {
11925
11820
  if (args.length === 0) return null;
11926
11821
  const firstArg = args[0];
@@ -11948,7 +11843,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11948
11843
  logger.debug(`[PgInstrumentation] PG query error (hasCallback): ${error.message} (${SpanUtils.getTraceInfo()})`);
11949
11844
  try {
11950
11845
  SpanUtils.endSpan(spanInfo.span, {
11951
- code: import_src$26.SpanStatusCode.ERROR,
11846
+ code: import_src$27.SpanStatusCode.ERROR,
11952
11847
  message: error.message
11953
11848
  });
11954
11849
  } catch (error$1) {
@@ -11958,7 +11853,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11958
11853
  logger.debug(`[PgInstrumentation] PG query completed successfully (hasCallback) (${SpanUtils.getTraceInfo()})`);
11959
11854
  try {
11960
11855
  this._addOutputAttributesToSpan(spanInfo, result);
11961
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11856
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11962
11857
  } catch (error$1) {
11963
11858
  logger.error(`[PgInstrumentation] error processing response:`, error$1);
11964
11859
  }
@@ -11985,7 +11880,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11985
11880
  logger.debug(`[PgInstrumentation] PG query completed successfully (${SpanUtils.getTraceInfo()})`);
11986
11881
  try {
11987
11882
  this._addOutputAttributesToSpan(spanInfo, result);
11988
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11883
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11989
11884
  } catch (error) {
11990
11885
  logger.error(`[PgInstrumentation] error processing response:`, error);
11991
11886
  }
@@ -11994,7 +11889,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11994
11889
  logger.debug(`[PgInstrumentation] PG query error: ${error.message} (${SpanUtils.getTraceInfo()})`);
11995
11890
  try {
11996
11891
  SpanUtils.endSpan(spanInfo.span, {
11997
- code: import_src$26.SpanStatusCode.ERROR,
11892
+ code: import_src$27.SpanStatusCode.ERROR,
11998
11893
  message: error.message
11999
11894
  });
12000
11895
  } catch (error$1) {
@@ -12026,7 +11921,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12026
11921
  packageName,
12027
11922
  instrumentationName: this.INSTRUMENTATION_NAME,
12028
11923
  submoduleName: "query",
12029
- kind: import_src$26.SpanKind.CLIENT,
11924
+ kind: import_src$27.SpanKind.CLIENT,
12030
11925
  stackTrace
12031
11926
  },
12032
11927
  tuskDrift: this.tuskDrift
@@ -12070,6 +11965,8 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12070
11965
  * Reference for data type IDs: https://jdbc.postgresql.org/documentation/publicapi/constant-values.html
12071
11966
  */
12072
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));
12073
11970
  if (!result || !result.fields || !result.rows) return result;
12074
11971
  if (rowMode === "array") {
12075
11972
  const convertedRows$1 = result.rows.map((row) => {
@@ -12110,7 +12007,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12110
12007
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12111
12008
  try {
12112
12009
  SpanUtils.endSpan(spanInfo.span, {
12113
- code: import_src$26.SpanStatusCode.ERROR,
12010
+ code: import_src$27.SpanStatusCode.ERROR,
12114
12011
  message: error.message
12115
12012
  });
12116
12013
  } catch (error$1) {
@@ -12120,7 +12017,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12120
12017
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12121
12018
  try {
12122
12019
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12123
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12020
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12124
12021
  } catch (error$1) {
12125
12022
  logger.error(`[PgInstrumentation] error processing connect response:`, error$1);
12126
12023
  }
@@ -12132,7 +12029,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12132
12029
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12133
12030
  try {
12134
12031
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12135
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12032
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12136
12033
  } catch (error) {
12137
12034
  logger.error(`[PgInstrumentation] error processing connect response:`, error);
12138
12035
  }
@@ -12141,7 +12038,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12141
12038
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12142
12039
  try {
12143
12040
  SpanUtils.endSpan(spanInfo.span, {
12144
- code: import_src$26.SpanStatusCode.ERROR,
12041
+ code: import_src$27.SpanStatusCode.ERROR,
12145
12042
  message: error.message
12146
12043
  });
12147
12044
  } catch (error$1) {
@@ -12159,7 +12056,18 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12159
12056
  }
12160
12057
  _addOutputAttributesToSpan(spanInfo, result) {
12161
12058
  if (!result) return;
12162
- 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 = {
12163
12071
  command: result.command,
12164
12072
  rowCount: result.rowCount,
12165
12073
  oid: result.oid,
@@ -12202,7 +12110,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12202
12110
  replayModeHandler: () => {
12203
12111
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12204
12112
  name: `pg-pool.connect`,
12205
- kind: import_src$26.SpanKind.CLIENT,
12113
+ kind: import_src$27.SpanKind.CLIENT,
12206
12114
  submodule: "connect",
12207
12115
  packageName: "pg-pool",
12208
12116
  packageType: PackageType.PG,
@@ -12219,7 +12127,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12219
12127
  recordModeHandler: ({ isPreAppStart }) => {
12220
12128
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12221
12129
  name: `pg-pool.connect`,
12222
- kind: import_src$26.SpanKind.CLIENT,
12130
+ kind: import_src$27.SpanKind.CLIENT,
12223
12131
  submodule: "connect",
12224
12132
  packageName: "pg-pool",
12225
12133
  packageType: PackageType.PG,
@@ -12230,7 +12138,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12230
12138
  return self._handleRecordPoolConnectInSpan(spanInfo, originalConnect, callback, this);
12231
12139
  });
12232
12140
  },
12233
- spanKind: import_src$26.SpanKind.CLIENT
12141
+ spanKind: import_src$27.SpanKind.CLIENT
12234
12142
  });
12235
12143
  else return originalConnect.apply(this, [callback]);
12236
12144
  };
@@ -12243,7 +12151,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12243
12151
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12244
12152
  try {
12245
12153
  SpanUtils.endSpan(spanInfo.span, {
12246
- code: import_src$26.SpanStatusCode.ERROR,
12154
+ code: import_src$27.SpanStatusCode.ERROR,
12247
12155
  message: error.message
12248
12156
  });
12249
12157
  } catch (error$1) {
@@ -12256,7 +12164,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12256
12164
  connected: true,
12257
12165
  hasClient: !!client
12258
12166
  } });
12259
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12167
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12260
12168
  } catch (error$1) {
12261
12169
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error$1);
12262
12170
  }
@@ -12271,7 +12179,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12271
12179
  connected: true,
12272
12180
  hasClient: !!client
12273
12181
  } });
12274
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12182
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12275
12183
  } catch (error) {
12276
12184
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error);
12277
12185
  }
@@ -12280,7 +12188,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12280
12188
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12281
12189
  try {
12282
12190
  SpanUtils.endSpan(spanInfo.span, {
12283
- code: import_src$26.SpanStatusCode.ERROR,
12191
+ code: import_src$27.SpanStatusCode.ERROR,
12284
12192
  message: error.message
12285
12193
  });
12286
12194
  } catch (error$1) {
@@ -12309,68 +12217,114 @@ function isPostgresOutputValueType(value) {
12309
12217
  }
12310
12218
 
12311
12219
  //#endregion
12312
- //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12313
- var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12314
- var PostgresInstrumentation = class extends TdInstrumentationBase {
12315
- constructor(config = {}) {
12316
- super("postgres", config);
12317
- this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12318
- this.mode = config.mode || TuskDriftMode.DISABLED;
12319
- 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;
12320
12229
  }
12321
- init() {
12322
- return [new TdInstrumentationNodeModule({
12323
- name: "postgres",
12324
- supportedVersions: ["3.*"],
12325
- patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12326
- })];
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;
12327
12272
  }
12328
- _patchPostgresModule(postgresModule) {
12329
- logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12330
- if (this.isModulePatched(postgresModule)) {
12331
- logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12332
- return postgresModule;
12333
- }
12334
- const self = this;
12335
- if (isEsm(postgresModule)) {
12336
- logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12337
- this._wrap(postgresModule, "default", (originalFunction) => {
12338
- return function(...args) {
12339
- return self._handlePostgresConnection(originalFunction, args);
12340
- };
12341
- });
12342
- } else {
12343
- logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12344
- const originalFunction = postgresModule;
12345
- const wrappedFunction = function(...args) {
12346
- logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12347
- return self._handlePostgresConnection(originalFunction, args);
12348
- };
12349
- Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12350
- Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12351
- for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12352
- Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12353
- if (key !== "prototype" && key !== "length" && key !== "name") {
12354
- const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12355
- if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12356
- }
12357
- });
12358
- postgresModule = wrappedFunction;
12359
- }
12360
- if (postgresModule.sql && typeof postgresModule.sql === "function") {
12361
- this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12362
- logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12363
- }
12364
- this.markModuleAsPatched(postgresModule);
12365
- logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12366
- 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}`;
12367
12310
  }
12368
- _handlePostgresConnection(originalFunction, args) {
12369
- const connectionString = typeof args[0] === "string" ? args[0] : void 0;
12370
- 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) {
12371
12325
  const inputValue = {
12372
- connectionString: connectionString ? this._sanitizeConnectionString(connectionString) : void 0,
12373
- 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]
12374
12328
  };
12375
12329
  if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
12376
12330
  noOpRequestHandler: () => {
@@ -12384,96 +12338,148 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12384
12338
  }));
12385
12339
  mockSql.begin = () => Promise.resolve();
12386
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();
12387
12351
  return mockSql;
12388
12352
  },
12389
12353
  isServerRequest: false,
12390
12354
  replayModeHandler: () => {
12391
12355
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12392
12356
  const sqlInstance = originalFunction(...args);
12393
- return this._wrapSqlInstance(sqlInstance);
12357
+ return this.wrapSqlInstance(sqlInstance);
12394
12358
  }, {
12395
12359
  name: "postgres.connect",
12396
- kind: import_src$25.SpanKind.CLIENT,
12360
+ kind: import_src$26.SpanKind.CLIENT,
12397
12361
  submodule: "connect",
12398
12362
  packageType: PackageType.PG,
12399
12363
  packageName: "postgres",
12400
- instrumentationName: this.INSTRUMENTATION_NAME,
12364
+ instrumentationName: this.instrumentationName,
12401
12365
  inputValue,
12402
- isPreAppStart: false
12366
+ isPreAppStart: this.isAppReady() ? false : true
12403
12367
  }, (spanInfo) => {
12404
- return this._handleReplayConnect(originalFunction, args);
12368
+ return this.handleReplayConnect(originalFunction, args);
12405
12369
  });
12406
12370
  }
12407
12371
  });
12408
12372
  else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
12409
12373
  originalFunctionCall: () => {
12410
12374
  const sqlInstance = originalFunction(...args);
12411
- return this._wrapSqlInstance(sqlInstance);
12375
+ return this.wrapSqlInstance(sqlInstance);
12412
12376
  },
12413
12377
  recordModeHandler: ({ isPreAppStart }) => {
12414
12378
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12415
12379
  const sqlInstance = originalFunction(...args);
12416
- return this._wrapSqlInstance(sqlInstance);
12380
+ return this.wrapSqlInstance(sqlInstance);
12417
12381
  }, {
12418
12382
  name: "postgres.connect",
12419
- kind: import_src$25.SpanKind.CLIENT,
12383
+ kind: import_src$26.SpanKind.CLIENT,
12420
12384
  submodule: "connect",
12421
12385
  packageType: PackageType.PG,
12422
12386
  packageName: "postgres",
12423
- instrumentationName: this.INSTRUMENTATION_NAME,
12387
+ instrumentationName: this.instrumentationName,
12424
12388
  inputValue,
12425
12389
  isPreAppStart
12426
12390
  }, (spanInfo) => {
12427
- return this._handleRecordConnect(spanInfo, originalFunction, args);
12391
+ return this.handleRecordConnect(spanInfo, originalFunction, args);
12428
12392
  });
12429
12393
  },
12430
- spanKind: import_src$25.SpanKind.CLIENT
12394
+ spanKind: import_src$26.SpanKind.CLIENT
12431
12395
  });
12432
12396
  else return originalFunction(...args);
12433
12397
  }
12434
- _sanitizeConnectionString(connectionString) {
12435
- try {
12436
- const url = new URL(connectionString);
12437
- if (url.password) url.password = "***";
12438
- return url.toString();
12439
- } catch {
12440
- return "[INVALID_URL]";
12441
- }
12442
- }
12443
- _sanitizeConnectionOptions(options) {
12444
- if (!options || typeof options !== "object") return options;
12445
- const sanitized = { ...options };
12446
- if (sanitized.password) sanitized.password = "***";
12447
- if (sanitized.ssl && typeof sanitized.ssl === "object") {
12448
- sanitized.ssl = { ...sanitized.ssl };
12449
- if (sanitized.ssl.key) sanitized.ssl.key = "***";
12450
- if (sanitized.ssl.cert) sanitized.ssl.cert = "***";
12451
- if (sanitized.ssl.ca) sanitized.ssl.ca = "***";
12452
- }
12453
- return sanitized;
12454
- }
12455
- _handleRecordConnect(spanInfo, originalFunction, args) {
12398
+ handleRecordConnect(spanInfo, originalFunction, args) {
12456
12399
  const sqlInstance = originalFunction(...args);
12457
- const wrappedInstance = this._wrapSqlInstance(sqlInstance);
12400
+ const wrappedInstance = this.wrapSqlInstance(sqlInstance);
12458
12401
  try {
12459
12402
  logger.debug(`[PostgresInstrumentation] Postgres connection created successfully (${SpanUtils.getTraceInfo()})`);
12460
12403
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12461
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12404
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12462
12405
  } catch (error) {
12463
12406
  logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12464
12407
  }
12465
12408
  return wrappedInstance;
12466
12409
  }
12467
- _handleReplayConnect(originalFunction, args) {
12410
+ handleReplayConnect(originalFunction, args) {
12468
12411
  logger.debug(`[PostgresInstrumentation] Replaying Postgres connection`);
12469
12412
  try {
12470
12413
  const sqlInstance = originalFunction(...args);
12471
- return this._wrapSqlInstance(sqlInstance);
12414
+ return this.wrapSqlInstance(sqlInstance);
12472
12415
  } catch (error) {
12473
12416
  logger.debug(`[PostgresInstrumentation] Postgres connection error in replay: ${error.message}`);
12474
12417
  throw error;
12475
12418
  }
12476
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
+ }
12477
12483
  _wrapSqlInstance(sqlInstance) {
12478
12484
  if (!sqlInstance || typeof sqlInstance !== "function") return sqlInstance;
12479
12485
  const self = this;
@@ -12489,11 +12495,34 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12489
12495
  logger.debug(`[PostgresInstrumentation] Wrapped unsafe method on sql instance`);
12490
12496
  }
12491
12497
  if (typeof originalSql.begin === "function") {
12492
- wrappedSql.begin = self._wrapBeginMethod(originalSql);
12493
- 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`);
12494
12517
  }
12495
12518
  return wrappedSql;
12496
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
+ }
12497
12526
  _wrapUnsafeMethod(sqlInstance) {
12498
12527
  const self = this;
12499
12528
  const originalUnsafe = sqlInstance.unsafe;
@@ -12510,9 +12539,178 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12510
12539
  return self._handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback);
12511
12540
  };
12512
12541
  }
12513
- _getSqlPatchFn() {
12542
+ _wrapFileMethod(sqlInstance) {
12514
12543
  const self = this;
12515
- return (originalSql) => {
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
+ }
12711
+ _getSqlPatchFn() {
12712
+ const self = this;
12713
+ return (originalSql) => {
12516
12714
  return function sql(strings, ...values) {
12517
12715
  return self._handleSqlQuery(originalSql, strings, values);
12518
12716
  };
@@ -12522,93 +12720,19 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12522
12720
  if (!strings || !Array.isArray(strings.raw)) return originalSql.call(this, strings, ...values);
12523
12721
  const creationContext = import_src$25.context.active();
12524
12722
  const query = originalSql.call(this, strings, ...values);
12525
- const originalThen = query.then.bind(query);
12526
- const self = this;
12527
- query.then = function(onFulfilled, onRejected) {
12528
- let queryString = "";
12529
- for (let i = 0; i < strings.length; i++) {
12530
- queryString += strings[i];
12531
- if (i < values.length) queryString += `$${i + 1}`;
12532
- }
12533
- const inputValue = {
12534
- query: queryString.trim(),
12535
- parameters: values
12536
- };
12537
- return import_src$25.context.with(creationContext, () => {
12538
- if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12539
- originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12540
- recordModeHandler: ({ isPreAppStart }) => {
12541
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12542
- name: "postgres.query",
12543
- kind: import_src$25.SpanKind.CLIENT,
12544
- submodule: "query",
12545
- packageType: PackageType.PG,
12546
- instrumentationName: self.INSTRUMENTATION_NAME,
12547
- packageName: "postgres",
12548
- inputValue,
12549
- isPreAppStart
12550
- }, (spanInfo) => {
12551
- const wrappedOnFulfilled = (result) => {
12552
- try {
12553
- logger.debug(`[PostgresInstrumentation] Postgres query completed successfully`, result);
12554
- self._addOutputAttributesToSpan(spanInfo, result);
12555
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12556
- } catch (error) {
12557
- logger.error(`[PostgresInstrumentation] error processing query response:`, error);
12558
- }
12559
- return onFulfilled ? onFulfilled(result) : result;
12560
- };
12561
- const wrappedOnRejected = (error) => {
12562
- try {
12563
- logger.debug(`[PostgresInstrumentation] Postgres query error`, error);
12564
- SpanUtils.endSpan(spanInfo.span, {
12565
- code: import_src$25.SpanStatusCode.ERROR,
12566
- message: error.message
12567
- });
12568
- } catch (spanError) {
12569
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12570
- }
12571
- if (onRejected) return onRejected(error);
12572
- throw error;
12573
- };
12574
- return originalThen(wrappedOnFulfilled, wrappedOnRejected);
12575
- });
12576
- },
12577
- spanKind: import_src$25.SpanKind.CLIENT
12578
- });
12579
- else if (self.mode === TuskDriftMode.REPLAY) {
12580
- const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12581
- return handleReplayMode({
12582
- noOpRequestHandler: () => Promise.resolve(Object.assign([], {
12583
- count: 0,
12584
- command: null
12585
- })),
12586
- isServerRequest: false,
12587
- replayModeHandler: () => {
12588
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12589
- name: "postgres.query",
12590
- kind: import_src$25.SpanKind.CLIENT,
12591
- submodule: "query",
12592
- packageType: PackageType.PG,
12593
- packageName: "postgres",
12594
- instrumentationName: self.INSTRUMENTATION_NAME,
12595
- inputValue,
12596
- isPreAppStart: false
12597
- }, async (spanInfo) => {
12598
- const mockedResult = await self.handleReplaySqlQuery({
12599
- inputValue,
12600
- spanInfo,
12601
- submodule: "query",
12602
- name: "postgres.query",
12603
- stackTrace
12604
- });
12605
- return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12606
- });
12607
- }
12608
- });
12609
- } else return originalThen(onFulfilled, onRejected);
12610
- });
12723
+ const inputValue = {
12724
+ query: reconstructQueryString(strings, values).trim(),
12725
+ parameters: values
12611
12726
  };
12727
+ const originalThen = query.then.bind(query);
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);
12612
12736
  return query;
12613
12737
  }
12614
12738
  _handleUnsafeQuery(sqlInstance, originalUnsafe, query, parameters, queryOptions) {
@@ -12619,21 +12743,46 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12619
12743
  })();
12620
12744
  const creationContext = import_src$25.context.active();
12621
12745
  const originalThen = unsafeQuery.then.bind(unsafeQuery);
12622
- const self = this;
12623
12746
  const inputValue = {
12624
12747
  query: query.trim(),
12625
12748
  parameters: parameters || [],
12626
12749
  options: queryOptions
12627
12750
  };
12628
- 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;
12629
12778
  return import_src$25.context.with(creationContext, () => {
12630
12779
  if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12631
12780
  originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12632
12781
  recordModeHandler: ({ isPreAppStart }) => {
12633
12782
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12634
- name: "postgres.unsafe",
12783
+ name: "postgres.file",
12635
12784
  kind: import_src$25.SpanKind.CLIENT,
12636
- submodule: "unsafe",
12785
+ submodule: "file",
12637
12786
  packageType: PackageType.PG,
12638
12787
  packageName: "postgres",
12639
12788
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -12642,17 +12791,17 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12642
12791
  }, (spanInfo) => {
12643
12792
  const wrappedOnFulfilled = (result) => {
12644
12793
  try {
12645
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query completed successfully (${SpanUtils.getTraceInfo()})`);
12646
- self._addOutputAttributesToSpan(spanInfo, result);
12794
+ logger.debug(`[PostgresInstrumentation] Postgres file query completed successfully (${SpanUtils.getTraceInfo()})`);
12795
+ addOutputAttributesToSpan(spanInfo, result);
12647
12796
  SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12648
12797
  } catch (error) {
12649
- logger.error(`[PostgresInstrumentation] error processing unsafe query response:`, error);
12798
+ logger.error(`[PostgresInstrumentation] error processing file query response:`, error);
12650
12799
  }
12651
12800
  return onFulfilled ? onFulfilled(result) : result;
12652
12801
  };
12653
12802
  const wrappedOnRejected = (error) => {
12654
12803
  try {
12655
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query error: ${error.message}`);
12804
+ logger.debug(`[PostgresInstrumentation] Postgres file query error: ${error.message}`);
12656
12805
  SpanUtils.endSpan(spanInfo.span, {
12657
12806
  code: import_src$25.SpanStatusCode.ERROR,
12658
12807
  message: error.message
@@ -12678,22 +12827,24 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12678
12827
  isServerRequest: false,
12679
12828
  replayModeHandler: () => {
12680
12829
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12681
- name: "postgres.unsafe",
12830
+ name: "postgres.file",
12682
12831
  kind: import_src$25.SpanKind.CLIENT,
12683
- submodule: "unsafe",
12832
+ submodule: "file",
12684
12833
  packageType: PackageType.PG,
12685
12834
  packageName: "postgres",
12686
12835
  instrumentationName: self.INSTRUMENTATION_NAME,
12687
12836
  inputValue,
12688
- isPreAppStart: false
12837
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
12689
12838
  }, async (spanInfo) => {
12690
- const mockedResult = await self.handleReplayUnsafeQuery({
12839
+ const mockedResult = await self._handleReplayQueryOperation({
12691
12840
  inputValue,
12692
12841
  spanInfo,
12693
- submodule: "unsafe",
12694
- name: "postgres.unsafe",
12695
- stackTrace
12842
+ submodule: "file",
12843
+ name: "postgres.file",
12844
+ stackTrace,
12845
+ operationType: "file"
12696
12846
  });
12847
+ if (!mockedResult) throw new Error(`No mock data found for Postgres file query: ${inputValue.query}`);
12697
12848
  return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12698
12849
  });
12699
12850
  }
@@ -12701,16 +12852,45 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12701
12852
  } else return originalThen(onFulfilled, onRejected);
12702
12853
  });
12703
12854
  };
12704
- 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
+ };
12705
12884
  }
12706
12885
  _handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback) {
12707
12886
  const inputValue = {
12708
12887
  query: "BEGIN",
12709
12888
  options: options ? { transactionOptions: options } : void 0
12710
12889
  };
12890
+ const wrappedCallback = transactionCallback ? this._wrapTransactionCallback(transactionCallback) : void 0;
12711
12891
  const executeBegin = () => {
12712
- if (options && transactionCallback) return originalBegin.call(sqlInstance, options, transactionCallback);
12713
- 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);
12714
12894
  else return originalBegin.call(sqlInstance, options || void 0);
12715
12895
  };
12716
12896
  if (this.mode === TuskDriftMode.REPLAY) {
@@ -12727,9 +12907,9 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12727
12907
  packageName: "postgres",
12728
12908
  instrumentationName: this.INSTRUMENTATION_NAME,
12729
12909
  inputValue,
12730
- isPreAppStart: false
12910
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12731
12911
  }, (spanInfo) => {
12732
- return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
12912
+ return this._handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback);
12733
12913
  });
12734
12914
  }
12735
12915
  });
@@ -12754,55 +12934,47 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12754
12934
  else return executeBegin();
12755
12935
  }
12756
12936
  _handleRecordBeginTransaction(spanInfo, executeBegin) {
12757
- const promise = executeBegin();
12758
- promise.finally(() => {
12759
- promise.then((result) => {
12760
- logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12761
- try {
12762
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12763
- status: "committed",
12764
- result
12765
- } });
12766
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12767
- } catch (error) {
12768
- logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12769
- }
12770
- }).catch((error) => {
12771
- logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12772
- try {
12773
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12774
- status: "rolled_back",
12775
- error: error.message
12776
- } });
12777
- SpanUtils.endSpan(spanInfo.span, {
12778
- code: import_src$25.SpanStatusCode.ERROR,
12779
- message: error.message
12780
- });
12781
- } catch (spanError) {
12782
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12783
- }
12784
- });
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;
12785
12964
  });
12786
- return promise;
12787
12965
  }
12788
- async _handleReplayBeginTransaction(spanInfo, options, stackTrace) {
12966
+ async _handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback) {
12789
12967
  logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
12790
- const mockData = await findMockResponseAsync({
12791
- mockRequestData: {
12792
- traceId: spanInfo.traceId,
12793
- spanId: spanInfo.spanId,
12794
- name: "postgres.begin",
12795
- inputValue: createMockInputValue({
12796
- query: "BEGIN",
12797
- options: options ? { transactionOptions: options } : void 0
12798
- }),
12799
- packageName: "postgres",
12800
- instrumentationName: this.INSTRUMENTATION_NAME,
12801
- submoduleName: "transaction",
12802
- kind: import_src$25.SpanKind.CLIENT,
12803
- stackTrace
12804
- },
12805
- tuskDrift: this.tuskDrift
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
12806
12978
  });
12807
12979
  if (!mockData) {
12808
12980
  logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
@@ -12810,15 +12982,49 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12810
12982
  }
12811
12983
  logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
12812
12984
  const transactionResult = mockData.result;
12813
- if (transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed") return transactionResult.result;
12985
+ const wasCommitted = transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed";
12986
+ if (!wrappedCallback) if (wasCommitted) return transactionResult.result;
12814
12987
  else {
12815
12988
  const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
12816
12989
  throw new Error(errorMessage);
12817
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
+ }
12818
13000
  }
12819
- async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12820
- logger.debug(`[PostgresInstrumentation] Replaying Postgres sql query`);
12821
- const mockData = await findMockResponseAsync({
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({
12822
13028
  mockRequestData: {
12823
13029
  traceId: spanInfo.traceId,
12824
13030
  spanId: spanInfo.spanId,
@@ -12826,79 +13032,574 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12826
13032
  inputValue: createMockInputValue(inputValue),
12827
13033
  packageName: "postgres",
12828
13034
  instrumentationName: this.INSTRUMENTATION_NAME,
12829
- submoduleName: submodule,
13035
+ submoduleName,
12830
13036
  kind: import_src$25.SpanKind.CLIENT,
12831
13037
  stackTrace
12832
13038
  },
12833
13039
  tuskDrift: this.tuskDrift
12834
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
+ });
12835
13069
  if (!mockData) {
12836
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12837
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres sql query: ${queryText}`);
12838
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres sql query: ${queryText}`);
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);
12839
13073
  }
12840
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres sql query: ${JSON.stringify(mockData)}`);
12841
- const processedResult = this.convertPostgresTypes(mockData.result);
12842
- logger.debug(`[PostgresInstrumentation] Sql query processed result: ${JSON.stringify(processedResult)}`);
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)}`);
12843
13077
  return processedResult;
12844
13078
  }
12845
- async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12846
- logger.debug(`[PostgresInstrumentation] Replaying Postgres unsafe query`);
12847
- const mockData = await findMockResponseAsync({
12848
- mockRequestData: {
12849
- traceId: spanInfo.traceId,
12850
- spanId: spanInfo.spanId,
12851
- name,
12852
- inputValue: createMockInputValue(inputValue),
12853
- packageName: "postgres",
12854
- instrumentationName: this.INSTRUMENTATION_NAME,
12855
- submoduleName: submodule,
12856
- kind: import_src$25.SpanKind.CLIENT,
12857
- stackTrace
12858
- },
12859
- tuskDrift: this.tuskDrift
12860
- });
12861
- if (!mockData) {
12862
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12863
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres unsafe query: ${queryText}`);
12864
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres unsafe query: ${queryText}`);
12865
- }
12866
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres unsafe query: ${JSON.stringify(mockData)}`);
12867
- const processedResult = this.convertPostgresTypes(mockData.result);
12868
- logger.debug(`[PostgresInstrumentation] Unsafe query processed result: ${JSON.stringify(processedResult)}`);
12869
- return processedResult;
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
+ });
13180
+ }
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
+ }
13520
+ });
13521
+ } else return originalThen(onFulfilled, onRejected);
13522
+ });
13523
+ };
13524
+ }
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
+ };
12870
13536
  }
12871
- convertPostgresTypes(result) {
12872
- if (!isPostgresOutputValueType(result)) {
12873
- logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12874
- return;
12875
- }
12876
- const { rows, count, command } = result;
12877
- const resultArray = Array.from(rows || []);
12878
- Object.defineProperties(resultArray, {
12879
- count: {
12880
- value: count !== void 0 ? count : null,
12881
- writable: true,
12882
- enumerable: false
12883
- },
12884
- command: {
12885
- value: command || null,
12886
- writable: true,
12887
- enumerable: false
12888
- }
12889
- });
12890
- 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
+ };
12891
13579
  }
12892
- _addOutputAttributesToSpan(spanInfo, result) {
12893
- if (!result) return;
12894
- const isArray$1 = Array.isArray(result);
12895
- logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12896
- const outputValue = {
12897
- rows: isArray$1 ? Array.from(result) : result.rows || [],
12898
- count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12899
- 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);
12900
13602
  };
12901
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12902
13603
  }
12903
13604
  _wrap(target, propertyName, wrapper) {
12904
13605
  wrap(target, propertyName, wrapper);
@@ -12921,8 +13622,9 @@ function isMysqlOkPacket(result) {
12921
13622
  * Extends EventEmitter to properly handle all connection methods and events
12922
13623
  */
12923
13624
  var TdMysqlConnectionMock = class extends events.EventEmitter {
12924
- constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo) {
13625
+ constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo, pool) {
12925
13626
  super();
13627
+ this._pool = null;
12926
13628
  this.threadId = null;
12927
13629
  this.config = {
12928
13630
  host: "localhost",
@@ -12934,6 +13636,7 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12934
13636
  this.spanInfo = spanInfo;
12935
13637
  this.clientType = clientType;
12936
13638
  this.threadId = 1;
13639
+ this._pool = pool;
12937
13640
  }
12938
13641
  query(...args) {
12939
13642
  logger.debug(`[TdMysqlConnectionMock] Mock connection query intercepted in REPLAY mode`);
@@ -12941,7 +13644,13 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12941
13644
  let values;
12942
13645
  let callback;
12943
13646
  let options = {};
12944
- 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") {
12945
13654
  sql = args[0];
12946
13655
  if (typeof args[1] === "function") callback = args[1];
12947
13656
  else if (Array.isArray(args[1])) {
@@ -12993,6 +13702,7 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
12993
13702
  }
12994
13703
  }
12995
13704
  release() {
13705
+ if (this._pool) this._pool.emit("release", this);
12996
13706
  this.emit("end");
12997
13707
  }
12998
13708
  destroy() {
@@ -13017,19 +13727,22 @@ var TdMysqlConnectionMock = class extends events.EventEmitter {
13017
13727
  return;
13018
13728
  }
13019
13729
  }
13020
- beginTransaction(callback) {
13730
+ beginTransaction(optionsOrCallback, callbackArg) {
13731
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
13021
13732
  if (callback) {
13022
13733
  process.nextTick(() => callback(null));
13023
13734
  return;
13024
13735
  }
13025
13736
  }
13026
- commit(callback) {
13737
+ commit(optionsOrCallback, callbackArg) {
13738
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
13027
13739
  if (callback) {
13028
13740
  process.nextTick(() => callback(null));
13029
13741
  return;
13030
13742
  }
13031
13743
  }
13032
- rollback(callback) {
13744
+ rollback(optionsOrCallback, callbackArg) {
13745
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
13033
13746
  if (callback) {
13034
13747
  process.nextTick(() => callback(null));
13035
13748
  return;
@@ -13225,6 +13938,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13225
13938
  name: "mysql/lib/Pool.js",
13226
13939
  supportedVersions: ["2.*"],
13227
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)
13228
13946
  })
13229
13947
  ]
13230
13948
  })];
@@ -13364,12 +14082,40 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13364
14082
  return PoolClass;
13365
14083
  }
13366
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
+ /**
13367
14111
  * Get wrapper function for query method (prototype-level patching)
13368
14112
  */
13369
14113
  _getQueryPatchFn() {
13370
14114
  const self = this;
13371
14115
  return (originalQuery) => {
13372
14116
  return function query(...args) {
14117
+ const firstArg = args[0];
14118
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13373
14119
  let sql;
13374
14120
  let values;
13375
14121
  let callback;
@@ -13380,6 +14126,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13380
14126
  values = queryObj.values;
13381
14127
  options = { nestTables: queryObj.nestTables };
13382
14128
  callback = args.find((arg) => typeof arg === "function");
14129
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13383
14130
  } catch (error) {
13384
14131
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13385
14132
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13390,7 +14137,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13390
14137
  values,
13391
14138
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13392
14139
  };
13393
- const isEventEmitterMode = !callback;
14140
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13394
14141
  if (self.mode === TuskDriftMode.REPLAY) {
13395
14142
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13396
14143
  return handleReplayMode({
@@ -13486,11 +14233,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13486
14233
  _getBeginTransactionPatchFn() {
13487
14234
  const self = this;
13488
14235
  return (originalBeginTransaction) => {
13489
- return function beginTransaction(callback) {
14236
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14237
+ let actualCallback;
14238
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14239
+ else actualCallback = callbackArg;
13490
14240
  const inputValue = { query: "BEGIN" };
13491
14241
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13492
14242
  noOpRequestHandler: () => {
13493
- if (callback) setImmediate(() => callback(null));
14243
+ if (actualCallback) setImmediate(() => actualCallback(null));
13494
14244
  },
13495
14245
  isServerRequest: false,
13496
14246
  replayModeHandler: () => {
@@ -13504,7 +14254,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13504
14254
  inputValue,
13505
14255
  isPreAppStart: false
13506
14256
  }, (spanInfo) => {
13507
- return self._handleReplayTransaction(inputValue, callback);
14257
+ return self._handleReplayTransaction(inputValue, actualCallback);
13508
14258
  });
13509
14259
  }
13510
14260
  });
@@ -13521,7 +14271,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13521
14271
  inputValue,
13522
14272
  isPreAppStart
13523
14273
  }, (spanInfo) => {
13524
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, callback);
14274
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, actualCallback);
13525
14275
  });
13526
14276
  },
13527
14277
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13536,11 +14286,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13536
14286
  _getCommitPatchFn() {
13537
14287
  const self = this;
13538
14288
  return (originalCommit) => {
13539
- return function commit(callback) {
14289
+ return function commit(optionsOrCallback, callbackArg) {
14290
+ let actualCallback;
14291
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14292
+ else actualCallback = callbackArg;
13540
14293
  const inputValue = { query: "COMMIT" };
13541
14294
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13542
14295
  noOpRequestHandler: () => {
13543
- if (callback) setImmediate(() => callback(null));
14296
+ if (actualCallback) setImmediate(() => actualCallback(null));
13544
14297
  },
13545
14298
  isServerRequest: false,
13546
14299
  replayModeHandler: () => {
@@ -13554,7 +14307,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13554
14307
  inputValue,
13555
14308
  isPreAppStart: false
13556
14309
  }, (spanInfo) => {
13557
- return self._handleReplayTransaction(inputValue, callback);
14310
+ return self._handleReplayTransaction(inputValue, actualCallback);
13558
14311
  });
13559
14312
  }
13560
14313
  });
@@ -13571,7 +14324,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13571
14324
  inputValue,
13572
14325
  isPreAppStart
13573
14326
  }, (spanInfo) => {
13574
- return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, callback);
14327
+ return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, actualCallback);
13575
14328
  });
13576
14329
  },
13577
14330
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13586,11 +14339,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13586
14339
  _getRollbackPatchFn() {
13587
14340
  const self = this;
13588
14341
  return (originalRollback) => {
13589
- return function rollback(callback) {
14342
+ return function rollback(optionsOrCallback, callbackArg) {
14343
+ let actualCallback;
14344
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14345
+ else actualCallback = callbackArg;
13590
14346
  const inputValue = { query: "ROLLBACK" };
13591
14347
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13592
14348
  noOpRequestHandler: () => {
13593
- if (callback) setImmediate(() => callback(null));
14349
+ if (actualCallback) setImmediate(() => actualCallback(null));
13594
14350
  },
13595
14351
  isServerRequest: false,
13596
14352
  replayModeHandler: () => {
@@ -13604,7 +14360,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13604
14360
  inputValue,
13605
14361
  isPreAppStart: false
13606
14362
  }, (spanInfo) => {
13607
- return self._handleReplayTransaction(inputValue, callback);
14363
+ return self._handleReplayTransaction(inputValue, actualCallback);
13608
14364
  });
13609
14365
  }
13610
14366
  });
@@ -13621,7 +14377,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13621
14377
  inputValue,
13622
14378
  isPreAppStart
13623
14379
  }, (spanInfo) => {
13624
- return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, callback);
14380
+ return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, actualCallback);
13625
14381
  });
13626
14382
  },
13627
14383
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13789,9 +14545,10 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13789
14545
  return (originalGetConnection) => {
13790
14546
  return function getConnection(callback) {
13791
14547
  const inputValue = { clientType: "pool" };
14548
+ const pool = this;
13792
14549
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13793
14550
  noOpRequestHandler: () => {
13794
- return self._handleNoOpReplayGetConnection(callback);
14551
+ return self._handleNoOpReplayGetConnection(pool, callback);
13795
14552
  },
13796
14553
  isServerRequest: false,
13797
14554
  replayModeHandler: () => {
@@ -13805,7 +14562,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13805
14562
  inputValue,
13806
14563
  isPreAppStart: false
13807
14564
  }, (spanInfo) => {
13808
- return self._handleReplayPoolGetConnection(spanInfo, callback);
14565
+ return self._handleReplayPoolGetConnection(pool, spanInfo, callback);
13809
14566
  });
13810
14567
  }
13811
14568
  });
@@ -13835,6 +14592,8 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13835
14592
  const self = this;
13836
14593
  return (originalQuery) => {
13837
14594
  return function query(...args) {
14595
+ const firstArg = args[0];
14596
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13838
14597
  let sql;
13839
14598
  let values;
13840
14599
  let callback;
@@ -13845,6 +14604,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13845
14604
  values = queryObj.values;
13846
14605
  options = { nestTables: queryObj.nestTables };
13847
14606
  callback = args.find((arg) => typeof arg === "function");
14607
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13848
14608
  } catch (error) {
13849
14609
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13850
14610
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13855,7 +14615,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13855
14615
  values,
13856
14616
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13857
14617
  };
13858
- const isEventEmitterMode = !callback;
14618
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13859
14619
  if (self.mode === TuskDriftMode.REPLAY) {
13860
14620
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13861
14621
  return handleReplayMode({
@@ -13957,6 +14717,33 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13957
14717
  });
13958
14718
  return queryEmitter;
13959
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
+ }
13960
14747
  const originalCallback = callback;
13961
14748
  const callbackIndex = args.findIndex((arg) => typeof arg === "function");
13962
14749
  args[callbackIndex] = function(err, results, fields) {
@@ -14011,11 +14798,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14011
14798
  _patchBeginTransaction(connection) {
14012
14799
  const self = this;
14013
14800
  return (originalBeginTransaction) => {
14014
- return function beginTransaction(callback) {
14801
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14802
+ let actualCallback;
14803
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14804
+ else actualCallback = callbackArg;
14015
14805
  const inputValue = { query: "BEGIN" };
14016
14806
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
14017
14807
  noOpRequestHandler: () => {
14018
- if (callback) setImmediate(() => callback(null));
14808
+ if (actualCallback) setImmediate(() => actualCallback(null));
14019
14809
  },
14020
14810
  isServerRequest: false,
14021
14811
  replayModeHandler: () => {
@@ -14029,7 +14819,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14029
14819
  inputValue,
14030
14820
  isPreAppStart: false
14031
14821
  }, (spanInfo) => {
14032
- return self._handleReplayTransaction(inputValue, callback);
14822
+ return self._handleReplayTransaction(inputValue, actualCallback);
14033
14823
  });
14034
14824
  }
14035
14825
  });
@@ -14046,7 +14836,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14046
14836
  inputValue,
14047
14837
  isPreAppStart
14048
14838
  }, (spanInfo) => {
14049
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, callback);
14839
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, actualCallback);
14050
14840
  });
14051
14841
  },
14052
14842
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14058,11 +14848,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14058
14848
  _patchCommit(connection) {
14059
14849
  const self = this;
14060
14850
  return (originalCommit) => {
14061
- return function commit(callback) {
14851
+ return function commit(optionsOrCallback, callbackArg) {
14852
+ let actualCallback;
14853
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14854
+ else actualCallback = callbackArg;
14062
14855
  const inputValue = { query: "COMMIT" };
14063
14856
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
14064
14857
  noOpRequestHandler: () => {
14065
- if (callback) setImmediate(() => callback(null));
14858
+ if (actualCallback) setImmediate(() => actualCallback(null));
14066
14859
  },
14067
14860
  isServerRequest: false,
14068
14861
  replayModeHandler: () => {
@@ -14076,7 +14869,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14076
14869
  inputValue,
14077
14870
  isPreAppStart: false
14078
14871
  }, (spanInfo) => {
14079
- return self._handleReplayTransaction(inputValue, callback);
14872
+ return self._handleReplayTransaction(inputValue, actualCallback);
14080
14873
  });
14081
14874
  }
14082
14875
  });
@@ -14093,7 +14886,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14093
14886
  inputValue,
14094
14887
  isPreAppStart
14095
14888
  }, (spanInfo) => {
14096
- return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, callback);
14889
+ return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, actualCallback);
14097
14890
  });
14098
14891
  },
14099
14892
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14105,11 +14898,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14105
14898
  _patchRollback(connection) {
14106
14899
  const self = this;
14107
14900
  return (originalRollback) => {
14108
- return function rollback(callback) {
14901
+ return function rollback(optionsOrCallback, callbackArg) {
14902
+ let actualCallback;
14903
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14904
+ else actualCallback = callbackArg;
14109
14905
  const inputValue = { query: "ROLLBACK" };
14110
14906
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
14111
14907
  noOpRequestHandler: () => {
14112
- if (callback) setImmediate(() => callback(null));
14908
+ if (actualCallback) setImmediate(() => actualCallback(null));
14113
14909
  },
14114
14910
  isServerRequest: false,
14115
14911
  replayModeHandler: () => {
@@ -14123,7 +14919,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14123
14919
  inputValue,
14124
14920
  isPreAppStart: false
14125
14921
  }, (spanInfo) => {
14126
- return self._handleReplayTransaction(inputValue, callback);
14922
+ return self._handleReplayTransaction(inputValue, actualCallback);
14127
14923
  });
14128
14924
  }
14129
14925
  });
@@ -14140,7 +14936,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14140
14936
  inputValue,
14141
14937
  isPreAppStart
14142
14938
  }, (spanInfo) => {
14143
- return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, callback);
14939
+ return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, actualCallback);
14144
14940
  });
14145
14941
  },
14146
14942
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14173,7 +14969,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14173
14969
  const argsArray = Array.from(args);
14174
14970
  const callbackIndex = argsArray.findIndex((arg) => typeof arg === "function");
14175
14971
  if (callbackIndex !== -1) {
14176
- const originalCallback = callback;
14972
+ const originalCallback = argsArray[callbackIndex];
14177
14973
  argsArray[callbackIndex] = function(err) {
14178
14974
  if (err) try {
14179
14975
  SpanUtils.endSpan(spanInfo.span, {
@@ -14202,7 +14998,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14202
14998
  callback(null);
14203
14999
  });
14204
15000
  }
14205
- _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$6) {
15001
+ _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, poolContext) {
14206
15002
  const self = this;
14207
15003
  if (callback) {
14208
15004
  const wrappedCallback = (error, connection) => {
@@ -14227,11 +15023,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14227
15023
  } });
14228
15024
  SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14229
15025
  }
14230
- return callback(error, connection);
15026
+ return import_src$23.context.bind(spanInfo.context, callback)(error, connection);
14231
15027
  };
14232
- return originalGetConnection.call(context$6, wrappedCallback);
15028
+ return originalGetConnection.call(poolContext, wrappedCallback);
14233
15029
  } else try {
14234
- const result = originalGetConnection.call(context$6);
15030
+ const result = originalGetConnection.call(poolContext);
14235
15031
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
14236
15032
  connected: true,
14237
15033
  hasConnection: true
@@ -14246,20 +15042,28 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14246
15042
  throw error;
14247
15043
  }
14248
15044
  }
14249
- _handleNoOpReplayGetConnection(callback) {
15045
+ _handleNoOpReplayGetConnection(pool, callback) {
14250
15046
  logger.debug(`[MysqlInstrumentation] Background getConnection detected, returning mock connection`);
14251
- const mockConnection = new TdMysqlConnectionMock(this, "pool");
15047
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", void 0, pool);
14252
15048
  if (callback) {
14253
- process.nextTick(() => callback(null, mockConnection));
15049
+ process.nextTick(() => {
15050
+ pool.emit("connection", mockConnection);
15051
+ pool.emit("acquire", mockConnection);
15052
+ callback(null, mockConnection);
15053
+ });
14254
15054
  return;
14255
15055
  }
14256
15056
  return mockConnection;
14257
15057
  }
14258
- _handleReplayPoolGetConnection(spanInfo, callback) {
15058
+ _handleReplayPoolGetConnection(pool, spanInfo, callback) {
14259
15059
  logger.debug(`[MysqlInstrumentation] Replaying MySQL Pool getConnection`);
14260
- const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo);
15060
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo, pool);
14261
15061
  if (callback) {
14262
- process.nextTick(() => callback(null, mockConnection));
15062
+ process.nextTick(() => {
15063
+ pool.emit("connection", mockConnection);
15064
+ pool.emit("acquire", mockConnection);
15065
+ callback(null, mockConnection);
15066
+ });
14263
15067
  return;
14264
15068
  }
14265
15069
  return mockConnection;
@@ -14492,6 +15296,122 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14492
15296
  });
14493
15297
  return readableStream;
14494
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
+ }
14495
15415
  _wrap(target, propertyName, wrapper) {
14496
15416
  wrap(target, propertyName, wrapper);
14497
15417
  }
@@ -19563,13 +20483,6 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19563
20483
  return originalHandleRequest.call(this, req, res, parsedUrl);
19564
20484
  }
19565
20485
  logger.debug(`[NextjsInstrumentation] Setting replay trace id`, replayTraceId);
19566
- if (self.replayHooks.extractShouldFetchEnvVars(req)) try {
19567
- const envVars = self.tuskDrift.requestEnvVarsSync(replayTraceId);
19568
- EnvVarTracker.setEnvVars(replayTraceId, envVars);
19569
- logger.debug(`[NextjsInstrumentation] Fetched env vars from CLI for trace ${replayTraceId}`);
19570
- } catch (error) {
19571
- logger.error(`[NextjsInstrumentation] Failed to fetch env vars from CLI:`, error);
19572
- }
19573
20486
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
19574
20487
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
19575
20488
  return import_src$11.context.with(ctxWithReplayTraceId, () => {
@@ -19724,10 +20637,8 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19724
20637
  decodedType: getDecodedType(outputValue.headers?.["content-type"] || "")
19725
20638
  },
19726
20639
  headers: { matchImportance: 0 }
19727
- },
19728
- metadata: { ENV_VARS: EnvVarTracker.getEnvVars(spanInfo.traceId) }
20640
+ }
19729
20641
  });
19730
- EnvVarTracker.clearEnvVars(spanInfo.traceId);
19731
20642
  const status = (capturedStatusCode || 200) >= 400 ? {
19732
20643
  code: import_src$11.SpanStatusCode.ERROR,
19733
20644
  message: `HTTP ${capturedStatusCode}`
@@ -19765,6 +20676,7 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19765
20676
  instrumentationName: self.INSTRUMENTATION_NAME,
19766
20677
  submoduleName: completeInputValue.method,
19767
20678
  inputValue: completeInputValue,
20679
+ environment: self.tuskDrift.getEnvironment(),
19768
20680
  outputValue,
19769
20681
  inputSchema,
19770
20682
  outputSchema,
@@ -24254,7 +25166,7 @@ var SpanTransformer = class SpanTransformer {
24254
25166
  * Return type is derived from protobuf schema but uses clean JSON.
24255
25167
  * We use JSON because serialized protobuf is extremely verbose and not readable.
24256
25168
  */
24257
- static transformSpanToCleanJSON(span) {
25169
+ static transformSpanToCleanJSON(span, environment) {
24258
25170
  const isRootSpan = !span.parentSpanId || span.kind === import_src$9.SpanKind.SERVER;
24259
25171
  const attributes = span.attributes;
24260
25172
  const packageName = SpanTransformer.extractPackageName(attributes);
@@ -24298,6 +25210,7 @@ var SpanTransformer = class SpanTransformer {
24298
25210
  instrumentationName,
24299
25211
  submoduleName: submoduleName || "",
24300
25212
  packageType: attributes[TdSpanAttributes.PACKAGE_TYPE] || void 0,
25213
+ environment,
24301
25214
  inputValue: inputData,
24302
25215
  outputValue: outputData,
24303
25216
  inputSchema,
@@ -24761,7 +25674,7 @@ var ApiSpanAdapter = class {
24761
25674
  const protoSpans = spans.map((span) => this.transformSpanToProtobuf(span));
24762
25675
  const request = {
24763
25676
  observableServiceId: this.observableServiceId,
24764
- environment: this.environment,
25677
+ environment: this.environment || "",
24765
25678
  sdkVersion: this.sdkVersion,
24766
25679
  sdkInstanceId: this.sdkInstanceId,
24767
25680
  spans: protoSpans
@@ -24788,6 +25701,7 @@ var ApiSpanAdapter = class {
24788
25701
  instrumentationName: cleanSpan.instrumentationName,
24789
25702
  submoduleName: cleanSpan.submoduleName,
24790
25703
  packageType: cleanSpan.packageType || PackageType.UNSPECIFIED,
25704
+ environment: this.environment,
24791
25705
  inputValue: toStruct(cleanSpan.inputValue),
24792
25706
  outputValue: toStruct(cleanSpan.outputValue),
24793
25707
  inputSchema: cleanSpan.inputSchema,
@@ -24813,12 +25727,12 @@ var ApiSpanAdapter = class {
24813
25727
  }
24814
25728
  mapSpanKind(kind) {
24815
25729
  switch (kind) {
24816
- case import_src$7.SpanKind.CLIENT: return SpanKind.CLIENT;
24817
- case import_src$7.SpanKind.SERVER: return SpanKind.SERVER;
24818
- case import_src$7.SpanKind.PRODUCER: return SpanKind.PRODUCER;
24819
- case import_src$7.SpanKind.CONSUMER: return SpanKind.CONSUMER;
24820
- case import_src$7.SpanKind.INTERNAL: return SpanKind.INTERNAL;
24821
- default: return SpanKind.UNSPECIFIED;
25730
+ case import_src$7.SpanKind.CLIENT: return SpanKind$1.CLIENT;
25731
+ case import_src$7.SpanKind.SERVER: return SpanKind$1.SERVER;
25732
+ case import_src$7.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
25733
+ case import_src$7.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
25734
+ case import_src$7.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
25735
+ default: return SpanKind$1.UNSPECIFIED;
24822
25736
  }
24823
25737
  }
24824
25738
  async shutdown() {
@@ -24833,6 +25747,7 @@ var TdSpanExporter = class {
24833
25747
  constructor(config) {
24834
25748
  this.adapters = [];
24835
25749
  this.mode = config.mode;
25750
+ this.environment = config.environment;
24836
25751
  this.setupDefaultAdapters(config);
24837
25752
  logger.debug(`TdSpanExporter initialized with ${this.adapters.length} adapter(s)`);
24838
25753
  }
@@ -24916,7 +25831,7 @@ var TdSpanExporter = class {
24916
25831
  return true;
24917
25832
  });
24918
25833
  logger.debug(`Filtered ${filteredSpansBasedOnLibraryName.length - filteredBlockedSpans.length} blocked/oversized span(s), ${filteredBlockedSpans.length} remaining`);
24919
- const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span));
25834
+ const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span, this.environment));
24920
25835
  if (this.adapters.length === 0) {
24921
25836
  logger.debug("No adapters configured");
24922
25837
  resultCallback({ code: import_src$5.ExportResultCode.SUCCESS });
@@ -32067,7 +32982,7 @@ var require_src = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/sdk-
32067
32982
  //#endregion
32068
32983
  //#region package.json
32069
32984
  var import_src$1 = /* @__PURE__ */ __toESM(require_src(), 1);
32070
- var version = "0.1.17";
32985
+ var version = "0.1.19";
32071
32986
 
32072
32987
  //#endregion
32073
32988
  //#region src/version.ts
@@ -32075,7 +32990,7 @@ const SDK_VERSION = version;
32075
32990
  const MIN_CLI_VERSION = "0.1.0";
32076
32991
 
32077
32992
  //#endregion
32078
- //#region node_modules/@use-tusk/drift-schemas/dist/communication-D4zqMBSI.js
32993
+ //#region node_modules/@use-tusk/drift-schemas/dist/communication-BY2KZhrg.js
32079
32994
  var import_commonjs = /* @__PURE__ */ __toESM(require_commonjs$1(), 1);
32080
32995
  var import_commonjs$1 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
32081
32996
  /**
@@ -33219,12 +34134,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33219
34134
  });
33220
34135
  await this.sendProtobufMessage(sdkMessage);
33221
34136
  }
33222
- getStackTrace() {
33223
- Error.stackTraceLimit = 100;
33224
- const s = (/* @__PURE__ */ new Error()).stack || "";
33225
- Error.stackTraceLimit = 10;
33226
- return s.split("\n").slice(2).filter((l) => !l.includes("ProtobufCommunicator")).join("\n");
33227
- }
33228
34137
  async requestMockAsync(mockRequest) {
33229
34138
  const requestId = this.generateRequestId();
33230
34139
  const cleanSpan = mockRequest.outboundSpan ? this.cleanSpan(mockRequest.outboundSpan) : void 0;
@@ -33257,7 +34166,7 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33257
34166
  /**
33258
34167
  * Generic synchronous request handler that spawns a child process.
33259
34168
  * @param sdkMessage The SDK message to send
33260
- * @param filePrefix Prefix for temporary files (e.g., 'envvar', 'mock')
34169
+ * @param filePrefix Prefix for temporary files (e.g., 'mock')
33261
34170
  * @param responseHandler Function to extract and return the desired response
33262
34171
  */
33263
34172
  executeSyncRequest(sdkMessage, filePrefix, responseHandler) {
@@ -33326,35 +34235,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33326
34235
  }
33327
34236
  }
33328
34237
  /**
33329
- * Request environment variables from CLI synchronously using a child process.
33330
- * This blocks the main thread, so it should be used carefully.
33331
- * Similar to requestMockSync but for environment variables.
33332
- */
33333
- requestEnvVarsSync(traceTestServerSpanId) {
33334
- const requestId = this.generateRequestId();
33335
- const envVarRequest = EnvVarRequest.create({ traceTestServerSpanId });
33336
- const sdkMessage = SDKMessage.create({
33337
- type: MessageType$1.ENV_VAR_REQUEST,
33338
- requestId,
33339
- payload: {
33340
- oneofKind: "envVarRequest",
33341
- envVarRequest
33342
- }
33343
- });
33344
- logger.debug(`[ProtobufCommunicator] Requesting env vars (sync) for trace: ${traceTestServerSpanId}`);
33345
- return this.executeSyncRequest(sdkMessage, "envvar", (cliMessage) => {
33346
- if (cliMessage.payload.oneofKind !== "envVarResponse") throw new Error(`Unexpected response type: ${cliMessage.type}`);
33347
- const envVarResponse = cliMessage.payload.envVarResponse;
33348
- if (!envVarResponse) throw new Error("No env var response received");
33349
- const envVars = {};
33350
- if (envVarResponse.envVars) Object.entries(envVarResponse.envVars).forEach(([key, value]) => {
33351
- envVars[key] = value;
33352
- });
33353
- logger.debug(`[ProtobufCommunicator] Received env vars (sync), count: ${Object.keys(envVars).length}`);
33354
- return envVars;
33355
- });
33356
- }
33357
- /**
33358
34238
  * This function uses a separate Node.js child process to communicate with the CLI over a socket.
33359
34239
  * The child process creates its own connection and event loop, allowing proper async socket handling.
33360
34240
  * The parent process blocks synchronously waiting for the child to complete.
@@ -33565,22 +34445,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33565
34445
  error: mockResponse.error || "Mock not found"
33566
34446
  });
33567
34447
  }
33568
- if (message.payload.oneofKind === "envVarResponse") {
33569
- const envVarResponse = message.payload.envVarResponse;
33570
- logger.debug(`[ProtobufCommunicator] Received env var response for requestId: ${requestId}`);
33571
- const pendingRequest = this.pendingRequests.get(requestId);
33572
- if (!pendingRequest) {
33573
- logger.warn("[ProtobufCommunicator] received env var response for unknown request:", requestId);
33574
- return;
33575
- }
33576
- this.pendingRequests.delete(requestId);
33577
- const envVars = {};
33578
- if (envVarResponse?.envVars) Object.entries(envVarResponse.envVars).forEach(([key, value]) => {
33579
- envVars[key] = value;
33580
- });
33581
- pendingRequest.resolve(envVars);
33582
- return;
33583
- }
33584
34448
  }
33585
34449
  /**
33586
34450
  * Extract response data from MockResponse
@@ -33880,10 +34744,6 @@ var TuskDriftCore = class TuskDriftCore {
33880
34744
  enabled: true,
33881
34745
  mode: this.mode
33882
34746
  });
33883
- new EnvInstrumentation({
33884
- enabled: this.config.recording?.enable_env_var_recording || false,
33885
- mode: this.mode
33886
- });
33887
34747
  new PostgresInstrumentation({
33888
34748
  enabled: true,
33889
34749
  mode: this.mode
@@ -33931,7 +34791,7 @@ var TuskDriftCore = class TuskDriftCore {
33931
34791
  observableServiceId: this.config.service?.id,
33932
34792
  apiKey: this.initParams.apiKey,
33933
34793
  tuskBackendBaseUrl: this.config.tusk_api?.url || "https://api.usetusk.ai",
33934
- environment: this.initParams.env || "unknown",
34794
+ environment: this.initParams.env,
33935
34795
  sdkVersion: SDK_VERSION,
33936
34796
  sdkInstanceId: this.generateSdkInstanceId()
33937
34797
  });
@@ -33949,6 +34809,34 @@ var TuskDriftCore = class TuskDriftCore {
33949
34809
  generateSdkInstanceId() {
33950
34810
  return `sdk-${OriginalGlobalUtils.getOriginalDate().getTime()}-${Math.random().toString(36).substr(2, 9)}`;
33951
34811
  }
34812
+ /**
34813
+ * Creates a pre-app-start span containing a snapshot of all environment variables.
34814
+ * Only runs in RECORD mode when env var recording is enabled.
34815
+ */
34816
+ createEnvVarsSnapshot() {
34817
+ if (this.mode !== TuskDriftMode.RECORD || !this.config.recording?.enable_env_var_recording) return;
34818
+ try {
34819
+ const envVarsSnapshot = {};
34820
+ for (const key of Object.keys(process.env)) envVarsSnapshot[key] = process.env[key];
34821
+ logger.debug(`Creating env vars snapshot with ${Object.keys(envVarsSnapshot).length} variables`);
34822
+ SpanUtils.createAndExecuteSpan(this.mode, () => {}, {
34823
+ name: "ENV_VARS_SNAPSHOT",
34824
+ kind: import_src.SpanKind.INTERNAL,
34825
+ packageName: "process.env",
34826
+ packageType: PackageType.UNSPECIFIED,
34827
+ instrumentationName: "TuskDriftCore",
34828
+ submodule: "env",
34829
+ inputValue: {},
34830
+ outputValue: { ENV_VARS: envVarsSnapshot },
34831
+ isPreAppStart: true
34832
+ }, (spanInfo) => {
34833
+ SpanUtils.endSpan(spanInfo.span, { code: import_src.SpanStatusCode.OK });
34834
+ logger.debug(`Env vars snapshot span created: ${spanInfo.spanId}`);
34835
+ });
34836
+ } catch (error) {
34837
+ logger.error("Failed to create env vars snapshot:", error);
34838
+ }
34839
+ }
33952
34840
  initialize(initParams) {
33953
34841
  initializeGlobalLogger({
33954
34842
  logLevel: initParams.logLevel || "info",
@@ -34025,6 +34913,7 @@ var TuskDriftCore = class TuskDriftCore {
34025
34913
  logger.debug(`Base directory: ${baseDirectory}`);
34026
34914
  this.registerDefaultInstrumentations();
34027
34915
  this.initializeTracing({ baseDirectory });
34916
+ this.createEnvVarsSnapshot();
34028
34917
  this.initialized = true;
34029
34918
  logger.info("SDK initialized successfully");
34030
34919
  }
@@ -34088,30 +34977,6 @@ var TuskDriftCore = class TuskDriftCore {
34088
34977
  };
34089
34978
  }
34090
34979
  }
34091
- /**
34092
- * Request environment variables from CLI for a specific trace (synchronously).
34093
- * This blocks the main thread, so it should be used carefully.
34094
- */
34095
- requestEnvVarsSync(traceTestServerSpanId) {
34096
- if (!this.isConnectedWithCLI) {
34097
- logger.error("Requesting sync env vars but CLI is not ready yet");
34098
- throw new Error("Requesting sync env vars but CLI is not ready yet");
34099
- }
34100
- if (!this.communicator || this.mode !== TuskDriftMode.REPLAY) {
34101
- logger.debug("Cannot request env vars: not in replay mode or no CLI connection");
34102
- return {};
34103
- }
34104
- try {
34105
- logger.debug(`Requesting env vars (sync) for trace: ${traceTestServerSpanId}`);
34106
- const envVars = this.communicator.requestEnvVarsSync(traceTestServerSpanId);
34107
- logger.debug(`Received env vars from CLI, count: ${Object.keys(envVars).length}`);
34108
- logger.debug(`First 10 env vars: ${JSON.stringify(Object.keys(envVars).slice(0, 10), null, 2)}`);
34109
- return envVars;
34110
- } catch (error) {
34111
- logger.error(`[TuskDrift] Error requesting env vars from CLI:`, error);
34112
- return {};
34113
- }
34114
- }
34115
34980
  requestMockSync(mockRequest) {
34116
34981
  if (!this.isConnectedWithCLI) {
34117
34982
  logger.error("Requesting sync mock but CLI is not ready yet");
@@ -34163,6 +35028,9 @@ var TuskDriftCore = class TuskDriftCore {
34163
35028
  getInitParams() {
34164
35029
  return this.initParams;
34165
35030
  }
35031
+ getEnvironment() {
35032
+ return this.initParams.env;
35033
+ }
34166
35034
  getTracer() {
34167
35035
  return import_src.trace.getTracer(TD_INSTRUMENTATION_LIBRARY_NAME);
34168
35036
  }