@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.js CHANGED
@@ -4978,31 +4978,31 @@ var require_SamplingResult = /* @__PURE__ */ __commonJS({ "node_modules/@opentel
4978
4978
  var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/span_kind.js": ((exports) => {
4979
4979
  Object.defineProperty(exports, "__esModule", { value: true });
4980
4980
  exports.SpanKind = void 0;
4981
- (function(SpanKind$24) {
4981
+ (function(SpanKind$26) {
4982
4982
  /** Default value. Indicates that the span is used internally. */
4983
- SpanKind$24[SpanKind$24["INTERNAL"] = 0] = "INTERNAL";
4983
+ SpanKind$26[SpanKind$26["INTERNAL"] = 0] = "INTERNAL";
4984
4984
  /**
4985
4985
  * Indicates that the span covers server-side handling of an RPC or other
4986
4986
  * remote request.
4987
4987
  */
4988
- SpanKind$24[SpanKind$24["SERVER"] = 1] = "SERVER";
4988
+ SpanKind$26[SpanKind$26["SERVER"] = 1] = "SERVER";
4989
4989
  /**
4990
4990
  * Indicates that the span covers the client-side wrapper around an RPC or
4991
4991
  * other remote request.
4992
4992
  */
4993
- SpanKind$24[SpanKind$24["CLIENT"] = 2] = "CLIENT";
4993
+ SpanKind$26[SpanKind$26["CLIENT"] = 2] = "CLIENT";
4994
4994
  /**
4995
4995
  * Indicates that the span describes producer sending a message to a
4996
4996
  * broker. Unlike client and server, there is no direct critical path latency
4997
4997
  * relationship between producer and consumer spans.
4998
4998
  */
4999
- SpanKind$24[SpanKind$24["PRODUCER"] = 3] = "PRODUCER";
4999
+ SpanKind$26[SpanKind$26["PRODUCER"] = 3] = "PRODUCER";
5000
5000
  /**
5001
5001
  * Indicates that the span describes consumer receiving a message from a
5002
5002
  * broker. Unlike client and server, there is no direct critical path latency
5003
5003
  * relationship between producer and consumer spans.
5004
5004
  */
5005
- SpanKind$24[SpanKind$24["CONSUMER"] = 4] = "CONSUMER";
5005
+ SpanKind$26[SpanKind$26["CONSUMER"] = 4] = "CONSUMER";
5006
5006
  })(exports.SpanKind || (exports.SpanKind = {}));
5007
5007
  }) });
5008
5008
 
@@ -5011,20 +5011,20 @@ var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetr
5011
5011
  var require_status = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/status.js": ((exports) => {
5012
5012
  Object.defineProperty(exports, "__esModule", { value: true });
5013
5013
  exports.SpanStatusCode = void 0;
5014
- (function(SpanStatusCode$13) {
5014
+ (function(SpanStatusCode$15) {
5015
5015
  /**
5016
5016
  * The default status.
5017
5017
  */
5018
- SpanStatusCode$13[SpanStatusCode$13["UNSET"] = 0] = "UNSET";
5018
+ SpanStatusCode$15[SpanStatusCode$15["UNSET"] = 0] = "UNSET";
5019
5019
  /**
5020
5020
  * The operation has been validated by an Application developer or
5021
5021
  * Operator to have completed successfully.
5022
5022
  */
5023
- SpanStatusCode$13[SpanStatusCode$13["OK"] = 1] = "OK";
5023
+ SpanStatusCode$15[SpanStatusCode$15["OK"] = 1] = "OK";
5024
5024
  /**
5025
5025
  * The operation contains an error.
5026
5026
  */
5027
- SpanStatusCode$13[SpanStatusCode$13["ERROR"] = 2] = "ERROR";
5027
+ SpanStatusCode$15[SpanStatusCode$15["ERROR"] = 2] = "ERROR";
5028
5028
  })(exports.SpanStatusCode || (exports.SpanStatusCode = {}));
5029
5029
  }) });
5030
5030
 
@@ -5673,7 +5673,7 @@ var require_src$7 = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/ap
5673
5673
 
5674
5674
  //#endregion
5675
5675
  //#region node_modules/@use-tusk/drift-schemas/dist/duration-B3fwb4jB.js
5676
- var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
5676
+ var import_src$35 = /* @__PURE__ */ __toESM(require_src$7(), 1);
5677
5677
  var import_commonjs$9 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
5678
5678
  var Duration$Type = class extends import_commonjs$9.MessageType {
5679
5679
  constructor() {
@@ -6198,7 +6198,7 @@ var JsonSchema$Type = class extends import_commonjs$7.MessageType {
6198
6198
  const JsonSchema = new JsonSchema$Type();
6199
6199
 
6200
6200
  //#endregion
6201
- //#region node_modules/@use-tusk/drift-schemas/dist/span-BZ89ct3l.js
6201
+ //#region node_modules/@use-tusk/drift-schemas/dist/span-CsBrzhI_.js
6202
6202
  var import_commonjs$6 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
6203
6203
  /**
6204
6204
  * Package type classification enum
@@ -6284,7 +6284,7 @@ let PackageType = /* @__PURE__ */ function(PackageType$1) {
6284
6284
  *
6285
6285
  * @generated from protobuf enum tusk.drift.core.v1.SpanKind
6286
6286
  */
6287
- let SpanKind = /* @__PURE__ */ function(SpanKind$1$1) {
6287
+ let SpanKind$1 = /* @__PURE__ */ function(SpanKind$1$1) {
6288
6288
  /**
6289
6289
  * @generated from protobuf enum value: SPAN_KIND_UNSPECIFIED = 0;
6290
6290
  */
@@ -6454,7 +6454,7 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6454
6454
  kind: "enum",
6455
6455
  T: () => [
6456
6456
  "tusk.drift.core.v1.SpanKind",
6457
- SpanKind,
6457
+ SpanKind$1,
6458
6458
  "SPAN_KIND_"
6459
6459
  ]
6460
6460
  },
@@ -6493,6 +6493,13 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6493
6493
  name: "metadata",
6494
6494
  kind: "message",
6495
6495
  T: () => Struct
6496
+ },
6497
+ {
6498
+ no: 24,
6499
+ name: "environment",
6500
+ kind: "scalar",
6501
+ opt: true,
6502
+ T: 9
6496
6503
  }
6497
6504
  ]);
6498
6505
  }
@@ -6590,6 +6597,9 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6590
6597
  case 23:
6591
6598
  message.metadata = Struct.internalBinaryRead(reader, reader.uint32(), options, message.metadata);
6592
6599
  break;
6600
+ case 24:
6601
+ message.environment = reader.string();
6602
+ break;
6593
6603
  default:
6594
6604
  let u = options.readUnknownField;
6595
6605
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -6623,6 +6633,7 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6623
6633
  if (message.duration) Duration.internalBinaryWrite(message.duration, writer.tag(21, import_commonjs$6.WireType.LengthDelimited).fork(), options).join();
6624
6634
  if (message.isRootSpan !== false) writer.tag(22, import_commonjs$6.WireType.Varint).bool(message.isRootSpan);
6625
6635
  if (message.metadata) Struct.internalBinaryWrite(message.metadata, writer.tag(23, import_commonjs$6.WireType.LengthDelimited).fork(), options).join();
6636
+ if (message.environment !== void 0) writer.tag(24, import_commonjs$6.WireType.LengthDelimited).string(message.environment);
6626
6637
  let u = options.writeUnknownFields;
6627
6638
  if (u !== false) (u == true ? import_commonjs$6.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
6628
6639
  return writer;
@@ -6986,12 +6997,12 @@ const Trace = new Trace$Type();
6986
6997
  const toStruct = (obj) => obj ? objectToProtobufStruct(obj) : void 0;
6987
6998
  const mapOtToPb = (k) => {
6988
6999
  switch (k) {
6989
- case import_src$34.SpanKind.INTERNAL: return SpanKind.INTERNAL;
6990
- case import_src$34.SpanKind.SERVER: return SpanKind.SERVER;
6991
- case import_src$34.SpanKind.CLIENT: return SpanKind.CLIENT;
6992
- case import_src$34.SpanKind.PRODUCER: return SpanKind.PRODUCER;
6993
- case import_src$34.SpanKind.CONSUMER: return SpanKind.CONSUMER;
6994
- default: return SpanKind.UNSPECIFIED;
7000
+ case import_src$35.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
7001
+ case import_src$35.SpanKind.SERVER: return SpanKind$1.SERVER;
7002
+ case import_src$35.SpanKind.CLIENT: return SpanKind$1.CLIENT;
7003
+ case import_src$35.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
7004
+ case import_src$35.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
7005
+ default: return SpanKind$1.UNSPECIFIED;
6995
7006
  }
6996
7007
  };
6997
7008
  /**
@@ -7394,13 +7405,13 @@ var TdInstrumentationNodeModule = class {
7394
7405
 
7395
7406
  //#endregion
7396
7407
  //#region src/core/types.ts
7397
- var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7408
+ var import_src$34 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7398
7409
  const TD_INSTRUMENTATION_LIBRARY_NAME = "tusk-drift-sdk";
7399
- const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.replayTraceId");
7400
- const SPAN_KIND_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.spanKind");
7401
- const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.isPreAppStart");
7402
- const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.stopRecordingChildSpans");
7403
- const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$33.createContextKey)("td.callingLibrary");
7410
+ const REPLAY_TRACE_ID_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.replayTraceId");
7411
+ const SPAN_KIND_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.spanKind");
7412
+ const IS_PRE_APP_START_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.isPreAppStart");
7413
+ const STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.stopRecordingChildSpans");
7414
+ const CALLING_LIBRARY_CONTEXT_KEY = (0, import_src$34.createContextKey)("td.callingLibrary");
7404
7415
  let TdSpanAttributes = /* @__PURE__ */ function(TdSpanAttributes$1) {
7405
7416
  /**
7406
7417
  * Presentational information:
@@ -7512,7 +7523,7 @@ TraceBlockingManager.instance = null;
7512
7523
 
7513
7524
  //#endregion
7514
7525
  //#region src/core/tracing/SpanUtils.ts
7515
- var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7526
+ var import_src$33 = /* @__PURE__ */ __toESM(require_src$7(), 1);
7516
7527
  var SpanUtils = class SpanUtils {
7517
7528
  /**
7518
7529
  * Creates a new span and returns span info including trace ID and span ID
@@ -7520,8 +7531,8 @@ var SpanUtils = class SpanUtils {
7520
7531
  static createSpan(options) {
7521
7532
  try {
7522
7533
  const tracer = TuskDriftCore.getInstance().getTracer();
7523
- const parentContext = options.parentContext || import_src$32.context.active();
7524
- const activeSpan = import_src$32.trace.getSpan(parentContext);
7534
+ const parentContext = options.parentContext || import_src$33.context.active();
7535
+ const activeSpan = import_src$33.trace.getSpan(parentContext);
7525
7536
  if (activeSpan) {
7526
7537
  const parentTraceId = activeSpan.spanContext().traceId;
7527
7538
  if (TraceBlockingManager.getInstance().isTraceBlocked(parentTraceId)) {
@@ -7530,11 +7541,11 @@ var SpanUtils = class SpanUtils {
7530
7541
  }
7531
7542
  }
7532
7543
  const span = tracer.startSpan(options.name, {
7533
- kind: options.kind || import_src$32.SpanKind.CLIENT,
7544
+ kind: options.kind || import_src$33.SpanKind.CLIENT,
7534
7545
  attributes: options.attributes || {}
7535
7546
  }, parentContext);
7536
7547
  const spanContext = span.spanContext();
7537
- const newContext = import_src$32.trace.setSpan(parentContext, span).setValue(SPAN_KIND_CONTEXT_KEY, options.kind).setValue(IS_PRE_APP_START_CONTEXT_KEY, options.isPreAppStart);
7548
+ const newContext = import_src$33.trace.setSpan(parentContext, span).setValue(SPAN_KIND_CONTEXT_KEY, options.kind).setValue(IS_PRE_APP_START_CONTEXT_KEY, options.isPreAppStart);
7538
7549
  return {
7539
7550
  traceId: spanContext.traceId,
7540
7551
  spanId: spanContext.spanId,
@@ -7551,7 +7562,7 @@ var SpanUtils = class SpanUtils {
7551
7562
  * Executes a function within a span context
7552
7563
  */
7553
7564
  static withSpan(spanInfo, fn) {
7554
- return import_src$32.context.with(spanInfo.context, fn);
7565
+ return import_src$33.context.with(spanInfo.context, fn);
7555
7566
  }
7556
7567
  /**
7557
7568
  * Execute a function within a properly configured span
@@ -7568,14 +7579,14 @@ var SpanUtils = class SpanUtils {
7568
7579
  * @returns The result of the function execution
7569
7580
  */
7570
7581
  static createAndExecuteSpan(mode, originalFunctionCall, options, fn) {
7571
- const spanContext = import_src$32.trace.getActiveSpan()?.spanContext();
7582
+ const spanContext = import_src$33.trace.getActiveSpan()?.spanContext();
7572
7583
  if (spanContext) {
7573
- if (import_src$32.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
7584
+ if (import_src$33.context.active().getValue(STOP_RECORDING_CHILD_SPANS_CONTEXT_KEY)) {
7574
7585
  logger.debug(`[SpanUtils] Stopping recording of child spans for span ${spanContext.spanId}, packageName: ${options.packageName}, instrumentationName: ${options.instrumentationName}`);
7575
7586
  return originalFunctionCall();
7576
7587
  }
7577
7588
  }
7578
- const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
7589
+ const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, outputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
7579
7590
  let spanInfo = null;
7580
7591
  try {
7581
7592
  spanInfo = SpanUtils.createSpan({
@@ -7589,6 +7600,7 @@ var SpanUtils = class SpanUtils {
7589
7600
  [TdSpanAttributes.INSTRUMENTATION_NAME]: instrumentationName,
7590
7601
  [TdSpanAttributes.PACKAGE_TYPE]: packageType,
7591
7602
  [TdSpanAttributes.INPUT_VALUE]: createSpanInputValue(inputValue),
7603
+ ...outputValue && { [TdSpanAttributes.OUTPUT_VALUE]: JSON.stringify(outputValue) },
7592
7604
  [TdSpanAttributes.IS_PRE_APP_START]: isPreAppStart,
7593
7605
  ...inputSchemaMerges && { [TdSpanAttributes.INPUT_SCHEMA_MERGES]: JSON.stringify(inputSchemaMerges) },
7594
7606
  ...metadata && { [TdSpanAttributes.METADATA]: JSON.stringify(metadata) }
@@ -7608,15 +7620,15 @@ var SpanUtils = class SpanUtils {
7608
7620
  */
7609
7621
  static getCurrentSpanInfo() {
7610
7622
  try {
7611
- const activeSpan = import_src$32.trace.getActiveSpan();
7623
+ const activeSpan = import_src$33.trace.getActiveSpan();
7612
7624
  if (!activeSpan) return null;
7613
7625
  const spanContext = activeSpan.spanContext();
7614
7626
  return {
7615
7627
  traceId: spanContext.traceId,
7616
7628
  spanId: spanContext.spanId,
7617
7629
  span: activeSpan,
7618
- context: import_src$32.context.active(),
7619
- isPreAppStart: import_src$32.context.active().getValue(IS_PRE_APP_START_CONTEXT_KEY)
7630
+ context: import_src$33.context.active(),
7631
+ isPreAppStart: import_src$33.context.active().getValue(IS_PRE_APP_START_CONTEXT_KEY)
7620
7632
  };
7621
7633
  } catch (error) {
7622
7634
  logger.error("SpanUtils error getting current span info:", error);
@@ -7680,7 +7692,7 @@ var SpanUtils = class SpanUtils {
7680
7692
  }
7681
7693
  static setCurrentReplayTraceId(replayTraceId) {
7682
7694
  try {
7683
- return import_src$32.context.active().setValue(REPLAY_TRACE_ID_CONTEXT_KEY, replayTraceId);
7695
+ return import_src$33.context.active().setValue(REPLAY_TRACE_ID_CONTEXT_KEY, replayTraceId);
7684
7696
  } catch (error) {
7685
7697
  logger.error("SpanUtils error setting current replay trace id:", error);
7686
7698
  return null;
@@ -7691,7 +7703,7 @@ var SpanUtils = class SpanUtils {
7691
7703
  */
7692
7704
  static getCurrentReplayTraceId() {
7693
7705
  try {
7694
- return import_src$32.context.active().getValue(REPLAY_TRACE_ID_CONTEXT_KEY);
7706
+ return import_src$33.context.active().getValue(REPLAY_TRACE_ID_CONTEXT_KEY);
7695
7707
  } catch (error) {
7696
7708
  logger.error("SpanUtils error getting current replay trace id:", error);
7697
7709
  return null;
@@ -7955,30 +7967,6 @@ var TdHttpMockSocket = class extends EventEmitter {
7955
7967
  }
7956
7968
  };
7957
7969
 
7958
- //#endregion
7959
- //#region src/instrumentation/core/trackers/EnvVarTracker.ts
7960
- var EnvVarTracker = class {
7961
- static setEnvVar({ traceId, key, value }) {
7962
- this.envVars.set(traceId, {
7963
- ...this.envVars.get(traceId) || {},
7964
- [key]: value
7965
- });
7966
- }
7967
- static setEnvVars(traceId, envVars) {
7968
- this.envVars.set(traceId, envVars);
7969
- }
7970
- static getEnvVar(traceId, key) {
7971
- return this.envVars.get(traceId)?.[key];
7972
- }
7973
- static getEnvVars(traceId) {
7974
- return this.envVars.get(traceId);
7975
- }
7976
- static clearEnvVars(traceId) {
7977
- this.envVars.delete(traceId);
7978
- }
7979
- };
7980
- EnvVarTracker.envVars = /* @__PURE__ */ new Map();
7981
-
7982
7970
  //#endregion
7983
7971
  //#region src/instrumentation/core/trackers/DateTracker.ts
7984
7972
  /**
@@ -8279,6 +8267,7 @@ function convertMockRequestDataToCleanSpanData(mockRequestData, tuskDrift, input
8279
8267
  return {
8280
8268
  ...mockRequestData,
8281
8269
  parentSpanId: "",
8270
+ environment: tuskDrift.getEnvironment(),
8282
8271
  inputValueHash,
8283
8272
  inputSchema,
8284
8273
  inputSchemaHash,
@@ -8363,7 +8352,7 @@ function findMockResponseSync({ mockRequestData, tuskDrift, inputValueSchemaMerg
8363
8352
 
8364
8353
  //#endregion
8365
8354
  //#region src/instrumentation/libraries/http/mocks/TdMockClientRequest.ts
8366
- var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8355
+ var import_src$32 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8367
8356
  let ClientRequest;
8368
8357
  /**
8369
8358
  * Mock ClientRequest implementation for Tusk Drift HTTP replay
@@ -8534,7 +8523,7 @@ var TdMockClientRequest = class TdMockClientRequest extends EventEmitter {
8534
8523
  instrumentationName: this.INSTRUMENTATION_NAME,
8535
8524
  submoduleName: rawInputValue.method,
8536
8525
  inputValue,
8537
- kind: import_src$31.SpanKind.CLIENT,
8526
+ kind: import_src$32.SpanKind.CLIENT,
8538
8527
  stackTrace: this.stackTrace
8539
8528
  },
8540
8529
  tuskDrift: this.tuskDrift,
@@ -8675,13 +8664,6 @@ var HttpReplayHooks = class {
8675
8664
  return traceIdHeader ? String(traceIdHeader) : null;
8676
8665
  }
8677
8666
  /**
8678
- * Check if we should fetch env vars from CLI
8679
- */
8680
- extractShouldFetchEnvVars(req) {
8681
- const fetchHeader = req.headers["x-td-fetch-env-vars"] || req.headers["X-TD-FETCH-ENV-VARS"];
8682
- return fetchHeader === "true" || fetchHeader === true;
8683
- }
8684
- /**
8685
8667
  * Handle outbound HTTP requests in replay mode
8686
8668
  * Uses TdMockClientRequest for simplified mocking approach
8687
8669
  */
@@ -8711,7 +8693,7 @@ var HttpReplayHooks = class {
8711
8693
 
8712
8694
  //#endregion
8713
8695
  //#region src/instrumentation/core/utils/modeUtils.ts
8714
- var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8696
+ var import_src$31 = /* @__PURE__ */ __toESM(require_src$7(), 1);
8715
8697
  /**
8716
8698
  * Utility function that abstracts the common record mode pattern of checking for current span context
8717
8699
  * and deciding whether to execute record mode logic or just call the original function.
@@ -8732,7 +8714,7 @@ function handleRecordMode({ originalFunctionCall, recordModeHandler, spanKind })
8732
8714
  return originalFunctionCall();
8733
8715
  }
8734
8716
  if (!isAppReady) return recordModeHandler({ isPreAppStart: true });
8735
- if (!currentSpanInfo && spanKind !== import_src$30.SpanKind.SERVER || currentSpanInfo?.isPreAppStart) return originalFunctionCall();
8717
+ if (!currentSpanInfo && spanKind !== import_src$31.SpanKind.SERVER || currentSpanInfo?.isPreAppStart) return originalFunctionCall();
8736
8718
  else return recordModeHandler({ isPreAppStart: false });
8737
8719
  }
8738
8720
  /**
@@ -9970,7 +9952,7 @@ var require_commonjs$1 = /* @__PURE__ */ __commonJS({ "node_modules/@protobuf-ts
9970
9952
  }) });
9971
9953
 
9972
9954
  //#endregion
9973
- //#region node_modules/@use-tusk/drift-schemas/dist/span_export_service-XwF6hpEK.js
9955
+ //#region node_modules/@use-tusk/drift-schemas/dist/span_export_service-CmkFvTqD.js
9974
9956
  var import_commonjs$4 = /* @__PURE__ */ __toESM(require_commonjs$1(), 1);
9975
9957
  var import_commonjs$5 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
9976
9958
  var ExportSpansRequest$Type = class extends import_commonjs$5.MessageType {
@@ -10212,7 +10194,7 @@ function captureStackTrace(excludeClassNames = []) {
10212
10194
 
10213
10195
  //#endregion
10214
10196
  //#region src/instrumentation/libraries/http/HttpTransformEngine.ts
10215
- var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10197
+ var import_src$30 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10216
10198
  /**
10217
10199
  * Creates an empty HttpClientInputValue object for dropped spans
10218
10200
  */
@@ -10265,7 +10247,7 @@ var HttpTransformEngine = class {
10265
10247
  const testSpan = {
10266
10248
  traceId: "",
10267
10249
  spanId: "",
10268
- kind: import_src$29.SpanKind.SERVER,
10250
+ kind: import_src$30.SpanKind.SERVER,
10269
10251
  protocol: "http",
10270
10252
  inputValue: {
10271
10253
  method,
@@ -10288,7 +10270,7 @@ var HttpTransformEngine = class {
10288
10270
  const testSpan = {
10289
10271
  traceId: "",
10290
10272
  spanId: "",
10291
- kind: import_src$29.SpanKind.CLIENT,
10273
+ kind: import_src$30.SpanKind.CLIENT,
10292
10274
  protocol: inputValue.protocol || "http",
10293
10275
  inputValue: clonedInputValue
10294
10276
  };
@@ -10315,8 +10297,8 @@ var HttpTransformEngine = class {
10315
10297
  const matcherFunction = this.compileMatcher(matcher);
10316
10298
  if (action.type === "drop") return (span) => {
10317
10299
  if (!matcherFunction(span)) return;
10318
- if (span.inputValue) span.inputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10319
- if (span.outputValue) span.outputValue = span.kind === import_src$29.SpanKind.CLIENT ? createEmptyClientOutputValue() : createEmptyServerOutputValue();
10300
+ if (span.inputValue) span.inputValue = span.kind === import_src$30.SpanKind.CLIENT ? createEmptyClientInputValue(span.protocol) : createEmptyServerInputValue();
10301
+ if (span.outputValue) span.outputValue = span.kind === import_src$30.SpanKind.CLIENT ? createEmptyClientOutputValue() : createEmptyServerOutputValue();
10320
10302
  return {
10321
10303
  type: "drop",
10322
10304
  field: "entire_span",
@@ -10346,8 +10328,8 @@ var HttpTransformEngine = class {
10346
10328
  }
10347
10329
  compileMatcher(matcher) {
10348
10330
  const checks = [];
10349
- if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$29.SpanKind.CLIENT);
10350
- else if (matcher.direction === "inbound") checks.push((span) => span.kind === import_src$29.SpanKind.SERVER);
10331
+ if (matcher.direction === "outbound") checks.push((span) => span.kind === import_src$30.SpanKind.CLIENT);
10332
+ else if (matcher.direction === "inbound") checks.push((span) => span.kind === import_src$30.SpanKind.SERVER);
10351
10333
  if (matcher.method) if (matcher.method.length === 0) {} else {
10352
10334
  const methods = matcher.method.map((method) => method.toUpperCase());
10353
10335
  checks.push((span) => {
@@ -10575,7 +10557,7 @@ var HttpTransformEngine = class {
10575
10557
 
10576
10558
  //#endregion
10577
10559
  //#region src/instrumentation/libraries/http/Instrumentation.ts
10578
- var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10560
+ var import_src$29 = /* @__PURE__ */ __toESM(require_src$7(), 1);
10579
10561
  var HttpInstrumentation = class extends TdInstrumentationBase {
10580
10562
  constructor(config) {
10581
10563
  super("http", config);
@@ -10660,19 +10642,12 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10660
10642
  return originalHandler.call(this);
10661
10643
  }
10662
10644
  logger.debug(`[HttpInstrumentation] Setting replay trace id`, replayTraceId);
10663
- if (this.replayHooks.extractShouldFetchEnvVars(req)) try {
10664
- const envVars = this.tuskDrift.requestEnvVarsSync(replayTraceId);
10665
- EnvVarTracker.setEnvVars(replayTraceId, envVars);
10666
- logger.debug(`[HttpInstrumentation] Fetched env vars from CLI for trace ${replayTraceId}`);
10667
- } catch (error) {
10668
- logger.error(`[HttpInstrumentation] Failed to fetch env vars from CLI:`, error);
10669
- }
10670
10645
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
10671
10646
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
10672
- return import_src$28.context.with(ctxWithReplayTraceId, () => {
10647
+ return import_src$29.context.with(ctxWithReplayTraceId, () => {
10673
10648
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10674
10649
  name: `${target}`,
10675
- kind: import_src$28.SpanKind.SERVER,
10650
+ kind: import_src$29.SpanKind.SERVER,
10676
10651
  packageName: spanProtocol,
10677
10652
  submodule: method,
10678
10653
  packageType: PackageType.HTTP,
@@ -10717,7 +10692,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10717
10692
  logger.debug(`[HttpInstrumentation] Http inbound request arriving, inputValue: ${JSON.stringify(inputValue)}`);
10718
10693
  return SpanUtils.createAndExecuteSpan(this.mode, () => originalHandler.call(this), {
10719
10694
  name: `${target}`,
10720
- kind: import_src$28.SpanKind.SERVER,
10695
+ kind: import_src$29.SpanKind.SERVER,
10721
10696
  packageName: spanProtocol,
10722
10697
  packageType: PackageType.HTTP,
10723
10698
  submodule: method,
@@ -10737,7 +10712,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10737
10712
  });
10738
10713
  });
10739
10714
  },
10740
- spanKind: import_src$28.SpanKind.SERVER
10715
+ spanKind: import_src$29.SpanKind.SERVER
10741
10716
  });
10742
10717
  } else return originalHandler.call(this);
10743
10718
  }
@@ -10754,8 +10729,8 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10754
10729
  _handleInboundRequestInSpan({ req, res, originalHandler, spanInfo, inputValue, schemaMerges, protocol }) {
10755
10730
  const self = this;
10756
10731
  const spanProtocol = this._normalizeProtocol(protocol, "http");
10757
- import_src$28.context.bind(spanInfo.context, req);
10758
- import_src$28.context.bind(spanInfo.context, res);
10732
+ import_src$29.context.bind(spanInfo.context, req);
10733
+ import_src$29.context.bind(spanInfo.context, res);
10759
10734
  let completeInputValue = inputValue;
10760
10735
  this._captureServerRequestBody(req, spanInfo, inputValue, schemaMerges, (updatedInputValue) => {
10761
10736
  completeInputValue = updatedInputValue;
@@ -10793,7 +10768,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10793
10768
  const spanData = {
10794
10769
  traceId: spanInfo.traceId,
10795
10770
  spanId: spanInfo.spanId,
10796
- kind: import_src$28.SpanKind.SERVER,
10771
+ kind: import_src$29.SpanKind.SERVER,
10797
10772
  protocol: spanProtocol,
10798
10773
  inputValue: completeInputValue,
10799
10774
  outputValue
@@ -10809,14 +10784,12 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10809
10784
  },
10810
10785
  headers: { matchImportance: 0 }
10811
10786
  },
10812
- metadata: { ENV_VARS: EnvVarTracker.getEnvVars(spanInfo.traceId) },
10813
10787
  ...spanData.transformMetadata && { transformMetadata: spanData.transformMetadata }
10814
10788
  });
10815
- EnvVarTracker.clearEnvVars(spanInfo.traceId);
10816
10789
  const status = statusCode >= 400 ? {
10817
- code: import_src$28.SpanStatusCode.ERROR,
10790
+ code: import_src$29.SpanStatusCode.ERROR,
10818
10791
  message: `HTTP ${statusCode}`
10819
- } : { code: import_src$28.SpanStatusCode.OK };
10792
+ } : { code: import_src$29.SpanStatusCode.OK };
10820
10793
  SpanUtils.setStatus(spanInfo.span, status);
10821
10794
  const decodedType = getDecodedType(outputValue.headers?.["content-type"] || "");
10822
10795
  if (decodedType && !ACCEPTABLE_CONTENT_TYPES.has(decodedType)) {
@@ -10858,6 +10831,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10858
10831
  instrumentationName: "HttpInstrumentation",
10859
10832
  submoduleName: completeInputValue.method || inputValue.method,
10860
10833
  inputValue: completeInputValue,
10834
+ environment: self.tuskDrift.getEnvironment(),
10861
10835
  outputValue,
10862
10836
  inputSchema,
10863
10837
  outputSchema,
@@ -10865,7 +10839,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10865
10839
  outputSchemaHash: JsonSchemaHelper.generateDeterministicHash(outputSchema),
10866
10840
  inputValueHash,
10867
10841
  outputValueHash,
10868
- kind: import_src$28.SpanKind.SERVER,
10842
+ kind: import_src$29.SpanKind.SERVER,
10869
10843
  packageType: PackageType.HTTP,
10870
10844
  status: {
10871
10845
  code: statusCode >= 400 ? StatusCode.ERROR : StatusCode.OK,
@@ -10894,7 +10868,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10894
10868
  try {
10895
10869
  logger.debug(`[HttpInstrumentation] Server request error: ${error.message} (${SpanUtils.getTraceInfo()})`);
10896
10870
  SpanUtils.endSpan(spanInfo.span, {
10897
- code: import_src$28.SpanStatusCode.ERROR,
10871
+ code: import_src$29.SpanStatusCode.ERROR,
10898
10872
  message: error.message
10899
10873
  });
10900
10874
  } catch (error$1) {
@@ -10905,7 +10879,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10905
10879
  try {
10906
10880
  logger.debug(`[HttpInstrumentation] Server response 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) {
@@ -11110,7 +11084,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11110
11084
  inputValue: completeInputValue
11111
11085
  });
11112
11086
  SpanUtils.endSpan(spanInfo.span, {
11113
- code: import_src$28.SpanStatusCode.ERROR,
11087
+ code: import_src$29.SpanStatusCode.ERROR,
11114
11088
  message: error.message
11115
11089
  });
11116
11090
  } catch (error$1) {
@@ -11127,7 +11101,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11127
11101
  const spanData = {
11128
11102
  traceId: spanInfo.traceId,
11129
11103
  spanId: spanInfo.spanId,
11130
- kind: import_src$28.SpanKind.CLIENT,
11104
+ kind: import_src$29.SpanKind.CLIENT,
11131
11105
  protocol: normalizedProtocol,
11132
11106
  inputValue,
11133
11107
  outputValue
@@ -11140,9 +11114,9 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11140
11114
  transformMetadata: spanData.transformMetadata ? spanData.transformMetadata : void 0
11141
11115
  });
11142
11116
  const status = statusCode >= 400 ? {
11143
- code: import_src$28.SpanStatusCode.ERROR,
11117
+ code: import_src$29.SpanStatusCode.ERROR,
11144
11118
  message: `HTTP ${statusCode}`
11145
- } : { code: import_src$28.SpanStatusCode.OK };
11119
+ } : { code: import_src$29.SpanStatusCode.OK };
11146
11120
  SpanUtils.endSpan(spanInfo.span, status);
11147
11121
  }
11148
11122
  _captureHeadersFromRawHeaders(rawHeaders) {
@@ -11196,7 +11170,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11196
11170
  };
11197
11171
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11198
11172
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11199
- kind: import_src$28.SpanKind.CLIENT,
11173
+ kind: import_src$29.SpanKind.CLIENT,
11200
11174
  packageName: requestProtocol,
11201
11175
  packageType: PackageType.HTTP,
11202
11176
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11231,7 +11205,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11231
11205
  };
11232
11206
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalRequest.apply(this, args), {
11233
11207
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11234
- kind: import_src$28.SpanKind.CLIENT,
11208
+ kind: import_src$29.SpanKind.CLIENT,
11235
11209
  packageName: requestProtocol,
11236
11210
  packageType: PackageType.HTTP,
11237
11211
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11243,7 +11217,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11243
11217
  return self._handleOutboundRequestInSpan(originalRequest, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11244
11218
  });
11245
11219
  },
11246
- spanKind: import_src$28.SpanKind.CLIENT
11220
+ spanKind: import_src$29.SpanKind.CLIENT
11247
11221
  });
11248
11222
  else return originalRequest.apply(this, args);
11249
11223
  };
@@ -11289,7 +11263,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11289
11263
  };
11290
11264
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11291
11265
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11292
- kind: import_src$28.SpanKind.CLIENT,
11266
+ kind: import_src$29.SpanKind.CLIENT,
11293
11267
  packageName: requestProtocol,
11294
11268
  packageType: PackageType.HTTP,
11295
11269
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11323,7 +11297,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11323
11297
  };
11324
11298
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalGet.apply(this, args), {
11325
11299
  name: requestOptions.path || `${requestProtocol.toUpperCase()} ${method}`,
11326
- kind: import_src$28.SpanKind.CLIENT,
11300
+ kind: import_src$29.SpanKind.CLIENT,
11327
11301
  packageName: requestProtocol,
11328
11302
  packageType: PackageType.HTTP,
11329
11303
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11335,7 +11309,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11335
11309
  return self._handleOutboundRequestInSpan(originalGet, args, spanInfo, inputValue, { headers: { matchImportance: 0 } });
11336
11310
  });
11337
11311
  },
11338
- spanKind: import_src$28.SpanKind.CLIENT
11312
+ spanKind: import_src$29.SpanKind.CLIENT
11339
11313
  });
11340
11314
  else return originalGet.apply(this, args);
11341
11315
  };
@@ -11378,99 +11352,9 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11378
11352
  }
11379
11353
  };
11380
11354
 
11381
- //#endregion
11382
- //#region src/instrumentation/libraries/env/Instrumentation.ts
11383
- /**
11384
- * Environment variable instrumentation that records and replays process.env access.
11385
- * In record mode, captures environment variable values.
11386
- * In replay mode, returns previously recorded values for deterministic behavior.
11387
- */
11388
- var EnvInstrumentation = class extends TdInstrumentationBase {
11389
- constructor(config = {}) {
11390
- super("env", config);
11391
- this.isInPatchedCall = false;
11392
- this.mode = config.mode || TuskDriftMode.DISABLED;
11393
- }
11394
- init() {
11395
- this.patchProcessEnv();
11396
- return [];
11397
- }
11398
- patchProcessEnv() {
11399
- if (this.mode === TuskDriftMode.DISABLED || !this._config.enabled) return;
11400
- this.originalProcessEnv = process.env;
11401
- const envProxy = new Proxy(this.originalProcessEnv, {
11402
- get: (target, property, receiver) => {
11403
- return this._handleEnvAccess(target, property);
11404
- },
11405
- set: (target, property, value, receiver) => {
11406
- target[property] = value;
11407
- return true;
11408
- },
11409
- deleteProperty: (target, property) => {
11410
- delete target[property];
11411
- return true;
11412
- },
11413
- ownKeys: (target) => {
11414
- return Reflect.ownKeys(target);
11415
- },
11416
- getOwnPropertyDescriptor: (target, property) => {
11417
- return Reflect.getOwnPropertyDescriptor(target, property);
11418
- },
11419
- has: (target, property) => {
11420
- return Reflect.has(target, property);
11421
- }
11422
- });
11423
- process.env = envProxy;
11424
- }
11425
- _handleEnvAccess(target, key) {
11426
- if (this.isInPatchedCall) return target[key];
11427
- if (!TuskDriftCore.getInstance().isAppReady()) return target[key];
11428
- this.isInPatchedCall = true;
11429
- try {
11430
- return this._handleEnvAccessInMode(target, key);
11431
- } finally {
11432
- this.isInPatchedCall = false;
11433
- }
11434
- }
11435
- _handleEnvAccessInMode(target, key) {
11436
- let currentSpanInfo = null;
11437
- try {
11438
- currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11439
- } catch (error) {
11440
- logger.error(`EnvInstrumentation error getting current span info:`, error);
11441
- }
11442
- if (!currentSpanInfo) return target[key];
11443
- if (this.mode === TuskDriftMode.REPLAY) return this._handleReplayMode(target, key);
11444
- else if (this.mode === TuskDriftMode.RECORD) return this._handleRecordMode(currentSpanInfo, target, key);
11445
- else return target[key];
11446
- }
11447
- _handleReplayMode(target, key) {
11448
- const replayTraceId = SpanUtils.getCurrentReplayTraceId();
11449
- if (!replayTraceId) return target[key];
11450
- const envVar = EnvVarTracker.getEnvVar(replayTraceId, key);
11451
- if (envVar) {
11452
- logger.debug(`Returning env var ${key} for trace ${replayTraceId}: ${envVar}`);
11453
- return envVar;
11454
- }
11455
- return target[key];
11456
- }
11457
- _handleRecordMode(spanInfo, target, key) {
11458
- try {
11459
- EnvVarTracker.setEnvVar({
11460
- traceId: spanInfo.traceId,
11461
- key,
11462
- value: target[key] || void 0
11463
- });
11464
- } catch (error) {
11465
- logger.error(`EnvInstrumentation error storing env var:`, error);
11466
- }
11467
- return target[key];
11468
- }
11469
- };
11470
-
11471
11355
  //#endregion
11472
11356
  //#region src/instrumentation/libraries/date/Instrumentation.ts
11473
- var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11357
+ var import_src$28 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11474
11358
  /**
11475
11359
  * Date instrumentation that provides consistent dates in replay mode.
11476
11360
  * In replay mode, new Date() calls return the latest mock response timestamp.
@@ -11509,7 +11393,7 @@ var DateInstrumentation = class DateInstrumentation extends TdInstrumentationBas
11509
11393
  if (this.mode !== TuskDriftMode.REPLAY) return this._callOriginalDate(args, isConstructorCall);
11510
11394
  const currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11511
11395
  if (!currentSpanInfo) return this._callOriginalDate(args, isConstructorCall);
11512
- if (currentSpanInfo.context.getValue(SPAN_KIND_CONTEXT_KEY) !== import_src$27.SpanKind.SERVER) return this._callOriginalDate(args, isConstructorCall);
11396
+ if (currentSpanInfo.context.getValue(SPAN_KIND_CONTEXT_KEY) !== import_src$28.SpanKind.SERVER) return this._callOriginalDate(args, isConstructorCall);
11513
11397
  this.isInPatchedCall = true;
11514
11398
  try {
11515
11399
  return this._handleReplayDate(args, isConstructorCall);
@@ -11755,7 +11639,7 @@ var TdPgClientMock = class extends EventEmitter {
11755
11639
 
11756
11640
  //#endregion
11757
11641
  //#region src/instrumentation/libraries/pg/Instrumentation.ts
11758
- var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11642
+ var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
11759
11643
  var PgInstrumentation = class extends TdInstrumentationBase {
11760
11644
  constructor(config = {}) {
11761
11645
  super("pg", config);
@@ -11796,6 +11680,10 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11796
11680
  const self = this;
11797
11681
  return (originalQuery) => {
11798
11682
  return function query(...args) {
11683
+ if (self.isSubmittable(args[0])) {
11684
+ logger.debug(`[PgInstrumentation] Submittable query detected, passing through uninstrumented`);
11685
+ return originalQuery.apply(this, args);
11686
+ }
11799
11687
  let queryConfig = null;
11800
11688
  try {
11801
11689
  queryConfig = self.parseQueryArgs(args);
@@ -11824,7 +11712,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11824
11712
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11825
11713
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11826
11714
  name: spanName,
11827
- kind: import_src$26.SpanKind.CLIENT,
11715
+ kind: import_src$27.SpanKind.CLIENT,
11828
11716
  submodule: "query",
11829
11717
  packageType: PackageType.PG,
11830
11718
  packageName,
@@ -11843,7 +11731,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11843
11731
  const spanName = inputValue.clientType === "pool" ? "pg-pool.query" : "pg.query";
11844
11732
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
11845
11733
  name: spanName,
11846
- kind: import_src$26.SpanKind.CLIENT,
11734
+ kind: import_src$27.SpanKind.CLIENT,
11847
11735
  submodule: "query",
11848
11736
  packageType: PackageType.PG,
11849
11737
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -11854,7 +11742,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11854
11742
  return self._handleRecordQueryInSpan(spanInfo, originalQuery, queryConfig, args, this);
11855
11743
  });
11856
11744
  },
11857
- spanKind: import_src$26.SpanKind.CLIENT
11745
+ spanKind: import_src$27.SpanKind.CLIENT
11858
11746
  });
11859
11747
  else return originalQuery.apply(this, args);
11860
11748
  };
@@ -11876,7 +11764,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11876
11764
  replayModeHandler: () => {
11877
11765
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11878
11766
  name: `pg.connect`,
11879
- kind: import_src$26.SpanKind.CLIENT,
11767
+ kind: import_src$27.SpanKind.CLIENT,
11880
11768
  submodule: "connect",
11881
11769
  packageName: "pg",
11882
11770
  packageType: PackageType.PG,
@@ -11893,7 +11781,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11893
11781
  recordModeHandler: ({ isPreAppStart }) => {
11894
11782
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
11895
11783
  name: `pg.connect`,
11896
- kind: import_src$26.SpanKind.CLIENT,
11784
+ kind: import_src$27.SpanKind.CLIENT,
11897
11785
  submodule: "connect",
11898
11786
  packageName: "pg",
11899
11787
  packageType: PackageType.PG,
@@ -11904,12 +11792,19 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11904
11792
  return self._handleRecordConnectInSpan(spanInfo, originalConnect, callback, this);
11905
11793
  });
11906
11794
  },
11907
- spanKind: import_src$26.SpanKind.CLIENT
11795
+ spanKind: import_src$27.SpanKind.CLIENT
11908
11796
  });
11909
11797
  else return originalConnect.apply(this, [callback]);
11910
11798
  };
11911
11799
  };
11912
11800
  }
11801
+ /**
11802
+ * Check if an object is a Submittable (Query object with submit method).
11803
+ * This is the same check pg uses internally: typeof config.submit === 'function'
11804
+ */
11805
+ isSubmittable(arg) {
11806
+ return arg && typeof arg.submit === "function";
11807
+ }
11913
11808
  parseQueryArgs(args) {
11914
11809
  if (args.length === 0) return null;
11915
11810
  const firstArg = args[0];
@@ -11937,7 +11832,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11937
11832
  logger.debug(`[PgInstrumentation] PG query error (hasCallback): ${error.message} (${SpanUtils.getTraceInfo()})`);
11938
11833
  try {
11939
11834
  SpanUtils.endSpan(spanInfo.span, {
11940
- code: import_src$26.SpanStatusCode.ERROR,
11835
+ code: import_src$27.SpanStatusCode.ERROR,
11941
11836
  message: error.message
11942
11837
  });
11943
11838
  } catch (error$1) {
@@ -11947,7 +11842,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11947
11842
  logger.debug(`[PgInstrumentation] PG query completed successfully (hasCallback) (${SpanUtils.getTraceInfo()})`);
11948
11843
  try {
11949
11844
  this._addOutputAttributesToSpan(spanInfo, result);
11950
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11845
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11951
11846
  } catch (error$1) {
11952
11847
  logger.error(`[PgInstrumentation] error processing response:`, error$1);
11953
11848
  }
@@ -11974,7 +11869,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11974
11869
  logger.debug(`[PgInstrumentation] PG query completed successfully (${SpanUtils.getTraceInfo()})`);
11975
11870
  try {
11976
11871
  this._addOutputAttributesToSpan(spanInfo, result);
11977
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
11872
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
11978
11873
  } catch (error) {
11979
11874
  logger.error(`[PgInstrumentation] error processing response:`, error);
11980
11875
  }
@@ -11983,7 +11878,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
11983
11878
  logger.debug(`[PgInstrumentation] PG query error: ${error.message} (${SpanUtils.getTraceInfo()})`);
11984
11879
  try {
11985
11880
  SpanUtils.endSpan(spanInfo.span, {
11986
- code: import_src$26.SpanStatusCode.ERROR,
11881
+ code: import_src$27.SpanStatusCode.ERROR,
11987
11882
  message: error.message
11988
11883
  });
11989
11884
  } catch (error$1) {
@@ -12015,7 +11910,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12015
11910
  packageName,
12016
11911
  instrumentationName: this.INSTRUMENTATION_NAME,
12017
11912
  submoduleName: "query",
12018
- kind: import_src$26.SpanKind.CLIENT,
11913
+ kind: import_src$27.SpanKind.CLIENT,
12019
11914
  stackTrace
12020
11915
  },
12021
11916
  tuskDrift: this.tuskDrift
@@ -12059,6 +11954,8 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12059
11954
  * Reference for data type IDs: https://jdbc.postgresql.org/documentation/publicapi/constant-values.html
12060
11955
  */
12061
11956
  convertPostgresTypes(result, rowMode) {
11957
+ if (result && result.isMultiStatement && Array.isArray(result.results)) return result.results.map((singleResult) => this.convertPostgresTypes(singleResult, rowMode));
11958
+ if (Array.isArray(result)) return result.map((singleResult) => this.convertPostgresTypes(singleResult, rowMode));
12062
11959
  if (!result || !result.fields || !result.rows) return result;
12063
11960
  if (rowMode === "array") {
12064
11961
  const convertedRows$1 = result.rows.map((row) => {
@@ -12099,7 +11996,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12099
11996
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12100
11997
  try {
12101
11998
  SpanUtils.endSpan(spanInfo.span, {
12102
- code: import_src$26.SpanStatusCode.ERROR,
11999
+ code: import_src$27.SpanStatusCode.ERROR,
12103
12000
  message: error.message
12104
12001
  });
12105
12002
  } catch (error$1) {
@@ -12109,7 +12006,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12109
12006
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12110
12007
  try {
12111
12008
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12112
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12009
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12113
12010
  } catch (error$1) {
12114
12011
  logger.error(`[PgInstrumentation] error processing connect response:`, error$1);
12115
12012
  }
@@ -12121,7 +12018,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12121
12018
  logger.debug(`[PgInstrumentation] PG connect completed successfully (${SpanUtils.getTraceInfo()})`);
12122
12019
  try {
12123
12020
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12124
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12021
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12125
12022
  } catch (error) {
12126
12023
  logger.error(`[PgInstrumentation] error processing connect response:`, error);
12127
12024
  }
@@ -12130,7 +12027,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12130
12027
  logger.debug(`[PgInstrumentation] PG connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12131
12028
  try {
12132
12029
  SpanUtils.endSpan(spanInfo.span, {
12133
- code: import_src$26.SpanStatusCode.ERROR,
12030
+ code: import_src$27.SpanStatusCode.ERROR,
12134
12031
  message: error.message
12135
12032
  });
12136
12033
  } catch (error$1) {
@@ -12148,7 +12045,18 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12148
12045
  }
12149
12046
  _addOutputAttributesToSpan(spanInfo, result) {
12150
12047
  if (!result) return;
12151
- const outputValue = {
12048
+ let outputValue;
12049
+ if (Array.isArray(result)) outputValue = {
12050
+ isMultiStatement: true,
12051
+ results: result.map((r) => ({
12052
+ command: r.command,
12053
+ rowCount: r.rowCount,
12054
+ oid: r.oid,
12055
+ rows: r.rows || [],
12056
+ fields: r.fields || []
12057
+ }))
12058
+ };
12059
+ else outputValue = {
12152
12060
  command: result.command,
12153
12061
  rowCount: result.rowCount,
12154
12062
  oid: result.oid,
@@ -12191,7 +12099,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12191
12099
  replayModeHandler: () => {
12192
12100
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12193
12101
  name: `pg-pool.connect`,
12194
- kind: import_src$26.SpanKind.CLIENT,
12102
+ kind: import_src$27.SpanKind.CLIENT,
12195
12103
  submodule: "connect",
12196
12104
  packageName: "pg-pool",
12197
12105
  packageType: PackageType.PG,
@@ -12208,7 +12116,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12208
12116
  recordModeHandler: ({ isPreAppStart }) => {
12209
12117
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalConnect.apply(this, [callback]), {
12210
12118
  name: `pg-pool.connect`,
12211
- kind: import_src$26.SpanKind.CLIENT,
12119
+ kind: import_src$27.SpanKind.CLIENT,
12212
12120
  submodule: "connect",
12213
12121
  packageName: "pg-pool",
12214
12122
  packageType: PackageType.PG,
@@ -12219,7 +12127,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12219
12127
  return self._handleRecordPoolConnectInSpan(spanInfo, originalConnect, callback, this);
12220
12128
  });
12221
12129
  },
12222
- spanKind: import_src$26.SpanKind.CLIENT
12130
+ spanKind: import_src$27.SpanKind.CLIENT
12223
12131
  });
12224
12132
  else return originalConnect.apply(this, [callback]);
12225
12133
  };
@@ -12232,7 +12140,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12232
12140
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12233
12141
  try {
12234
12142
  SpanUtils.endSpan(spanInfo.span, {
12235
- code: import_src$26.SpanStatusCode.ERROR,
12143
+ code: import_src$27.SpanStatusCode.ERROR,
12236
12144
  message: error.message
12237
12145
  });
12238
12146
  } catch (error$1) {
@@ -12245,7 +12153,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12245
12153
  connected: true,
12246
12154
  hasClient: !!client
12247
12155
  } });
12248
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12156
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12249
12157
  } catch (error$1) {
12250
12158
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error$1);
12251
12159
  }
@@ -12260,7 +12168,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12260
12168
  connected: true,
12261
12169
  hasClient: !!client
12262
12170
  } });
12263
- SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12171
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$27.SpanStatusCode.OK });
12264
12172
  } catch (error) {
12265
12173
  logger.error(`[PgInstrumentation] error processing pool connect response:`, error);
12266
12174
  }
@@ -12269,7 +12177,7 @@ var PgInstrumentation = class extends TdInstrumentationBase {
12269
12177
  logger.debug(`[PgInstrumentation] PG Pool connect error: ${error.message} (${SpanUtils.getTraceInfo()})`);
12270
12178
  try {
12271
12179
  SpanUtils.endSpan(spanInfo.span, {
12272
- code: import_src$26.SpanStatusCode.ERROR,
12180
+ code: import_src$27.SpanStatusCode.ERROR,
12273
12181
  message: error.message
12274
12182
  });
12275
12183
  } catch (error$1) {
@@ -12298,68 +12206,114 @@ function isPostgresOutputValueType(value) {
12298
12206
  }
12299
12207
 
12300
12208
  //#endregion
12301
- //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12302
- var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12303
- var PostgresInstrumentation = class extends TdInstrumentationBase {
12304
- constructor(config = {}) {
12305
- super("postgres", config);
12306
- this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12307
- this.mode = config.mode || TuskDriftMode.DISABLED;
12308
- this.tuskDrift = TuskDriftCore.getInstance();
12209
+ //#region src/instrumentation/libraries/postgres/utils/typeConversion.ts
12210
+ /**
12211
+ * Convert PostgreSQL string values back to appropriate JavaScript types
12212
+ * based on field metadata from the recorded response.
12213
+ */
12214
+ function convertPostgresTypes(result) {
12215
+ if (!isPostgresOutputValueType(result)) {
12216
+ logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12217
+ return;
12309
12218
  }
12310
- init() {
12311
- return [new TdInstrumentationNodeModule({
12312
- name: "postgres",
12313
- supportedVersions: ["3.*"],
12314
- patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12315
- })];
12219
+ const { rows, count, command, columns, state, statement } = result;
12220
+ const resultArray = Array.from((rows || []).map((row) => reconstructBuffers(row)));
12221
+ if (count !== void 0) Object.defineProperty(resultArray, "count", {
12222
+ value: count,
12223
+ writable: true,
12224
+ enumerable: false
12225
+ });
12226
+ if (command !== void 0) Object.defineProperty(resultArray, "command", {
12227
+ value: command,
12228
+ writable: true,
12229
+ enumerable: false
12230
+ });
12231
+ if (columns !== void 0) Object.defineProperty(resultArray, "columns", {
12232
+ value: columns,
12233
+ writable: true,
12234
+ enumerable: false
12235
+ });
12236
+ if (state !== void 0) Object.defineProperty(resultArray, "state", {
12237
+ value: state,
12238
+ writable: true,
12239
+ enumerable: false
12240
+ });
12241
+ if (statement !== void 0) Object.defineProperty(resultArray, "statement", {
12242
+ value: statement,
12243
+ writable: true,
12244
+ enumerable: false
12245
+ });
12246
+ return resultArray;
12247
+ }
12248
+ /**
12249
+ * Recursively reconstructs Buffer objects from their JSON-serialized format.
12250
+ * When Buffers are JSON.stringify'd, they become { type: "Buffer", data: [...] }.
12251
+ * This method converts them back to actual Buffer instances.
12252
+ */
12253
+ function reconstructBuffers(value) {
12254
+ if (value === null || value === void 0) return value;
12255
+ if (typeof value === "object" && value.type === "Buffer" && Array.isArray(value.data)) return Buffer.from(value.data);
12256
+ if (Array.isArray(value)) return value.map((item) => reconstructBuffers(item));
12257
+ if (typeof value === "object") {
12258
+ const result = {};
12259
+ for (const key of Object.keys(value)) result[key] = reconstructBuffers(value[key]);
12260
+ return result;
12316
12261
  }
12317
- _patchPostgresModule(postgresModule) {
12318
- logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12319
- if (this.isModulePatched(postgresModule)) {
12320
- logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12321
- return postgresModule;
12322
- }
12323
- const self = this;
12324
- if (isEsm(postgresModule)) {
12325
- logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12326
- this._wrap(postgresModule, "default", (originalFunction) => {
12327
- return function(...args) {
12328
- return self._handlePostgresConnection(originalFunction, args);
12329
- };
12330
- });
12331
- } else {
12332
- logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12333
- const originalFunction = postgresModule;
12334
- const wrappedFunction = function(...args) {
12335
- logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12336
- return self._handlePostgresConnection(originalFunction, args);
12337
- };
12338
- Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12339
- Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12340
- for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12341
- Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12342
- if (key !== "prototype" && key !== "length" && key !== "name") {
12343
- const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12344
- if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12345
- }
12346
- });
12347
- postgresModule = wrappedFunction;
12348
- }
12349
- if (postgresModule.sql && typeof postgresModule.sql === "function") {
12350
- this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12351
- logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12352
- }
12353
- this.markModuleAsPatched(postgresModule);
12354
- logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12355
- return postgresModule;
12262
+ return value;
12263
+ }
12264
+ /**
12265
+ * Add output attributes to span for PostgreSQL results.
12266
+ */
12267
+ function addOutputAttributesToSpan(spanInfo, result) {
12268
+ if (!result) return;
12269
+ const isArray$1 = Array.isArray(result);
12270
+ logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12271
+ const normalizeValue = (val) => {
12272
+ if (Buffer.isBuffer(val)) return val.toString("utf8");
12273
+ else if (Array.isArray(val)) return val.map(normalizeValue);
12274
+ else if (val && typeof val === "object" && val.type === "Buffer" && Array.isArray(val.data)) return Buffer.from(val.data).toString("utf8");
12275
+ return val;
12276
+ };
12277
+ const outputValue = {
12278
+ rows: isArray$1 ? Array.from(result).map(normalizeValue) : (result.rows || []).map(normalizeValue),
12279
+ count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12280
+ command: result.command || void 0,
12281
+ columns: result.columns || void 0,
12282
+ state: result.state || void 0,
12283
+ statement: result.statement || void 0
12284
+ };
12285
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12286
+ }
12287
+
12288
+ //#endregion
12289
+ //#region src/instrumentation/libraries/postgres/utils/queryUtils.ts
12290
+ /**
12291
+ * Reconstruct a parameterized query string from template strings array and values.
12292
+ * Converts values to $1, $2, etc. placeholders.
12293
+ */
12294
+ function reconstructQueryString(strings, values) {
12295
+ let queryString = "";
12296
+ for (let i = 0; i < strings.length; i++) {
12297
+ queryString += strings[i];
12298
+ if (i < values.length) queryString += `$${i + 1}`;
12356
12299
  }
12357
- _handlePostgresConnection(originalFunction, args) {
12358
- const connectionString = typeof args[0] === "string" ? args[0] : void 0;
12359
- const options = typeof args[0] === "string" ? args[1] : args[0];
12300
+ return queryString;
12301
+ }
12302
+
12303
+ //#endregion
12304
+ //#region src/instrumentation/libraries/postgres/handlers/ConnectionHandler.ts
12305
+ var import_src$26 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12306
+ var ConnectionHandler = class {
12307
+ constructor(mode, instrumentationName, isAppReady, wrapSqlInstance) {
12308
+ this.mode = mode;
12309
+ this.instrumentationName = instrumentationName;
12310
+ this.isAppReady = isAppReady;
12311
+ this.wrapSqlInstance = wrapSqlInstance;
12312
+ }
12313
+ handlePostgresConnection(originalFunction, args) {
12360
12314
  const inputValue = {
12361
- connectionString: connectionString ? this._sanitizeConnectionString(connectionString) : void 0,
12362
- options: options ? this._sanitizeConnectionOptions(options) : void 0
12315
+ connectionString: typeof args[0] === "string" ? args[0] : void 0,
12316
+ options: typeof args[0] === "string" ? args[1] : args[0]
12363
12317
  };
12364
12318
  if (this.mode === TuskDriftMode.REPLAY) return handleReplayMode({
12365
12319
  noOpRequestHandler: () => {
@@ -12373,96 +12327,148 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12373
12327
  }));
12374
12328
  mockSql.begin = () => Promise.resolve();
12375
12329
  mockSql.end = () => Promise.resolve();
12330
+ mockSql.file = () => Promise.resolve(Object.assign([], {
12331
+ count: 0,
12332
+ command: null
12333
+ }));
12334
+ mockSql.reserve = () => Promise.resolve(mockSql);
12335
+ mockSql.listen = () => Promise.resolve({
12336
+ state: { state: "I" },
12337
+ unlisten: async () => {}
12338
+ });
12339
+ mockSql.notify = () => Promise.resolve();
12376
12340
  return mockSql;
12377
12341
  },
12378
12342
  isServerRequest: false,
12379
12343
  replayModeHandler: () => {
12380
12344
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12381
12345
  const sqlInstance = originalFunction(...args);
12382
- return this._wrapSqlInstance(sqlInstance);
12346
+ return this.wrapSqlInstance(sqlInstance);
12383
12347
  }, {
12384
12348
  name: "postgres.connect",
12385
- kind: import_src$25.SpanKind.CLIENT,
12349
+ kind: import_src$26.SpanKind.CLIENT,
12386
12350
  submodule: "connect",
12387
12351
  packageType: PackageType.PG,
12388
12352
  packageName: "postgres",
12389
- instrumentationName: this.INSTRUMENTATION_NAME,
12353
+ instrumentationName: this.instrumentationName,
12390
12354
  inputValue,
12391
- isPreAppStart: false
12355
+ isPreAppStart: this.isAppReady() ? false : true
12392
12356
  }, (spanInfo) => {
12393
- return this._handleReplayConnect(originalFunction, args);
12357
+ return this.handleReplayConnect(originalFunction, args);
12394
12358
  });
12395
12359
  }
12396
12360
  });
12397
12361
  else if (this.mode === TuskDriftMode.RECORD) return handleRecordMode({
12398
12362
  originalFunctionCall: () => {
12399
12363
  const sqlInstance = originalFunction(...args);
12400
- return this._wrapSqlInstance(sqlInstance);
12364
+ return this.wrapSqlInstance(sqlInstance);
12401
12365
  },
12402
12366
  recordModeHandler: ({ isPreAppStart }) => {
12403
12367
  return SpanUtils.createAndExecuteSpan(this.mode, () => {
12404
12368
  const sqlInstance = originalFunction(...args);
12405
- return this._wrapSqlInstance(sqlInstance);
12369
+ return this.wrapSqlInstance(sqlInstance);
12406
12370
  }, {
12407
12371
  name: "postgres.connect",
12408
- kind: import_src$25.SpanKind.CLIENT,
12372
+ kind: import_src$26.SpanKind.CLIENT,
12409
12373
  submodule: "connect",
12410
12374
  packageType: PackageType.PG,
12411
12375
  packageName: "postgres",
12412
- instrumentationName: this.INSTRUMENTATION_NAME,
12376
+ instrumentationName: this.instrumentationName,
12413
12377
  inputValue,
12414
12378
  isPreAppStart
12415
12379
  }, (spanInfo) => {
12416
- return this._handleRecordConnect(spanInfo, originalFunction, args);
12380
+ return this.handleRecordConnect(spanInfo, originalFunction, args);
12417
12381
  });
12418
12382
  },
12419
- spanKind: import_src$25.SpanKind.CLIENT
12383
+ spanKind: import_src$26.SpanKind.CLIENT
12420
12384
  });
12421
12385
  else return originalFunction(...args);
12422
12386
  }
12423
- _sanitizeConnectionString(connectionString) {
12424
- try {
12425
- const url = new URL(connectionString);
12426
- if (url.password) url.password = "***";
12427
- return url.toString();
12428
- } catch {
12429
- return "[INVALID_URL]";
12430
- }
12431
- }
12432
- _sanitizeConnectionOptions(options) {
12433
- if (!options || typeof options !== "object") return options;
12434
- const sanitized = { ...options };
12435
- if (sanitized.password) sanitized.password = "***";
12436
- if (sanitized.ssl && typeof sanitized.ssl === "object") {
12437
- sanitized.ssl = { ...sanitized.ssl };
12438
- if (sanitized.ssl.key) sanitized.ssl.key = "***";
12439
- if (sanitized.ssl.cert) sanitized.ssl.cert = "***";
12440
- if (sanitized.ssl.ca) sanitized.ssl.ca = "***";
12441
- }
12442
- return sanitized;
12443
- }
12444
- _handleRecordConnect(spanInfo, originalFunction, args) {
12387
+ handleRecordConnect(spanInfo, originalFunction, args) {
12445
12388
  const sqlInstance = originalFunction(...args);
12446
- const wrappedInstance = this._wrapSqlInstance(sqlInstance);
12389
+ const wrappedInstance = this.wrapSqlInstance(sqlInstance);
12447
12390
  try {
12448
12391
  logger.debug(`[PostgresInstrumentation] Postgres connection created successfully (${SpanUtils.getTraceInfo()})`);
12449
12392
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: { connected: true } });
12450
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12393
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$26.SpanStatusCode.OK });
12451
12394
  } catch (error) {
12452
12395
  logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12453
12396
  }
12454
12397
  return wrappedInstance;
12455
12398
  }
12456
- _handleReplayConnect(originalFunction, args) {
12399
+ handleReplayConnect(originalFunction, args) {
12457
12400
  logger.debug(`[PostgresInstrumentation] Replaying Postgres connection`);
12458
12401
  try {
12459
12402
  const sqlInstance = originalFunction(...args);
12460
- return this._wrapSqlInstance(sqlInstance);
12403
+ return this.wrapSqlInstance(sqlInstance);
12461
12404
  } catch (error) {
12462
12405
  logger.debug(`[PostgresInstrumentation] Postgres connection error in replay: ${error.message}`);
12463
12406
  throw error;
12464
12407
  }
12465
12408
  }
12409
+ };
12410
+
12411
+ //#endregion
12412
+ //#region src/instrumentation/libraries/postgres/Instrumentation.ts
12413
+ var import_src$25 = /* @__PURE__ */ __toESM(require_src$7(), 1);
12414
+ var PostgresInstrumentation = class extends TdInstrumentationBase {
12415
+ constructor(config = {}) {
12416
+ super("postgres", config);
12417
+ this.INSTRUMENTATION_NAME = "PostgresInstrumentation";
12418
+ this.mode = config.mode || TuskDriftMode.DISABLED;
12419
+ this.tuskDrift = TuskDriftCore.getInstance();
12420
+ this.connectionHandler = new ConnectionHandler(this.mode, this.INSTRUMENTATION_NAME, () => this.tuskDrift.isAppReady(), (sqlInstance) => this._wrapSqlInstance(sqlInstance));
12421
+ }
12422
+ init() {
12423
+ return [new TdInstrumentationNodeModule({
12424
+ name: "postgres",
12425
+ supportedVersions: ["3.*"],
12426
+ patch: (moduleExports) => this._patchPostgresModule(moduleExports)
12427
+ })];
12428
+ }
12429
+ _patchPostgresModule(postgresModule) {
12430
+ logger.debug(`[PostgresInstrumentation] Patching Postgres module in ${this.mode} mode`);
12431
+ if (this.isModulePatched(postgresModule)) {
12432
+ logger.debug(`[PostgresInstrumentation] Postgres module already patched, skipping`);
12433
+ return postgresModule;
12434
+ }
12435
+ const self = this;
12436
+ if (isEsm(postgresModule)) {
12437
+ logger.debug(`[PostgresInstrumentation] Wrapping ESM default export`);
12438
+ this._wrap(postgresModule, "default", (originalFunction) => {
12439
+ return function(...args) {
12440
+ return self._handlePostgresConnection(originalFunction, args);
12441
+ };
12442
+ });
12443
+ } else {
12444
+ logger.debug(`[PostgresInstrumentation] Module is a function (CJS style)`);
12445
+ const originalFunction = postgresModule;
12446
+ const wrappedFunction = function(...args) {
12447
+ logger.debug(`[PostgresInstrumentation] Wrapped postgres() (CJS) called with args:`, args);
12448
+ return self._handlePostgresConnection(originalFunction, args);
12449
+ };
12450
+ Object.setPrototypeOf(wrappedFunction, Object.getPrototypeOf(originalFunction));
12451
+ Object.defineProperty(wrappedFunction, "name", { value: originalFunction.name });
12452
+ for (const key in originalFunction) if (originalFunction.hasOwnProperty(key)) wrappedFunction[key] = originalFunction[key];
12453
+ Object.getOwnPropertyNames(originalFunction).forEach((key) => {
12454
+ if (key !== "prototype" && key !== "length" && key !== "name") {
12455
+ const descriptor = Object.getOwnPropertyDescriptor(originalFunction, key);
12456
+ if (descriptor) Object.defineProperty(wrappedFunction, key, descriptor);
12457
+ }
12458
+ });
12459
+ postgresModule = wrappedFunction;
12460
+ }
12461
+ if (postgresModule.sql && typeof postgresModule.sql === "function") {
12462
+ this._wrap(postgresModule, "sql", this._getSqlPatchFn());
12463
+ logger.debug(`[PostgresInstrumentation] Wrapped sql function`);
12464
+ }
12465
+ this.markModuleAsPatched(postgresModule);
12466
+ logger.debug(`[PostgresInstrumentation] Postgres module patching complete`);
12467
+ return postgresModule;
12468
+ }
12469
+ _handlePostgresConnection(originalFunction, args) {
12470
+ return this.connectionHandler.handlePostgresConnection(originalFunction, args);
12471
+ }
12466
12472
  _wrapSqlInstance(sqlInstance) {
12467
12473
  if (!sqlInstance || typeof sqlInstance !== "function") return sqlInstance;
12468
12474
  const self = this;
@@ -12478,11 +12484,34 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12478
12484
  logger.debug(`[PostgresInstrumentation] Wrapped unsafe method on sql instance`);
12479
12485
  }
12480
12486
  if (typeof originalSql.begin === "function") {
12481
- wrappedSql.begin = self._wrapBeginMethod(originalSql);
12482
- logger.debug(`[PostgresInstrumentation] Wrapped begin method on sql instance`);
12487
+ const wrappedBegin = self._wrapBeginMethod(originalSql);
12488
+ originalSql.begin = wrappedBegin;
12489
+ wrappedSql.begin = wrappedBegin;
12490
+ }
12491
+ if (typeof originalSql.file === "function") {
12492
+ wrappedSql.file = self._wrapFileMethod(originalSql);
12493
+ logger.debug(`[PostgresInstrumentation] Wrapped file method on sql instance`);
12494
+ }
12495
+ if (typeof originalSql.reserve === "function") {
12496
+ wrappedSql.reserve = self._wrapReserveMethod(originalSql);
12497
+ logger.debug(`[PostgresInstrumentation] Wrapped reserve method on sql instance`);
12498
+ }
12499
+ if (typeof originalSql.listen === "function") {
12500
+ wrappedSql.listen = self._wrapListenMethod(originalSql);
12501
+ logger.debug(`[PostgresInstrumentation] Wrapped listen method on sql instance`);
12502
+ }
12503
+ if (typeof originalSql.notify === "function") {
12504
+ wrappedSql.notify = self._wrapNotifyMethod(wrappedSql);
12505
+ logger.debug(`[PostgresInstrumentation] Wrapped notify method on sql instance`);
12483
12506
  }
12484
12507
  return wrappedSql;
12485
12508
  }
12509
+ _wrapNotifyMethod(wrappedSqlInstance) {
12510
+ return async function notify(channel, payload) {
12511
+ logger.debug(`[PostgresInstrumentation] notify() called for channel ${channel}`);
12512
+ return wrappedSqlInstance`select pg_notify(${channel}, ${String(payload)})`;
12513
+ };
12514
+ }
12486
12515
  _wrapUnsafeMethod(sqlInstance) {
12487
12516
  const self = this;
12488
12517
  const originalUnsafe = sqlInstance.unsafe;
@@ -12499,9 +12528,178 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12499
12528
  return self._handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback);
12500
12529
  };
12501
12530
  }
12502
- _getSqlPatchFn() {
12531
+ _wrapFileMethod(sqlInstance) {
12503
12532
  const self = this;
12504
- return (originalSql) => {
12533
+ const originalFile = sqlInstance.file;
12534
+ return function file(path$2, parameters, queryOptions) {
12535
+ return self._handleFileQuery(sqlInstance, originalFile, path$2, parameters, queryOptions);
12536
+ };
12537
+ }
12538
+ _wrapReserveMethod(sqlInstance) {
12539
+ const self = this;
12540
+ const originalReserve = sqlInstance.reserve;
12541
+ return async function reserve() {
12542
+ if (self.mode === TuskDriftMode.REPLAY) {
12543
+ logger.debug(`[PostgresInstrumentation] REPLAY mode: Creating mock reserved connection without TCP`);
12544
+ const mockReservedSql = self._wrapSqlInstance(sqlInstance);
12545
+ if (typeof mockReservedSql === "function") mockReservedSql.release = function() {
12546
+ logger.debug(`[PostgresInstrumentation] Mock reserved connection released`);
12547
+ };
12548
+ return mockReservedSql;
12549
+ }
12550
+ const reservedSql = await originalReserve.call(sqlInstance);
12551
+ const wrappedReservedSql = self._wrapSqlInstance(reservedSql);
12552
+ logger.debug(`[PostgresInstrumentation] Reserved connection obtained and wrapped`);
12553
+ return wrappedReservedSql;
12554
+ };
12555
+ }
12556
+ _wrapListenMethod(sqlInstance) {
12557
+ const self = this;
12558
+ const originalListen = sqlInstance.listen;
12559
+ return async function listen(channelName, callback, onlisten) {
12560
+ return self._handleListenMethod(sqlInstance, originalListen, channelName, callback, onlisten);
12561
+ };
12562
+ }
12563
+ async _handleListenMethod(sqlInstance, originalListen, channelName, callback, onlisten) {
12564
+ const inputValue = {
12565
+ operation: "listen",
12566
+ channel: channelName
12567
+ };
12568
+ if (this.mode === TuskDriftMode.REPLAY) return this._handleReplayListen(channelName, callback, onlisten, inputValue);
12569
+ else if (this.mode === TuskDriftMode.RECORD) return this._handleRecordListen(sqlInstance, originalListen, channelName, callback, onlisten, inputValue);
12570
+ else return originalListen.call(sqlInstance, channelName, callback, onlisten);
12571
+ }
12572
+ async _handleRecordListen(sqlInstance, originalListen, channelName, callback, onlisten, inputValue) {
12573
+ const receivedPayloads = [];
12574
+ const wrappedCallback = (payload) => {
12575
+ logger.debug(`[PostgresInstrumentation] RECORD: Captured notification payload on channel ${channelName}: ${payload}`);
12576
+ receivedPayloads.push(payload);
12577
+ callback(payload);
12578
+ };
12579
+ return handleRecordMode({
12580
+ originalFunctionCall: () => originalListen.call(sqlInstance, channelName, callback, onlisten),
12581
+ recordModeHandler: ({ isPreAppStart }) => {
12582
+ return SpanUtils.createAndExecuteSpan(this.mode, () => originalListen.call(sqlInstance, channelName, callback, onlisten), {
12583
+ name: "postgres.listen",
12584
+ kind: import_src$25.SpanKind.CLIENT,
12585
+ submodule: "listen",
12586
+ packageType: PackageType.PG,
12587
+ packageName: "postgres",
12588
+ instrumentationName: this.INSTRUMENTATION_NAME,
12589
+ inputValue,
12590
+ isPreAppStart
12591
+ }, async (spanInfo) => {
12592
+ try {
12593
+ const result = await originalListen.call(sqlInstance, channelName, wrappedCallback, onlisten);
12594
+ try {
12595
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12596
+ channel: channelName,
12597
+ state: result.state
12598
+ } });
12599
+ } catch (error) {
12600
+ logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12601
+ }
12602
+ const originalUnlisten = result.unlisten;
12603
+ const wrappedUnlisten = async () => {
12604
+ logger.debug(`[PostgresInstrumentation] RECORD: Unlisten called, captured ${receivedPayloads.length} payloads`);
12605
+ try {
12606
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12607
+ channel: channelName,
12608
+ state: result.state,
12609
+ payloads: receivedPayloads
12610
+ } });
12611
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12612
+ } catch (error) {
12613
+ logger.error(`[PostgresInstrumentation] error adding span attributes:`, error);
12614
+ }
12615
+ return originalUnlisten();
12616
+ };
12617
+ return {
12618
+ state: result.state,
12619
+ unlisten: wrappedUnlisten
12620
+ };
12621
+ } catch (error) {
12622
+ logger.error(`[PostgresInstrumentation] RECORD listen error: ${error.message}`);
12623
+ try {
12624
+ SpanUtils.endSpan(spanInfo.span, {
12625
+ code: import_src$25.SpanStatusCode.ERROR,
12626
+ message: error.message
12627
+ });
12628
+ } catch (error$1) {
12629
+ logger.error(`[PostgresInstrumentation] error ending span:`, error$1);
12630
+ }
12631
+ throw error;
12632
+ }
12633
+ });
12634
+ },
12635
+ spanKind: import_src$25.SpanKind.CLIENT
12636
+ });
12637
+ }
12638
+ async _handleReplayListen(channelName, callback, onlisten, inputValue) {
12639
+ logger.debug(`[PostgresInstrumentation] REPLAY: Mocking listen for channel ${channelName} without TCP`);
12640
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12641
+ return handleReplayMode({
12642
+ noOpRequestHandler: () => Promise.resolve({
12643
+ state: { state: "I" },
12644
+ unlisten: async () => {}
12645
+ }),
12646
+ isServerRequest: false,
12647
+ replayModeHandler: () => {
12648
+ return SpanUtils.createAndExecuteSpan(this.mode, () => Promise.resolve({
12649
+ state: { state: "I" },
12650
+ unlisten: async () => {}
12651
+ }), {
12652
+ name: "postgres.listen",
12653
+ kind: import_src$25.SpanKind.CLIENT,
12654
+ submodule: "listen",
12655
+ packageType: PackageType.PG,
12656
+ packageName: "postgres",
12657
+ instrumentationName: this.INSTRUMENTATION_NAME,
12658
+ inputValue,
12659
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12660
+ }, async (spanInfo) => {
12661
+ try {
12662
+ const mockData = await this._findMockData({
12663
+ spanInfo,
12664
+ name: "postgres.listen",
12665
+ inputValue,
12666
+ submoduleName: "listen",
12667
+ stackTrace
12668
+ });
12669
+ if (!mockData) {
12670
+ logger.warn(`[PostgresInstrumentation] No mock data found for listen channel: ${channelName}`);
12671
+ throw new Error(`No mock data found for listen channel: ${channelName}`);
12672
+ }
12673
+ logger.debug(`[PostgresInstrumentation] Found mock data for listen: ${JSON.stringify(mockData)}`);
12674
+ const recordedPayloads = mockData.result?.payloads || [];
12675
+ const recordedState = mockData.result?.state || { state: "I" };
12676
+ if (onlisten) onlisten();
12677
+ for (const payload of recordedPayloads) {
12678
+ logger.debug(`[PostgresInstrumentation] REPLAY: Invoking callback with recorded payload: ${payload}`);
12679
+ callback(payload);
12680
+ }
12681
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12682
+ return {
12683
+ state: recordedState,
12684
+ unlisten: async () => {
12685
+ logger.debug(`[PostgresInstrumentation] REPLAY: Mock unlisten called`);
12686
+ }
12687
+ };
12688
+ } catch (error) {
12689
+ logger.error(`[PostgresInstrumentation] REPLAY listen error: ${error.message}`);
12690
+ SpanUtils.endSpan(spanInfo.span, {
12691
+ code: import_src$25.SpanStatusCode.ERROR,
12692
+ message: error.message
12693
+ });
12694
+ throw error;
12695
+ }
12696
+ });
12697
+ }
12698
+ });
12699
+ }
12700
+ _getSqlPatchFn() {
12701
+ const self = this;
12702
+ return (originalSql) => {
12505
12703
  return function sql(strings, ...values) {
12506
12704
  return self._handleSqlQuery(originalSql, strings, values);
12507
12705
  };
@@ -12511,93 +12709,19 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12511
12709
  if (!strings || !Array.isArray(strings.raw)) return originalSql.call(this, strings, ...values);
12512
12710
  const creationContext = import_src$25.context.active();
12513
12711
  const query = originalSql.call(this, strings, ...values);
12514
- const originalThen = query.then.bind(query);
12515
- const self = this;
12516
- query.then = function(onFulfilled, onRejected) {
12517
- let queryString = "";
12518
- for (let i = 0; i < strings.length; i++) {
12519
- queryString += strings[i];
12520
- if (i < values.length) queryString += `$${i + 1}`;
12521
- }
12522
- const inputValue = {
12523
- query: queryString.trim(),
12524
- parameters: values
12525
- };
12526
- return import_src$25.context.with(creationContext, () => {
12527
- if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12528
- originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12529
- recordModeHandler: ({ isPreAppStart }) => {
12530
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12531
- name: "postgres.query",
12532
- kind: import_src$25.SpanKind.CLIENT,
12533
- submodule: "query",
12534
- packageType: PackageType.PG,
12535
- instrumentationName: self.INSTRUMENTATION_NAME,
12536
- packageName: "postgres",
12537
- inputValue,
12538
- isPreAppStart
12539
- }, (spanInfo) => {
12540
- const wrappedOnFulfilled = (result) => {
12541
- try {
12542
- logger.debug(`[PostgresInstrumentation] Postgres query completed successfully`, result);
12543
- self._addOutputAttributesToSpan(spanInfo, result);
12544
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12545
- } catch (error) {
12546
- logger.error(`[PostgresInstrumentation] error processing query response:`, error);
12547
- }
12548
- return onFulfilled ? onFulfilled(result) : result;
12549
- };
12550
- const wrappedOnRejected = (error) => {
12551
- try {
12552
- logger.debug(`[PostgresInstrumentation] Postgres query error`, error);
12553
- SpanUtils.endSpan(spanInfo.span, {
12554
- code: import_src$25.SpanStatusCode.ERROR,
12555
- message: error.message
12556
- });
12557
- } catch (spanError) {
12558
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12559
- }
12560
- if (onRejected) return onRejected(error);
12561
- throw error;
12562
- };
12563
- return originalThen(wrappedOnFulfilled, wrappedOnRejected);
12564
- });
12565
- },
12566
- spanKind: import_src$25.SpanKind.CLIENT
12567
- });
12568
- else if (self.mode === TuskDriftMode.REPLAY) {
12569
- const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
12570
- return handleReplayMode({
12571
- noOpRequestHandler: () => Promise.resolve(Object.assign([], {
12572
- count: 0,
12573
- command: null
12574
- })),
12575
- isServerRequest: false,
12576
- replayModeHandler: () => {
12577
- return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12578
- name: "postgres.query",
12579
- kind: import_src$25.SpanKind.CLIENT,
12580
- submodule: "query",
12581
- packageType: PackageType.PG,
12582
- packageName: "postgres",
12583
- instrumentationName: self.INSTRUMENTATION_NAME,
12584
- inputValue,
12585
- isPreAppStart: false
12586
- }, async (spanInfo) => {
12587
- const mockedResult = await self.handleReplaySqlQuery({
12588
- inputValue,
12589
- spanInfo,
12590
- submodule: "query",
12591
- name: "postgres.query",
12592
- stackTrace
12593
- });
12594
- return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12595
- });
12596
- }
12597
- });
12598
- } else return originalThen(onFulfilled, onRejected);
12599
- });
12712
+ const inputValue = {
12713
+ query: reconstructQueryString(strings, values).trim(),
12714
+ parameters: values
12600
12715
  };
12716
+ const originalThen = query.then.bind(query);
12717
+ this._wrapThenMethod(query, originalThen, inputValue, creationContext, {
12718
+ name: "postgres.query",
12719
+ submodule: "query",
12720
+ operationType: "sql"
12721
+ });
12722
+ this._wrapExecuteMethod(query);
12723
+ this._wrapCursorMethod(query, inputValue, creationContext);
12724
+ this._wrapForEachMethod(query, inputValue, creationContext);
12601
12725
  return query;
12602
12726
  }
12603
12727
  _handleUnsafeQuery(sqlInstance, originalUnsafe, query, parameters, queryOptions) {
@@ -12608,21 +12732,46 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12608
12732
  })();
12609
12733
  const creationContext = import_src$25.context.active();
12610
12734
  const originalThen = unsafeQuery.then.bind(unsafeQuery);
12611
- const self = this;
12612
12735
  const inputValue = {
12613
12736
  query: query.trim(),
12614
12737
  parameters: parameters || [],
12615
12738
  options: queryOptions
12616
12739
  };
12617
- unsafeQuery.then = function(onFulfilled, onRejected) {
12740
+ this._wrapThenMethod(unsafeQuery, originalThen, inputValue, creationContext, {
12741
+ name: "postgres.unsafe",
12742
+ submodule: "unsafe",
12743
+ operationType: "unsafe"
12744
+ });
12745
+ this._wrapExecuteMethod(unsafeQuery);
12746
+ this._wrapCursorMethod(unsafeQuery, inputValue, creationContext);
12747
+ this._wrapForEachMethod(unsafeQuery, inputValue, creationContext);
12748
+ return unsafeQuery;
12749
+ }
12750
+ _handleFileQuery(sqlInstance, originalFile, path$2, parameters, queryOptions) {
12751
+ const fileQuery = (() => {
12752
+ if (queryOptions !== void 0) return originalFile.call(sqlInstance, path$2, parameters, queryOptions);
12753
+ else if (parameters !== void 0) return originalFile.call(sqlInstance, path$2, parameters);
12754
+ else return originalFile.call(sqlInstance, path$2);
12755
+ })();
12756
+ const creationContext = import_src$25.context.active();
12757
+ const originalThen = fileQuery.then.bind(fileQuery);
12758
+ const self = this;
12759
+ const inputValue = {
12760
+ query: path$2,
12761
+ parameters: parameters || [],
12762
+ options: queryOptions
12763
+ };
12764
+ fileQuery.then = function(onFulfilled, onRejected) {
12765
+ if (fileQuery._tuskRecorded) return originalThen(onFulfilled, onRejected);
12766
+ fileQuery._tuskRecorded = true;
12618
12767
  return import_src$25.context.with(creationContext, () => {
12619
12768
  if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
12620
12769
  originalFunctionCall: () => originalThen(onFulfilled, onRejected),
12621
12770
  recordModeHandler: ({ isPreAppStart }) => {
12622
12771
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12623
- name: "postgres.unsafe",
12772
+ name: "postgres.file",
12624
12773
  kind: import_src$25.SpanKind.CLIENT,
12625
- submodule: "unsafe",
12774
+ submodule: "file",
12626
12775
  packageType: PackageType.PG,
12627
12776
  packageName: "postgres",
12628
12777
  instrumentationName: self.INSTRUMENTATION_NAME,
@@ -12631,17 +12780,17 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12631
12780
  }, (spanInfo) => {
12632
12781
  const wrappedOnFulfilled = (result) => {
12633
12782
  try {
12634
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query completed successfully (${SpanUtils.getTraceInfo()})`);
12635
- self._addOutputAttributesToSpan(spanInfo, result);
12783
+ logger.debug(`[PostgresInstrumentation] Postgres file query completed successfully (${SpanUtils.getTraceInfo()})`);
12784
+ addOutputAttributesToSpan(spanInfo, result);
12636
12785
  SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12637
12786
  } catch (error) {
12638
- logger.error(`[PostgresInstrumentation] error processing unsafe query response:`, error);
12787
+ logger.error(`[PostgresInstrumentation] error processing file query response:`, error);
12639
12788
  }
12640
12789
  return onFulfilled ? onFulfilled(result) : result;
12641
12790
  };
12642
12791
  const wrappedOnRejected = (error) => {
12643
12792
  try {
12644
- logger.debug(`[PostgresInstrumentation] Postgres unsafe query error: ${error.message}`);
12793
+ logger.debug(`[PostgresInstrumentation] Postgres file query error: ${error.message}`);
12645
12794
  SpanUtils.endSpan(spanInfo.span, {
12646
12795
  code: import_src$25.SpanStatusCode.ERROR,
12647
12796
  message: error.message
@@ -12667,22 +12816,24 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12667
12816
  isServerRequest: false,
12668
12817
  replayModeHandler: () => {
12669
12818
  return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
12670
- name: "postgres.unsafe",
12819
+ name: "postgres.file",
12671
12820
  kind: import_src$25.SpanKind.CLIENT,
12672
- submodule: "unsafe",
12821
+ submodule: "file",
12673
12822
  packageType: PackageType.PG,
12674
12823
  packageName: "postgres",
12675
12824
  instrumentationName: self.INSTRUMENTATION_NAME,
12676
12825
  inputValue,
12677
- isPreAppStart: false
12826
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
12678
12827
  }, async (spanInfo) => {
12679
- const mockedResult = await self.handleReplayUnsafeQuery({
12828
+ const mockedResult = await self._handleReplayQueryOperation({
12680
12829
  inputValue,
12681
12830
  spanInfo,
12682
- submodule: "unsafe",
12683
- name: "postgres.unsafe",
12684
- stackTrace
12831
+ submodule: "file",
12832
+ name: "postgres.file",
12833
+ stackTrace,
12834
+ operationType: "file"
12685
12835
  });
12836
+ if (!mockedResult) throw new Error(`No mock data found for Postgres file query: ${inputValue.query}`);
12686
12837
  return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
12687
12838
  });
12688
12839
  }
@@ -12690,16 +12841,45 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12690
12841
  } else return originalThen(onFulfilled, onRejected);
12691
12842
  });
12692
12843
  };
12693
- return unsafeQuery;
12844
+ const originalExecute = fileQuery.execute ? fileQuery.execute.bind(fileQuery) : void 0;
12845
+ if (originalExecute) fileQuery.execute = function() {
12846
+ if (self.mode === TuskDriftMode.REPLAY) return this;
12847
+ else return originalExecute.call(this);
12848
+ };
12849
+ return fileQuery;
12850
+ }
12851
+ /**
12852
+ * Wraps a transaction callback to ensure the inner SQL instance is instrumented.
12853
+ * This is necessary because postgres.js creates a new SQL instance inside begin()
12854
+ * that would otherwise bypass instrumentation.
12855
+ */
12856
+ _wrapTransactionCallback(transactionCallback) {
12857
+ const self = this;
12858
+ return (transactionSql) => {
12859
+ const wrappedSql = self._wrapSqlInstance(transactionSql);
12860
+ if (typeof transactionSql.savepoint === "function") {
12861
+ const originalSavepoint = transactionSql.savepoint;
12862
+ wrappedSql.savepoint = function(nameOrFn, fn) {
12863
+ const savepointCallback = typeof nameOrFn === "function" ? nameOrFn : fn;
12864
+ const savepointName = typeof nameOrFn === "string" ? nameOrFn : void 0;
12865
+ const wrappedSavepointCallback = self._wrapTransactionCallback(savepointCallback);
12866
+ if (savepointName) return originalSavepoint.call(transactionSql, savepointName, wrappedSavepointCallback);
12867
+ else return originalSavepoint.call(transactionSql, wrappedSavepointCallback);
12868
+ };
12869
+ }
12870
+ if (typeof transactionSql.prepare === "function") wrappedSql.prepare = transactionSql.prepare.bind(transactionSql);
12871
+ return transactionCallback(wrappedSql);
12872
+ };
12694
12873
  }
12695
12874
  _handleBeginTransaction(sqlInstance, originalBegin, options, transactionCallback) {
12696
12875
  const inputValue = {
12697
12876
  query: "BEGIN",
12698
12877
  options: options ? { transactionOptions: options } : void 0
12699
12878
  };
12879
+ const wrappedCallback = transactionCallback ? this._wrapTransactionCallback(transactionCallback) : void 0;
12700
12880
  const executeBegin = () => {
12701
- if (options && transactionCallback) return originalBegin.call(sqlInstance, options, transactionCallback);
12702
- else if (transactionCallback) return originalBegin.call(sqlInstance, transactionCallback);
12881
+ if (options && wrappedCallback) return originalBegin.call(sqlInstance, options, wrappedCallback);
12882
+ else if (wrappedCallback) return originalBegin.call(sqlInstance, wrappedCallback);
12703
12883
  else return originalBegin.call(sqlInstance, options || void 0);
12704
12884
  };
12705
12885
  if (this.mode === TuskDriftMode.REPLAY) {
@@ -12716,9 +12896,9 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12716
12896
  packageName: "postgres",
12717
12897
  instrumentationName: this.INSTRUMENTATION_NAME,
12718
12898
  inputValue,
12719
- isPreAppStart: false
12899
+ isPreAppStart: this.tuskDrift.isAppReady() ? false : true
12720
12900
  }, (spanInfo) => {
12721
- return this._handleReplayBeginTransaction(spanInfo, options, stackTrace);
12901
+ return this._handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback);
12722
12902
  });
12723
12903
  }
12724
12904
  });
@@ -12743,55 +12923,47 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12743
12923
  else return executeBegin();
12744
12924
  }
12745
12925
  _handleRecordBeginTransaction(spanInfo, executeBegin) {
12746
- const promise = executeBegin();
12747
- promise.finally(() => {
12748
- promise.then((result) => {
12749
- logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12750
- try {
12751
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12752
- status: "committed",
12753
- result
12754
- } });
12755
- SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12756
- } catch (error) {
12757
- logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12758
- }
12759
- }).catch((error) => {
12760
- logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12761
- try {
12762
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12763
- status: "rolled_back",
12764
- error: error.message
12765
- } });
12766
- SpanUtils.endSpan(spanInfo.span, {
12767
- code: import_src$25.SpanStatusCode.ERROR,
12768
- message: error.message
12769
- });
12770
- } catch (spanError) {
12771
- logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12772
- }
12773
- });
12926
+ return executeBegin().then((result) => {
12927
+ logger.debug(`[PostgresInstrumentation] Postgres transaction completed successfully (${SpanUtils.getTraceInfo()})`);
12928
+ try {
12929
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12930
+ status: "committed",
12931
+ result
12932
+ } });
12933
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
12934
+ } catch (error) {
12935
+ logger.error(`[PostgresInstrumentation] error processing transaction response:`, error);
12936
+ }
12937
+ return result;
12938
+ }).catch((error) => {
12939
+ logger.debug(`[PostgresInstrumentation] Postgres transaction error (rolled back): ${error.message} (${SpanUtils.getTraceInfo()})`);
12940
+ try {
12941
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
12942
+ status: "rolled_back",
12943
+ error: error.message
12944
+ } });
12945
+ SpanUtils.endSpan(spanInfo.span, {
12946
+ code: import_src$25.SpanStatusCode.ERROR,
12947
+ message: error.message
12948
+ });
12949
+ } catch (spanError) {
12950
+ logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
12951
+ }
12952
+ throw error;
12774
12953
  });
12775
- return promise;
12776
12954
  }
12777
- async _handleReplayBeginTransaction(spanInfo, options, stackTrace) {
12955
+ async _handleReplayBeginTransaction(spanInfo, options, stackTrace, wrappedCallback) {
12778
12956
  logger.debug(`[PostgresInstrumentation] Replaying Postgres transaction`);
12779
- const mockData = await findMockResponseAsync({
12780
- mockRequestData: {
12781
- traceId: spanInfo.traceId,
12782
- spanId: spanInfo.spanId,
12783
- name: "postgres.begin",
12784
- inputValue: createMockInputValue({
12785
- query: "BEGIN",
12786
- options: options ? { transactionOptions: options } : void 0
12787
- }),
12788
- packageName: "postgres",
12789
- instrumentationName: this.INSTRUMENTATION_NAME,
12790
- submoduleName: "transaction",
12791
- kind: import_src$25.SpanKind.CLIENT,
12792
- stackTrace
12793
- },
12794
- tuskDrift: this.tuskDrift
12957
+ const transactionInputValue = {
12958
+ query: "BEGIN",
12959
+ options: options ? { transactionOptions: options } : void 0
12960
+ };
12961
+ const mockData = await this._findMockData({
12962
+ spanInfo,
12963
+ name: "postgres.begin",
12964
+ inputValue: transactionInputValue,
12965
+ submoduleName: "transaction",
12966
+ stackTrace
12795
12967
  });
12796
12968
  if (!mockData) {
12797
12969
  logger.warn(`[PostgresInstrumentation] No mock data found for transaction BEGIN`);
@@ -12799,15 +12971,49 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12799
12971
  }
12800
12972
  logger.debug(`[PostgresInstrumentation] Found mock data for transaction: ${JSON.stringify(mockData)}`);
12801
12973
  const transactionResult = mockData.result;
12802
- if (transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed") return transactionResult.result;
12974
+ const wasCommitted = transactionResult && typeof transactionResult === "object" && "status" in transactionResult && transactionResult.status === "committed";
12975
+ if (!wrappedCallback) if (wasCommitted) return transactionResult.result;
12803
12976
  else {
12804
12977
  const errorMessage = transactionResult && typeof transactionResult === "object" && "error" in transactionResult && transactionResult.error ? transactionResult.error : "Transaction rolled back";
12805
12978
  throw new Error(errorMessage);
12806
12979
  }
12980
+ try {
12981
+ const result = await wrappedCallback(this._createMockTransactionSql());
12982
+ logger.debug(`[PostgresInstrumentation] Replay transaction callback completed with result`);
12983
+ return result;
12984
+ } catch (error) {
12985
+ if (!wasCommitted) throw error;
12986
+ logger.error(`[PostgresInstrumentation] Unexpected error during transaction replay: ${error.message}`);
12987
+ throw error;
12988
+ }
12807
12989
  }
12808
- async handleReplaySqlQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12809
- logger.debug(`[PostgresInstrumentation] Replaying Postgres sql query`);
12810
- const mockData = await findMockResponseAsync({
12990
+ /**
12991
+ * Creates a minimal mock SQL instance for transaction replay.
12992
+ * _wrapSqlInstance will wrap this and handle all the actual REPLAY logic.
12993
+ * The mock just needs to return objects with .then() methods that can be wrapped.
12994
+ */
12995
+ _createMockTransactionSql() {
12996
+ const self = this;
12997
+ const createThenable = () => ({ then: (onFulfilled, onRejected) => Promise.resolve([]).then(onFulfilled, onRejected) });
12998
+ const mockSql = function() {
12999
+ return createThenable();
13000
+ };
13001
+ mockSql.unsafe = function() {
13002
+ return createThenable();
13003
+ };
13004
+ mockSql.savepoint = function(nameOrFn, fn) {
13005
+ const callback = typeof nameOrFn === "function" ? nameOrFn : fn;
13006
+ const nestedMockSql = self._createMockTransactionSql();
13007
+ return Promise.resolve(callback(nestedMockSql));
13008
+ };
13009
+ return mockSql;
13010
+ }
13011
+ /**
13012
+ * Generic helper to find mock data for replay operations.
13013
+ * Consolidates the common findMockResponseAsync pattern used across multiple handlers.
13014
+ */
13015
+ async _findMockData({ spanInfo, name, inputValue, submoduleName, stackTrace }) {
13016
+ return findMockResponseAsync({
12811
13017
  mockRequestData: {
12812
13018
  traceId: spanInfo.traceId,
12813
13019
  spanId: spanInfo.spanId,
@@ -12815,79 +13021,574 @@ var PostgresInstrumentation = class extends TdInstrumentationBase {
12815
13021
  inputValue: createMockInputValue(inputValue),
12816
13022
  packageName: "postgres",
12817
13023
  instrumentationName: this.INSTRUMENTATION_NAME,
12818
- submoduleName: submodule,
13024
+ submoduleName,
12819
13025
  kind: import_src$25.SpanKind.CLIENT,
12820
13026
  stackTrace
12821
13027
  },
12822
13028
  tuskDrift: this.tuskDrift
12823
13029
  });
13030
+ }
13031
+ /**
13032
+ * Helper to end a cursor span with collected rows.
13033
+ * Consolidates common span ending logic used in cursor and forEach operations.
13034
+ */
13035
+ _endCursorSpan(spanInfo, allRows, result, operation = "Cursor") {
13036
+ addOutputAttributesToSpan(spanInfo, Object.assign(allRows, {
13037
+ count: allRows.length,
13038
+ columns: result?.columns,
13039
+ state: result?.state,
13040
+ statement: result?.statement
13041
+ }));
13042
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13043
+ logger.debug(`[PostgresInstrumentation] ${operation} completed, recorded ${allRows.length} rows`);
13044
+ }
13045
+ /**
13046
+ * Generic helper to handle replay for query operations (sql, unsafe, file).
13047
+ * Consolidates common logic for finding mock data and processing results.
13048
+ */
13049
+ async _handleReplayQueryOperation({ inputValue, spanInfo, submodule, name, stackTrace, operationType }) {
13050
+ logger.debug(`[PostgresInstrumentation] Replaying Postgres ${operationType} query`);
13051
+ const mockData = await this._findMockData({
13052
+ spanInfo,
13053
+ name,
13054
+ inputValue,
13055
+ submoduleName: submodule,
13056
+ stackTrace
13057
+ });
12824
13058
  if (!mockData) {
12825
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12826
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres sql query: ${queryText}`);
12827
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres sql query: ${queryText}`);
13059
+ const errorMsg = `[PostgresInstrumentation] No matching mock found for Postgres ${operationType} query: ${inputValue.query || "UNKNOWN_QUERY"}`;
13060
+ logger.warn(errorMsg);
13061
+ throw new Error(errorMsg);
12828
13062
  }
12829
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres sql query: ${JSON.stringify(mockData)}`);
12830
- const processedResult = this.convertPostgresTypes(mockData.result);
12831
- logger.debug(`[PostgresInstrumentation] Sql query processed result: ${JSON.stringify(processedResult)}`);
13063
+ logger.debug(`[PostgresInstrumentation] Found mock data for Postgres ${operationType} query: ${JSON.stringify(mockData)}`);
13064
+ const processedResult = convertPostgresTypes(mockData.result);
13065
+ logger.debug(`[PostgresInstrumentation] ${operationType} query processed result: ${JSON.stringify(processedResult)}`);
12832
13066
  return processedResult;
12833
13067
  }
12834
- async handleReplayUnsafeQuery({ inputValue, spanInfo, submodule, name, stackTrace }) {
12835
- logger.debug(`[PostgresInstrumentation] Replaying Postgres unsafe query`);
12836
- const mockData = await findMockResponseAsync({
12837
- mockRequestData: {
12838
- traceId: spanInfo.traceId,
12839
- spanId: spanInfo.spanId,
12840
- name,
12841
- inputValue: createMockInputValue(inputValue),
12842
- packageName: "postgres",
12843
- instrumentationName: this.INSTRUMENTATION_NAME,
12844
- submoduleName: submodule,
12845
- kind: import_src$25.SpanKind.CLIENT,
12846
- stackTrace
12847
- },
12848
- tuskDrift: this.tuskDrift
12849
- });
12850
- if (!mockData) {
12851
- const queryText = inputValue.query || "UNKNOWN_QUERY";
12852
- logger.warn(`[PostgresInstrumentation] No mock data found for Postgres unsafe query: ${queryText}`);
12853
- throw new Error(`[PostgresInstrumentation] No matching mock found for Postgres unsafe query: ${queryText}`);
12854
- }
12855
- logger.debug(`[PostgresInstrumentation] Found mock data for Postgres unsafe query: ${JSON.stringify(mockData)}`);
12856
- const processedResult = this.convertPostgresTypes(mockData.result);
12857
- logger.debug(`[PostgresInstrumentation] Unsafe query processed result: ${JSON.stringify(processedResult)}`);
12858
- return processedResult;
13068
+ _handleCursorCallbackRecord({ originalCursor, rows, inputValue, creationContext, userCallback }) {
13069
+ const self = this;
13070
+ return import_src$25.context.with(creationContext, () => {
13071
+ return handleRecordMode({
13072
+ originalFunctionCall: () => originalCursor(rows, userCallback),
13073
+ recordModeHandler: ({ isPreAppStart }) => {
13074
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalCursor(rows, userCallback), {
13075
+ name: "postgres.cursor",
13076
+ kind: import_src$25.SpanKind.CLIENT,
13077
+ submodule: "cursor",
13078
+ packageType: PackageType.PG,
13079
+ packageName: "postgres",
13080
+ instrumentationName: self.INSTRUMENTATION_NAME,
13081
+ inputValue,
13082
+ isPreAppStart
13083
+ }, (spanInfo) => {
13084
+ return self._executeAndRecordCursorCallback({
13085
+ originalCursor,
13086
+ rows,
13087
+ userCallback,
13088
+ spanInfo
13089
+ });
13090
+ });
13091
+ },
13092
+ spanKind: import_src$25.SpanKind.CLIENT
13093
+ });
13094
+ });
13095
+ }
13096
+ async _executeAndRecordCursorCallback({ originalCursor, rows, userCallback, spanInfo }) {
13097
+ const allRows = [];
13098
+ try {
13099
+ const wrappedCallback = (batchRows) => {
13100
+ allRows.push(...batchRows);
13101
+ return userCallback(batchRows);
13102
+ };
13103
+ const cursorPromise = originalCursor(rows, wrappedCallback);
13104
+ cursorPromise._tuskRecorded = true;
13105
+ const result = await cursorPromise;
13106
+ if (spanInfo) try {
13107
+ this._endCursorSpan(spanInfo, allRows, result, "Cursor callback");
13108
+ } catch (error) {
13109
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13110
+ }
13111
+ } catch (error) {
13112
+ logger.debug(`[PostgresInstrumentation] Cursor callback error: ${error.message}`);
13113
+ if (spanInfo) try {
13114
+ SpanUtils.endSpan(spanInfo.span, {
13115
+ code: import_src$25.SpanStatusCode.ERROR,
13116
+ message: error.message
13117
+ });
13118
+ } catch (error$1) {
13119
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13120
+ }
13121
+ throw error;
13122
+ }
13123
+ }
13124
+ _handleCursorCallbackReplay({ inputValue, creationContext, cursorBatchSize, userCallback }) {
13125
+ const self = this;
13126
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13127
+ return import_src$25.context.with(creationContext, () => {
13128
+ return handleReplayMode({
13129
+ noOpRequestHandler: () => Promise.resolve(),
13130
+ isServerRequest: false,
13131
+ replayModeHandler: () => {
13132
+ return SpanUtils.createAndExecuteSpan(self.mode, () => Promise.resolve(), {
13133
+ name: "postgres.cursor",
13134
+ kind: import_src$25.SpanKind.CLIENT,
13135
+ submodule: "cursor",
13136
+ packageType: PackageType.PG,
13137
+ packageName: "postgres",
13138
+ instrumentationName: self.INSTRUMENTATION_NAME,
13139
+ inputValue,
13140
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13141
+ }, async (spanInfo) => {
13142
+ try {
13143
+ const mockData = await this._findMockData({
13144
+ spanInfo,
13145
+ name: "postgres.cursor",
13146
+ inputValue,
13147
+ submoduleName: "cursor",
13148
+ stackTrace
13149
+ });
13150
+ if (!mockData) throw new Error(`[PostgresInstrumentation] No matching mock found for cursor query: ${inputValue.query}`);
13151
+ logger.debug(`[PostgresInstrumentation] Found mock data for cursor query: ${JSON.stringify(mockData)}`);
13152
+ const processedResult = convertPostgresTypes(mockData.result);
13153
+ const mockedData = Array.isArray(processedResult) ? processedResult : [];
13154
+ for (let i = 0; i < mockedData.length; i += cursorBatchSize) {
13155
+ const batch = mockedData.slice(i, i + cursorBatchSize);
13156
+ logger.debug(`[PostgresInstrumentation] Cursor replay calling callback with batch of ${batch.length} rows`);
13157
+ await userCallback(batch);
13158
+ }
13159
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13160
+ } catch (error) {
13161
+ logger.debug(`[PostgresInstrumentation] Cursor callback replay error: ${error.message}`);
13162
+ SpanUtils.endSpan(spanInfo.span, {
13163
+ code: import_src$25.SpanStatusCode.ERROR,
13164
+ message: error.message
13165
+ });
13166
+ throw error;
13167
+ }
13168
+ });
13169
+ }
13170
+ });
13171
+ });
13172
+ }
13173
+ _handleCursorRecord({ originalCursor, rows, inputValue, creationContext, queryObject }) {
13174
+ const self = this;
13175
+ return { [Symbol.asyncIterator]() {
13176
+ const iterator = originalCursor(rows)[Symbol.asyncIterator]();
13177
+ let allRows = [];
13178
+ let result;
13179
+ let spanInfo = null;
13180
+ let spanStarted = false;
13181
+ return {
13182
+ async next() {
13183
+ return import_src$25.context.with(creationContext, async () => {
13184
+ if (!spanStarted) {
13185
+ spanStarted = true;
13186
+ let spanInputValue;
13187
+ try {
13188
+ spanInputValue = createSpanInputValue(inputValue);
13189
+ } catch (error) {
13190
+ logger.error(`[PostgresInstrumentation] error creating span input value:`, error);
13191
+ spanInputValue = void 0;
13192
+ }
13193
+ spanInfo = SpanUtils.createSpan({
13194
+ name: "postgres.cursor",
13195
+ kind: import_src$25.SpanKind.CLIENT,
13196
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true,
13197
+ attributes: {
13198
+ [TdSpanAttributes.NAME]: "postgres.cursor",
13199
+ [TdSpanAttributes.PACKAGE_NAME]: "postgres",
13200
+ [TdSpanAttributes.SUBMODULE_NAME]: "cursor",
13201
+ [TdSpanAttributes.INSTRUMENTATION_NAME]: self.INSTRUMENTATION_NAME,
13202
+ [TdSpanAttributes.PACKAGE_TYPE]: PackageType.PG,
13203
+ [TdSpanAttributes.INPUT_VALUE]: spanInputValue,
13204
+ [TdSpanAttributes.IS_PRE_APP_START]: self.tuskDrift.isAppReady() ? false : true
13205
+ }
13206
+ });
13207
+ if (!spanInfo) logger.warn(`[PostgresInstrumentation] Failed to create cursor span in RECORD mode`);
13208
+ }
13209
+ try {
13210
+ result = await iterator.next();
13211
+ if (result.done) {
13212
+ if (spanInfo) try {
13213
+ self._endCursorSpan(spanInfo, allRows, queryObject, "Cursor");
13214
+ } catch (error) {
13215
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13216
+ }
13217
+ return {
13218
+ done: true,
13219
+ value: void 0
13220
+ };
13221
+ }
13222
+ if (Array.isArray(result.value)) allRows.push(...result.value);
13223
+ return {
13224
+ done: false,
13225
+ value: result.value
13226
+ };
13227
+ } catch (error) {
13228
+ if (spanInfo) try {
13229
+ SpanUtils.endSpan(spanInfo.span, {
13230
+ code: import_src$25.SpanStatusCode.ERROR,
13231
+ message: error.message
13232
+ });
13233
+ } catch (error$1) {
13234
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13235
+ }
13236
+ throw error;
13237
+ }
13238
+ });
13239
+ },
13240
+ async return() {
13241
+ if (spanInfo) try {
13242
+ self._endCursorSpan(spanInfo, allRows, queryObject, "Cursor terminated early");
13243
+ } catch (error) {
13244
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13245
+ }
13246
+ if (iterator.return) await iterator.return();
13247
+ return {
13248
+ done: true,
13249
+ value: void 0
13250
+ };
13251
+ }
13252
+ };
13253
+ } };
13254
+ }
13255
+ _handleCursorReplay({ inputValue, creationContext, cursorBatchSize }) {
13256
+ const self = this;
13257
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13258
+ return { [Symbol.asyncIterator]() {
13259
+ let mockedData = null;
13260
+ let currentIndex = 0;
13261
+ let spanInfo = null;
13262
+ let dataFetched = false;
13263
+ return {
13264
+ async next() {
13265
+ return import_src$25.context.with(creationContext, async () => {
13266
+ if (!dataFetched) {
13267
+ dataFetched = true;
13268
+ spanInfo = SpanUtils.createSpan({
13269
+ name: "postgres.cursor",
13270
+ kind: import_src$25.SpanKind.CLIENT,
13271
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true,
13272
+ attributes: {
13273
+ [TdSpanAttributes.NAME]: "postgres.cursor",
13274
+ [TdSpanAttributes.PACKAGE_NAME]: "postgres",
13275
+ [TdSpanAttributes.SUBMODULE_NAME]: "cursor",
13276
+ [TdSpanAttributes.INSTRUMENTATION_NAME]: self.INSTRUMENTATION_NAME,
13277
+ [TdSpanAttributes.PACKAGE_TYPE]: PackageType.PG,
13278
+ [TdSpanAttributes.INPUT_VALUE]: createSpanInputValue(inputValue),
13279
+ [TdSpanAttributes.IS_PRE_APP_START]: self.tuskDrift.isAppReady() ? false : true
13280
+ }
13281
+ });
13282
+ if (!spanInfo) throw new Error(`[PostgresInstrumentation] Failed to create cursor span in REPLAY mode`);
13283
+ const mockData = await self._findMockData({
13284
+ spanInfo,
13285
+ name: "postgres.cursor",
13286
+ inputValue,
13287
+ submoduleName: "cursor",
13288
+ stackTrace
13289
+ });
13290
+ if (!mockData) {
13291
+ SpanUtils.endSpan(spanInfo.span, {
13292
+ code: import_src$25.SpanStatusCode.ERROR,
13293
+ message: "No mock data found"
13294
+ });
13295
+ throw new Error(`[PostgresInstrumentation] No matching mock found for cursor query: ${inputValue.query}`);
13296
+ }
13297
+ logger.debug(`[PostgresInstrumentation] Found mock data for cursor query: ${JSON.stringify(mockData)}`);
13298
+ const processedResult = convertPostgresTypes(mockData.result);
13299
+ mockedData = Array.isArray(processedResult) ? processedResult : [];
13300
+ }
13301
+ if (currentIndex >= mockedData.length) {
13302
+ if (spanInfo) SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13303
+ return {
13304
+ done: true,
13305
+ value: void 0
13306
+ };
13307
+ }
13308
+ const batch = mockedData.slice(currentIndex, currentIndex + cursorBatchSize);
13309
+ currentIndex += batch.length;
13310
+ logger.debug(`[PostgresInstrumentation] Cursor replay returning batch of ${batch.length} rows`);
13311
+ return {
13312
+ done: false,
13313
+ value: batch
13314
+ };
13315
+ });
13316
+ },
13317
+ async return() {
13318
+ if (spanInfo) SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13319
+ return {
13320
+ done: true,
13321
+ value: void 0
13322
+ };
13323
+ }
13324
+ };
13325
+ } };
13326
+ }
13327
+ _handleForEachRecord({ originalForEach, inputValue, creationContext, userCallback }) {
13328
+ const self = this;
13329
+ return import_src$25.context.with(creationContext, () => {
13330
+ return handleRecordMode({
13331
+ originalFunctionCall: () => originalForEach(userCallback),
13332
+ recordModeHandler: ({ isPreAppStart }) => {
13333
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalForEach(userCallback), {
13334
+ name: "postgres.query",
13335
+ kind: import_src$25.SpanKind.CLIENT,
13336
+ submodule: "query",
13337
+ packageType: PackageType.PG,
13338
+ packageName: "postgres",
13339
+ instrumentationName: self.INSTRUMENTATION_NAME,
13340
+ inputValue,
13341
+ isPreAppStart
13342
+ }, async (spanInfo) => {
13343
+ const allRows = [];
13344
+ const wrappedCallback = (row, result) => {
13345
+ allRows.push(row);
13346
+ return userCallback(row, result);
13347
+ };
13348
+ try {
13349
+ const result = await originalForEach(wrappedCallback);
13350
+ try {
13351
+ self._endCursorSpan(spanInfo, allRows, result, "forEach");
13352
+ } catch (error) {
13353
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error);
13354
+ }
13355
+ return result;
13356
+ } catch (error) {
13357
+ try {
13358
+ SpanUtils.endSpan(spanInfo.span, {
13359
+ code: import_src$25.SpanStatusCode.ERROR,
13360
+ message: error.message
13361
+ });
13362
+ } catch (error$1) {
13363
+ logger.error(`[PostgresInstrumentation] error ending cursor span:`, error$1);
13364
+ }
13365
+ throw error;
13366
+ }
13367
+ });
13368
+ },
13369
+ spanKind: import_src$25.SpanKind.CLIENT
13370
+ });
13371
+ });
13372
+ }
13373
+ _handleForEachReplay({ inputValue, creationContext, userCallback }) {
13374
+ const self = this;
13375
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13376
+ return import_src$25.context.with(creationContext, () => {
13377
+ return handleReplayMode({
13378
+ noOpRequestHandler: () => Promise.resolve(Object.assign([], {
13379
+ count: 0,
13380
+ command: null
13381
+ })),
13382
+ isServerRequest: false,
13383
+ replayModeHandler: () => {
13384
+ return SpanUtils.createAndExecuteSpan(self.mode, () => Promise.resolve(Object.assign([], {
13385
+ count: 0,
13386
+ command: null
13387
+ })), {
13388
+ name: "postgres.query",
13389
+ kind: import_src$25.SpanKind.CLIENT,
13390
+ submodule: "query",
13391
+ packageType: PackageType.PG,
13392
+ packageName: "postgres",
13393
+ instrumentationName: self.INSTRUMENTATION_NAME,
13394
+ inputValue,
13395
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13396
+ }, async (spanInfo) => {
13397
+ try {
13398
+ const mockedResult = await self._handleReplayQueryOperation({
13399
+ inputValue,
13400
+ spanInfo,
13401
+ submodule: "query",
13402
+ name: "postgres.query",
13403
+ stackTrace,
13404
+ operationType: "forEach"
13405
+ });
13406
+ const mockedRows = Array.isArray(mockedResult) ? mockedResult : [];
13407
+ logger.debug(`[PostgresInstrumentation] forEach replay: calling callback with ${mockedRows.length} mocked rows`);
13408
+ for (const row of mockedRows) userCallback(row, mockedResult);
13409
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13410
+ return Object.assign([], {
13411
+ count: mockedRows.length,
13412
+ command: null
13413
+ });
13414
+ } catch (error) {
13415
+ logger.debug(`[PostgresInstrumentation] forEach replay error: ${error.message}`);
13416
+ SpanUtils.endSpan(spanInfo.span, {
13417
+ code: import_src$25.SpanStatusCode.ERROR,
13418
+ message: error.message
13419
+ });
13420
+ throw error;
13421
+ }
13422
+ });
13423
+ }
13424
+ });
13425
+ });
13426
+ }
13427
+ /**
13428
+ * Wraps a query's .then() method to add instrumentation.
13429
+ * This is reusable for both sql template literals and unsafe() queries.
13430
+ */
13431
+ _wrapThenMethod(query, originalThen, inputValue, creationContext, spanConfig) {
13432
+ const self = this;
13433
+ query.then = function(onFulfilled, onRejected) {
13434
+ if (query._forEachCalled) return originalThen(onFulfilled, onRejected);
13435
+ if (query._tuskRecorded) return originalThen(onFulfilled, onRejected);
13436
+ query._tuskRecorded = true;
13437
+ return import_src$25.context.with(creationContext, () => {
13438
+ if (self.mode === TuskDriftMode.RECORD) return handleRecordMode({
13439
+ originalFunctionCall: () => originalThen(onFulfilled, onRejected),
13440
+ recordModeHandler: ({ isPreAppStart }) => {
13441
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
13442
+ name: spanConfig.name,
13443
+ kind: import_src$25.SpanKind.CLIENT,
13444
+ submodule: spanConfig.submodule,
13445
+ packageType: PackageType.PG,
13446
+ packageName: "postgres",
13447
+ instrumentationName: self.INSTRUMENTATION_NAME,
13448
+ inputValue,
13449
+ isPreAppStart
13450
+ }, (spanInfo) => {
13451
+ const wrappedOnFulfilled = (result) => {
13452
+ try {
13453
+ logger.debug(`[PostgresInstrumentation] Postgres ${spanConfig.operationType} query completed successfully (${SpanUtils.getTraceInfo()})`);
13454
+ addOutputAttributesToSpan(spanInfo, result);
13455
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$25.SpanStatusCode.OK });
13456
+ } catch (error) {
13457
+ logger.error(`[PostgresInstrumentation] error processing ${spanConfig.operationType} query response:`, error);
13458
+ }
13459
+ return onFulfilled ? onFulfilled(result) : result;
13460
+ };
13461
+ const wrappedOnRejected = (error) => {
13462
+ try {
13463
+ logger.debug(`[PostgresInstrumentation] Postgres ${spanConfig.operationType} query error: ${error.message}`);
13464
+ SpanUtils.endSpan(spanInfo.span, {
13465
+ code: import_src$25.SpanStatusCode.ERROR,
13466
+ message: error.message
13467
+ });
13468
+ } catch (spanError) {
13469
+ logger.error(`[PostgresInstrumentation] error ending span:`, spanError);
13470
+ }
13471
+ if (onRejected) return onRejected(error);
13472
+ throw error;
13473
+ };
13474
+ return originalThen(wrappedOnFulfilled, wrappedOnRejected);
13475
+ });
13476
+ },
13477
+ spanKind: import_src$25.SpanKind.CLIENT
13478
+ });
13479
+ else if (self.mode === TuskDriftMode.REPLAY) {
13480
+ const stackTrace = captureStackTrace(["PostgresInstrumentation"]);
13481
+ return handleReplayMode({
13482
+ noOpRequestHandler: () => Promise.resolve(Object.assign([], {
13483
+ count: 0,
13484
+ command: null
13485
+ })),
13486
+ isServerRequest: false,
13487
+ replayModeHandler: () => {
13488
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalThen(onFulfilled, onRejected), {
13489
+ name: spanConfig.name,
13490
+ kind: import_src$25.SpanKind.CLIENT,
13491
+ submodule: spanConfig.submodule,
13492
+ packageType: PackageType.PG,
13493
+ packageName: "postgres",
13494
+ instrumentationName: self.INSTRUMENTATION_NAME,
13495
+ inputValue,
13496
+ isPreAppStart: self.tuskDrift.isAppReady() ? false : true
13497
+ }, async (spanInfo) => {
13498
+ const mockedResult = await self._handleReplayQueryOperation({
13499
+ inputValue,
13500
+ spanInfo,
13501
+ submodule: spanConfig.submodule,
13502
+ name: spanConfig.name,
13503
+ stackTrace,
13504
+ operationType: spanConfig.operationType
13505
+ });
13506
+ return onFulfilled ? onFulfilled(mockedResult) : mockedResult;
13507
+ });
13508
+ }
13509
+ });
13510
+ } else return originalThen(onFulfilled, onRejected);
13511
+ });
13512
+ };
13513
+ }
13514
+ /**
13515
+ * Wraps a query's .execute() method to prevent TCP calls in REPLAY mode.
13516
+ * This is reusable for both sql template literals and unsafe() queries.
13517
+ */
13518
+ _wrapExecuteMethod(query) {
13519
+ const self = this;
13520
+ const originalExecute = query.execute ? query.execute.bind(query) : void 0;
13521
+ if (originalExecute) query.execute = function() {
13522
+ if (self.mode === TuskDriftMode.REPLAY) return this;
13523
+ else return originalExecute.call(this);
13524
+ };
12859
13525
  }
12860
- convertPostgresTypes(result) {
12861
- if (!isPostgresOutputValueType(result)) {
12862
- logger.error(`[PostgresInstrumentation] output value is not of type PostgresOutputValueType`, result);
12863
- return;
12864
- }
12865
- const { rows, count, command } = result;
12866
- const resultArray = Array.from(rows || []);
12867
- Object.defineProperties(resultArray, {
12868
- count: {
12869
- value: count !== void 0 ? count : null,
12870
- writable: true,
12871
- enumerable: false
12872
- },
12873
- command: {
12874
- value: command || null,
12875
- writable: true,
12876
- enumerable: false
12877
- }
12878
- });
12879
- return resultArray;
13526
+ /**
13527
+ * Wraps a query's cursor() method to add instrumentation.
13528
+ * This is reusable for both sql template literals and unsafe() queries.
13529
+ */
13530
+ _wrapCursorMethod(query, inputValue, creationContext) {
13531
+ if (typeof query.cursor !== "function") return;
13532
+ const self = this;
13533
+ const originalCursor = query.cursor.bind(query);
13534
+ query.cursor = function(rows, fn) {
13535
+ if (typeof rows === "function") {
13536
+ fn = rows;
13537
+ rows = 1;
13538
+ }
13539
+ if (!rows) rows = 1;
13540
+ if (typeof fn === "function") if (self.mode === TuskDriftMode.RECORD) return self._handleCursorCallbackRecord({
13541
+ originalCursor,
13542
+ rows,
13543
+ inputValue,
13544
+ creationContext,
13545
+ userCallback: fn
13546
+ });
13547
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleCursorCallbackReplay({
13548
+ inputValue,
13549
+ creationContext,
13550
+ cursorBatchSize: rows,
13551
+ userCallback: fn
13552
+ });
13553
+ else return originalCursor(rows, fn);
13554
+ if (self.mode === TuskDriftMode.RECORD) return self._handleCursorRecord({
13555
+ originalCursor,
13556
+ rows,
13557
+ inputValue,
13558
+ creationContext,
13559
+ queryObject: this
13560
+ });
13561
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleCursorReplay({
13562
+ inputValue,
13563
+ creationContext,
13564
+ cursorBatchSize: rows
13565
+ });
13566
+ else return originalCursor(rows);
13567
+ };
12880
13568
  }
12881
- _addOutputAttributesToSpan(spanInfo, result) {
12882
- if (!result) return;
12883
- const isArray$1 = Array.isArray(result);
12884
- logger.debug(`[PostgresInstrumentation] Adding output attributes to span for ${isArray$1 ? "array" : "object"} result`);
12885
- const outputValue = {
12886
- rows: isArray$1 ? Array.from(result) : result.rows || [],
12887
- count: result.count !== void 0 && result.count !== null ? result.count : void 0,
12888
- command: result.command || void 0
13569
+ /**
13570
+ * Wraps a query's forEach() method to add instrumentation.
13571
+ * This is reusable for both sql template literals and unsafe() queries.
13572
+ */
13573
+ _wrapForEachMethod(query, inputValue, creationContext) {
13574
+ if (typeof query.forEach !== "function") return;
13575
+ const self = this;
13576
+ const originalForEach = query.forEach.bind(query);
13577
+ query.forEach = function(fn) {
13578
+ query._forEachCalled = true;
13579
+ if (self.mode === TuskDriftMode.RECORD) return self._handleForEachRecord({
13580
+ originalForEach,
13581
+ inputValue,
13582
+ creationContext,
13583
+ userCallback: fn
13584
+ });
13585
+ else if (self.mode === TuskDriftMode.REPLAY) return self._handleForEachReplay({
13586
+ inputValue,
13587
+ creationContext,
13588
+ userCallback: fn
13589
+ });
13590
+ else return originalForEach(fn);
12889
13591
  };
12890
- SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
12891
13592
  }
12892
13593
  _wrap(target, propertyName, wrapper) {
12893
13594
  wrap(target, propertyName, wrapper);
@@ -12910,8 +13611,9 @@ function isMysqlOkPacket(result) {
12910
13611
  * Extends EventEmitter to properly handle all connection methods and events
12911
13612
  */
12912
13613
  var TdMysqlConnectionMock = class extends EventEmitter {
12913
- constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo) {
13614
+ constructor(mysqlInstrumentation, clientType = "poolConnection", spanInfo, pool) {
12914
13615
  super();
13616
+ this._pool = null;
12915
13617
  this.threadId = null;
12916
13618
  this.config = {
12917
13619
  host: "localhost",
@@ -12923,6 +13625,7 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12923
13625
  this.spanInfo = spanInfo;
12924
13626
  this.clientType = clientType;
12925
13627
  this.threadId = 1;
13628
+ this._pool = pool;
12926
13629
  }
12927
13630
  query(...args) {
12928
13631
  logger.debug(`[TdMysqlConnectionMock] Mock connection query intercepted in REPLAY mode`);
@@ -12930,7 +13633,13 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12930
13633
  let values;
12931
13634
  let callback;
12932
13635
  let options = {};
12933
- if (typeof args[0] === "string") {
13636
+ const firstArg = args[0];
13637
+ if (firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function") {
13638
+ sql = firstArg.sql;
13639
+ values = firstArg.values;
13640
+ callback = firstArg._callback;
13641
+ options = { nestTables: firstArg.nestTables };
13642
+ } else if (typeof args[0] === "string") {
12934
13643
  sql = args[0];
12935
13644
  if (typeof args[1] === "function") callback = args[1];
12936
13645
  else if (Array.isArray(args[1])) {
@@ -12982,6 +13691,7 @@ var TdMysqlConnectionMock = class extends EventEmitter {
12982
13691
  }
12983
13692
  }
12984
13693
  release() {
13694
+ if (this._pool) this._pool.emit("release", this);
12985
13695
  this.emit("end");
12986
13696
  }
12987
13697
  destroy() {
@@ -13006,19 +13716,22 @@ var TdMysqlConnectionMock = class extends EventEmitter {
13006
13716
  return;
13007
13717
  }
13008
13718
  }
13009
- beginTransaction(callback) {
13719
+ beginTransaction(optionsOrCallback, callbackArg) {
13720
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
13010
13721
  if (callback) {
13011
13722
  process.nextTick(() => callback(null));
13012
13723
  return;
13013
13724
  }
13014
13725
  }
13015
- commit(callback) {
13726
+ commit(optionsOrCallback, callbackArg) {
13727
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
13016
13728
  if (callback) {
13017
13729
  process.nextTick(() => callback(null));
13018
13730
  return;
13019
13731
  }
13020
13732
  }
13021
- rollback(callback) {
13733
+ rollback(optionsOrCallback, callbackArg) {
13734
+ const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : callbackArg;
13022
13735
  if (callback) {
13023
13736
  process.nextTick(() => callback(null));
13024
13737
  return;
@@ -13214,6 +13927,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13214
13927
  name: "mysql/lib/Pool.js",
13215
13928
  supportedVersions: ["2.*"],
13216
13929
  patch: (moduleExports) => this._patchPoolFile(moduleExports)
13930
+ }),
13931
+ new TdInstrumentationNodeModuleFile({
13932
+ name: "mysql/lib/PoolNamespace.js",
13933
+ supportedVersions: ["2.*"],
13934
+ patch: (moduleExports) => this._patchPoolNamespaceFile(moduleExports)
13217
13935
  })
13218
13936
  ]
13219
13937
  })];
@@ -13353,12 +14071,40 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13353
14071
  return PoolClass;
13354
14072
  }
13355
14073
  /**
14074
+ * Patch PoolNamespace.prototype methods at the file level
14075
+ * This handles queries made via poolCluster.of("pattern").query()
14076
+ */
14077
+ _patchPoolNamespaceFile(PoolNamespaceClass) {
14078
+ logger.debug(`[MysqlInstrumentation] Patching PoolNamespace class (file-based)`);
14079
+ if (this.isModulePatched(PoolNamespaceClass)) {
14080
+ logger.debug(`[MysqlInstrumentation] PoolNamespace class already patched, skipping`);
14081
+ return PoolNamespaceClass;
14082
+ }
14083
+ if (PoolNamespaceClass.prototype && PoolNamespaceClass.prototype.query) {
14084
+ if (!isWrapped$1(PoolNamespaceClass.prototype.query)) {
14085
+ this._wrap(PoolNamespaceClass.prototype, "query", this._getPoolNamespaceQueryPatchFn());
14086
+ logger.debug(`[MysqlInstrumentation] Wrapped PoolNamespace.prototype.query`);
14087
+ }
14088
+ }
14089
+ if (PoolNamespaceClass.prototype && PoolNamespaceClass.prototype.getConnection) {
14090
+ if (!isWrapped$1(PoolNamespaceClass.prototype.getConnection)) {
14091
+ this._wrap(PoolNamespaceClass.prototype, "getConnection", this._getPoolNamespaceGetConnectionPatchFn());
14092
+ logger.debug(`[MysqlInstrumentation] Wrapped PoolNamespace.prototype.getConnection`);
14093
+ }
14094
+ }
14095
+ this.markModuleAsPatched(PoolNamespaceClass);
14096
+ logger.debug(`[MysqlInstrumentation] PoolNamespace class patching complete`);
14097
+ return PoolNamespaceClass;
14098
+ }
14099
+ /**
13356
14100
  * Get wrapper function for query method (prototype-level patching)
13357
14101
  */
13358
14102
  _getQueryPatchFn() {
13359
14103
  const self = this;
13360
14104
  return (originalQuery) => {
13361
14105
  return function query(...args) {
14106
+ const firstArg = args[0];
14107
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13362
14108
  let sql;
13363
14109
  let values;
13364
14110
  let callback;
@@ -13369,6 +14115,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13369
14115
  values = queryObj.values;
13370
14116
  options = { nestTables: queryObj.nestTables };
13371
14117
  callback = args.find((arg) => typeof arg === "function");
14118
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13372
14119
  } catch (error) {
13373
14120
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13374
14121
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13379,7 +14126,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13379
14126
  values,
13380
14127
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13381
14128
  };
13382
- const isEventEmitterMode = !callback;
14129
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13383
14130
  if (self.mode === TuskDriftMode.REPLAY) {
13384
14131
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13385
14132
  return handleReplayMode({
@@ -13475,11 +14222,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13475
14222
  _getBeginTransactionPatchFn() {
13476
14223
  const self = this;
13477
14224
  return (originalBeginTransaction) => {
13478
- return function beginTransaction(callback) {
14225
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14226
+ let actualCallback;
14227
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14228
+ else actualCallback = callbackArg;
13479
14229
  const inputValue = { query: "BEGIN" };
13480
14230
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13481
14231
  noOpRequestHandler: () => {
13482
- if (callback) setImmediate(() => callback(null));
14232
+ if (actualCallback) setImmediate(() => actualCallback(null));
13483
14233
  },
13484
14234
  isServerRequest: false,
13485
14235
  replayModeHandler: () => {
@@ -13493,7 +14243,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13493
14243
  inputValue,
13494
14244
  isPreAppStart: false
13495
14245
  }, (spanInfo) => {
13496
- return self._handleReplayTransaction(inputValue, callback);
14246
+ return self._handleReplayTransaction(inputValue, actualCallback);
13497
14247
  });
13498
14248
  }
13499
14249
  });
@@ -13510,7 +14260,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13510
14260
  inputValue,
13511
14261
  isPreAppStart
13512
14262
  }, (spanInfo) => {
13513
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, callback);
14263
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, this, arguments, actualCallback);
13514
14264
  });
13515
14265
  },
13516
14266
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13525,11 +14275,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13525
14275
  _getCommitPatchFn() {
13526
14276
  const self = this;
13527
14277
  return (originalCommit) => {
13528
- return function commit(callback) {
14278
+ return function commit(optionsOrCallback, callbackArg) {
14279
+ let actualCallback;
14280
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14281
+ else actualCallback = callbackArg;
13529
14282
  const inputValue = { query: "COMMIT" };
13530
14283
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13531
14284
  noOpRequestHandler: () => {
13532
- if (callback) setImmediate(() => callback(null));
14285
+ if (actualCallback) setImmediate(() => actualCallback(null));
13533
14286
  },
13534
14287
  isServerRequest: false,
13535
14288
  replayModeHandler: () => {
@@ -13543,7 +14296,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13543
14296
  inputValue,
13544
14297
  isPreAppStart: false
13545
14298
  }, (spanInfo) => {
13546
- return self._handleReplayTransaction(inputValue, callback);
14299
+ return self._handleReplayTransaction(inputValue, actualCallback);
13547
14300
  });
13548
14301
  }
13549
14302
  });
@@ -13560,7 +14313,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13560
14313
  inputValue,
13561
14314
  isPreAppStart
13562
14315
  }, (spanInfo) => {
13563
- return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, callback);
14316
+ return self._handleRecordTransaction(spanInfo, originalCommit, this, arguments, actualCallback);
13564
14317
  });
13565
14318
  },
13566
14319
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13575,11 +14328,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13575
14328
  _getRollbackPatchFn() {
13576
14329
  const self = this;
13577
14330
  return (originalRollback) => {
13578
- return function rollback(callback) {
14331
+ return function rollback(optionsOrCallback, callbackArg) {
14332
+ let actualCallback;
14333
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14334
+ else actualCallback = callbackArg;
13579
14335
  const inputValue = { query: "ROLLBACK" };
13580
14336
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13581
14337
  noOpRequestHandler: () => {
13582
- if (callback) setImmediate(() => callback(null));
14338
+ if (actualCallback) setImmediate(() => actualCallback(null));
13583
14339
  },
13584
14340
  isServerRequest: false,
13585
14341
  replayModeHandler: () => {
@@ -13593,7 +14349,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13593
14349
  inputValue,
13594
14350
  isPreAppStart: false
13595
14351
  }, (spanInfo) => {
13596
- return self._handleReplayTransaction(inputValue, callback);
14352
+ return self._handleReplayTransaction(inputValue, actualCallback);
13597
14353
  });
13598
14354
  }
13599
14355
  });
@@ -13610,7 +14366,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13610
14366
  inputValue,
13611
14367
  isPreAppStart
13612
14368
  }, (spanInfo) => {
13613
- return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, callback);
14369
+ return self._handleRecordTransaction(spanInfo, originalRollback, this, arguments, actualCallback);
13614
14370
  });
13615
14371
  },
13616
14372
  spanKind: import_src$23.SpanKind.CLIENT
@@ -13778,9 +14534,10 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13778
14534
  return (originalGetConnection) => {
13779
14535
  return function getConnection(callback) {
13780
14536
  const inputValue = { clientType: "pool" };
14537
+ const pool = this;
13781
14538
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
13782
14539
  noOpRequestHandler: () => {
13783
- return self._handleNoOpReplayGetConnection(callback);
14540
+ return self._handleNoOpReplayGetConnection(pool, callback);
13784
14541
  },
13785
14542
  isServerRequest: false,
13786
14543
  replayModeHandler: () => {
@@ -13794,7 +14551,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13794
14551
  inputValue,
13795
14552
  isPreAppStart: false
13796
14553
  }, (spanInfo) => {
13797
- return self._handleReplayPoolGetConnection(spanInfo, callback);
14554
+ return self._handleReplayPoolGetConnection(pool, spanInfo, callback);
13798
14555
  });
13799
14556
  }
13800
14557
  });
@@ -13824,6 +14581,8 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13824
14581
  const self = this;
13825
14582
  return (originalQuery) => {
13826
14583
  return function query(...args) {
14584
+ const firstArg = args[0];
14585
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
13827
14586
  let sql;
13828
14587
  let values;
13829
14588
  let callback;
@@ -13834,6 +14593,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13834
14593
  values = queryObj.values;
13835
14594
  options = { nestTables: queryObj.nestTables };
13836
14595
  callback = args.find((arg) => typeof arg === "function");
14596
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
13837
14597
  } catch (error) {
13838
14598
  logger.debug(`[MysqlInstrumentation] Error using createQuery, falling back to manual parsing:`, error);
13839
14599
  ({sql, values, callback, options} = self._parseQueryArgs(args));
@@ -13844,7 +14604,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13844
14604
  values,
13845
14605
  options: options.nestTables ? { nestTables: options.nestTables } : void 0
13846
14606
  };
13847
- const isEventEmitterMode = !callback;
14607
+ const isEventEmitterMode = !callback && !hasInternalCallback;
13848
14608
  if (self.mode === TuskDriftMode.REPLAY) {
13849
14609
  const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
13850
14610
  return handleReplayMode({
@@ -13946,6 +14706,33 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
13946
14706
  });
13947
14707
  return queryEmitter;
13948
14708
  } else {
14709
+ const queryObject = args[0];
14710
+ if (queryObject && typeof queryObject === "object" && typeof queryObject._callback === "function") {
14711
+ const originalCallback$1 = queryObject._callback;
14712
+ queryObject._callback = function(err, results, fields) {
14713
+ if (err) try {
14714
+ SpanUtils.endSpan(spanInfo.span, {
14715
+ code: import_src$23.SpanStatusCode.ERROR,
14716
+ message: err.message
14717
+ });
14718
+ } catch (error) {
14719
+ logger.error(`[MysqlInstrumentation] error ending span:`, error);
14720
+ }
14721
+ else try {
14722
+ const outputValue = {
14723
+ results,
14724
+ fields
14725
+ };
14726
+ SpanUtils.addSpanAttributes(spanInfo.span, { outputValue });
14727
+ SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14728
+ } catch (error) {
14729
+ logger.error(`[MysqlInstrumentation] error ending span:`, error);
14730
+ }
14731
+ logger.debug(`[MysqlInstrumentation] Query completed`);
14732
+ originalCallback$1.call(this, err, results, fields);
14733
+ };
14734
+ return originalQuery.apply(connection, args);
14735
+ }
13949
14736
  const originalCallback = callback;
13950
14737
  const callbackIndex = args.findIndex((arg) => typeof arg === "function");
13951
14738
  args[callbackIndex] = function(err, results, fields) {
@@ -14000,11 +14787,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14000
14787
  _patchBeginTransaction(connection) {
14001
14788
  const self = this;
14002
14789
  return (originalBeginTransaction) => {
14003
- return function beginTransaction(callback) {
14790
+ return function beginTransaction(optionsOrCallback, callbackArg) {
14791
+ let actualCallback;
14792
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14793
+ else actualCallback = callbackArg;
14004
14794
  const inputValue = { query: "BEGIN" };
14005
14795
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
14006
14796
  noOpRequestHandler: () => {
14007
- if (callback) setImmediate(() => callback(null));
14797
+ if (actualCallback) setImmediate(() => actualCallback(null));
14008
14798
  },
14009
14799
  isServerRequest: false,
14010
14800
  replayModeHandler: () => {
@@ -14018,7 +14808,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14018
14808
  inputValue,
14019
14809
  isPreAppStart: false
14020
14810
  }, (spanInfo) => {
14021
- return self._handleReplayTransaction(inputValue, callback);
14811
+ return self._handleReplayTransaction(inputValue, actualCallback);
14022
14812
  });
14023
14813
  }
14024
14814
  });
@@ -14035,7 +14825,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14035
14825
  inputValue,
14036
14826
  isPreAppStart
14037
14827
  }, (spanInfo) => {
14038
- return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, callback);
14828
+ return self._handleRecordTransaction(spanInfo, originalBeginTransaction, connection, arguments, actualCallback);
14039
14829
  });
14040
14830
  },
14041
14831
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14047,11 +14837,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14047
14837
  _patchCommit(connection) {
14048
14838
  const self = this;
14049
14839
  return (originalCommit) => {
14050
- return function commit(callback) {
14840
+ return function commit(optionsOrCallback, callbackArg) {
14841
+ let actualCallback;
14842
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14843
+ else actualCallback = callbackArg;
14051
14844
  const inputValue = { query: "COMMIT" };
14052
14845
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
14053
14846
  noOpRequestHandler: () => {
14054
- if (callback) setImmediate(() => callback(null));
14847
+ if (actualCallback) setImmediate(() => actualCallback(null));
14055
14848
  },
14056
14849
  isServerRequest: false,
14057
14850
  replayModeHandler: () => {
@@ -14065,7 +14858,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14065
14858
  inputValue,
14066
14859
  isPreAppStart: false
14067
14860
  }, (spanInfo) => {
14068
- return self._handleReplayTransaction(inputValue, callback);
14861
+ return self._handleReplayTransaction(inputValue, actualCallback);
14069
14862
  });
14070
14863
  }
14071
14864
  });
@@ -14082,7 +14875,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14082
14875
  inputValue,
14083
14876
  isPreAppStart
14084
14877
  }, (spanInfo) => {
14085
- return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, callback);
14878
+ return self._handleRecordTransaction(spanInfo, originalCommit, connection, arguments, actualCallback);
14086
14879
  });
14087
14880
  },
14088
14881
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14094,11 +14887,14 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14094
14887
  _patchRollback(connection) {
14095
14888
  const self = this;
14096
14889
  return (originalRollback) => {
14097
- return function rollback(callback) {
14890
+ return function rollback(optionsOrCallback, callbackArg) {
14891
+ let actualCallback;
14892
+ if (typeof optionsOrCallback === "function") actualCallback = optionsOrCallback;
14893
+ else actualCallback = callbackArg;
14098
14894
  const inputValue = { query: "ROLLBACK" };
14099
14895
  if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
14100
14896
  noOpRequestHandler: () => {
14101
- if (callback) setImmediate(() => callback(null));
14897
+ if (actualCallback) setImmediate(() => actualCallback(null));
14102
14898
  },
14103
14899
  isServerRequest: false,
14104
14900
  replayModeHandler: () => {
@@ -14112,7 +14908,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14112
14908
  inputValue,
14113
14909
  isPreAppStart: false
14114
14910
  }, (spanInfo) => {
14115
- return self._handleReplayTransaction(inputValue, callback);
14911
+ return self._handleReplayTransaction(inputValue, actualCallback);
14116
14912
  });
14117
14913
  }
14118
14914
  });
@@ -14129,7 +14925,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14129
14925
  inputValue,
14130
14926
  isPreAppStart
14131
14927
  }, (spanInfo) => {
14132
- return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, callback);
14928
+ return self._handleRecordTransaction(spanInfo, originalRollback, connection, arguments, actualCallback);
14133
14929
  });
14134
14930
  },
14135
14931
  spanKind: import_src$23.SpanKind.CLIENT
@@ -14162,7 +14958,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14162
14958
  const argsArray = Array.from(args);
14163
14959
  const callbackIndex = argsArray.findIndex((arg) => typeof arg === "function");
14164
14960
  if (callbackIndex !== -1) {
14165
- const originalCallback = callback;
14961
+ const originalCallback = argsArray[callbackIndex];
14166
14962
  argsArray[callbackIndex] = function(err) {
14167
14963
  if (err) try {
14168
14964
  SpanUtils.endSpan(spanInfo.span, {
@@ -14191,7 +14987,7 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14191
14987
  callback(null);
14192
14988
  });
14193
14989
  }
14194
- _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, context$6) {
14990
+ _handleRecordPoolGetConnectionInSpan(spanInfo, originalGetConnection, callback, poolContext) {
14195
14991
  const self = this;
14196
14992
  if (callback) {
14197
14993
  const wrappedCallback = (error, connection) => {
@@ -14216,11 +15012,11 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14216
15012
  } });
14217
15013
  SpanUtils.endSpan(spanInfo.span, { code: import_src$23.SpanStatusCode.OK });
14218
15014
  }
14219
- return callback(error, connection);
15015
+ return import_src$23.context.bind(spanInfo.context, callback)(error, connection);
14220
15016
  };
14221
- return originalGetConnection.call(context$6, wrappedCallback);
15017
+ return originalGetConnection.call(poolContext, wrappedCallback);
14222
15018
  } else try {
14223
- const result = originalGetConnection.call(context$6);
15019
+ const result = originalGetConnection.call(poolContext);
14224
15020
  SpanUtils.addSpanAttributes(spanInfo.span, { outputValue: {
14225
15021
  connected: true,
14226
15022
  hasConnection: true
@@ -14235,20 +15031,28 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14235
15031
  throw error;
14236
15032
  }
14237
15033
  }
14238
- _handleNoOpReplayGetConnection(callback) {
15034
+ _handleNoOpReplayGetConnection(pool, callback) {
14239
15035
  logger.debug(`[MysqlInstrumentation] Background getConnection detected, returning mock connection`);
14240
- const mockConnection = new TdMysqlConnectionMock(this, "pool");
15036
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", void 0, pool);
14241
15037
  if (callback) {
14242
- process.nextTick(() => callback(null, mockConnection));
15038
+ process.nextTick(() => {
15039
+ pool.emit("connection", mockConnection);
15040
+ pool.emit("acquire", mockConnection);
15041
+ callback(null, mockConnection);
15042
+ });
14243
15043
  return;
14244
15044
  }
14245
15045
  return mockConnection;
14246
15046
  }
14247
- _handleReplayPoolGetConnection(spanInfo, callback) {
15047
+ _handleReplayPoolGetConnection(pool, spanInfo, callback) {
14248
15048
  logger.debug(`[MysqlInstrumentation] Replaying MySQL Pool getConnection`);
14249
- const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo);
15049
+ const mockConnection = new TdMysqlConnectionMock(this, "pool", spanInfo, pool);
14250
15050
  if (callback) {
14251
- process.nextTick(() => callback(null, mockConnection));
15051
+ process.nextTick(() => {
15052
+ pool.emit("connection", mockConnection);
15053
+ pool.emit("acquire", mockConnection);
15054
+ callback(null, mockConnection);
15055
+ });
14252
15056
  return;
14253
15057
  }
14254
15058
  return mockConnection;
@@ -14481,6 +15285,122 @@ var MysqlInstrumentation = class extends TdInstrumentationBase {
14481
15285
  });
14482
15286
  return readableStream;
14483
15287
  }
15288
+ /**
15289
+ * Get wrapper function for PoolNamespace.query method
15290
+ * This handles queries made via poolCluster.of("pattern").query()
15291
+ */
15292
+ _getPoolNamespaceQueryPatchFn() {
15293
+ const self = this;
15294
+ return (originalQuery) => {
15295
+ return function query(...args) {
15296
+ const firstArg = args[0];
15297
+ const hasInternalCallback = firstArg && typeof firstArg === "object" && typeof firstArg._callback === "function";
15298
+ if (self.mode === TuskDriftMode.REPLAY) {
15299
+ let sql;
15300
+ let values;
15301
+ let callback;
15302
+ let options = {};
15303
+ if (self.createQuery) try {
15304
+ const queryObj = self.createQuery(...args);
15305
+ sql = queryObj.sql;
15306
+ values = queryObj.values;
15307
+ options = { nestTables: queryObj.nestTables };
15308
+ callback = args.find((arg) => typeof arg === "function");
15309
+ if (!callback && hasInternalCallback) callback = firstArg._callback;
15310
+ } catch (error) {
15311
+ ({sql, values, callback, options} = self._parseQueryArgs(args));
15312
+ }
15313
+ else ({sql, values, callback, options} = self._parseQueryArgs(args));
15314
+ const inputValue = {
15315
+ sql,
15316
+ values,
15317
+ options: options.nestTables ? { nestTables: options.nestTables } : void 0
15318
+ };
15319
+ const stackTrace = captureStackTrace(["MysqlInstrumentation"]);
15320
+ return handleReplayMode({
15321
+ noOpRequestHandler: () => {
15322
+ return self.queryMock.handleNoOpReplayQuery({
15323
+ sql,
15324
+ values,
15325
+ callback,
15326
+ options
15327
+ });
15328
+ },
15329
+ isServerRequest: false,
15330
+ replayModeHandler: () => {
15331
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalQuery.apply(this, args), {
15332
+ name: "mysql.query",
15333
+ kind: import_src$23.SpanKind.CLIENT,
15334
+ submodule: "query",
15335
+ packageType: PackageType.MYSQL,
15336
+ packageName: "mysql",
15337
+ instrumentationName: self.INSTRUMENTATION_NAME,
15338
+ inputValue,
15339
+ isPreAppStart: false
15340
+ }, (spanInfo) => {
15341
+ const queryEmitter = self.queryMock.handleReplayQuery({
15342
+ sql,
15343
+ values,
15344
+ callback,
15345
+ options
15346
+ }, inputValue, spanInfo, stackTrace);
15347
+ if (queryEmitter && typeof queryEmitter === "object") queryEmitter.stream = function(streamOptions) {
15348
+ return self._createReplayStreamForQuery(inputValue, spanInfo, stackTrace, queryEmitter, streamOptions);
15349
+ };
15350
+ return queryEmitter;
15351
+ });
15352
+ }
15353
+ });
15354
+ } else if (self.mode === TuskDriftMode.RECORD) return originalQuery.apply(this, args);
15355
+ else return originalQuery.apply(this, args);
15356
+ };
15357
+ };
15358
+ }
15359
+ /**
15360
+ * Get wrapper function for PoolNamespace.getConnection method
15361
+ * This handles connections obtained via poolCluster.of("pattern").getConnection()
15362
+ */
15363
+ _getPoolNamespaceGetConnectionPatchFn() {
15364
+ const self = this;
15365
+ return (originalGetConnection) => {
15366
+ return function getConnection(callback) {
15367
+ const namespace = this;
15368
+ const inputValue = { clientType: "poolNamespace" };
15369
+ if (self.mode === TuskDriftMode.REPLAY) return handleReplayMode({
15370
+ noOpRequestHandler: () => {
15371
+ const mockConnection = new TdMysqlConnectionMock(self, "pool", void 0, void 0);
15372
+ if (callback) {
15373
+ process.nextTick(() => callback(null, mockConnection));
15374
+ return;
15375
+ }
15376
+ return mockConnection;
15377
+ },
15378
+ isServerRequest: false,
15379
+ replayModeHandler: () => {
15380
+ return SpanUtils.createAndExecuteSpan(self.mode, () => originalGetConnection.apply(namespace, [callback]), {
15381
+ name: `mysql.poolNamespace.getConnection`,
15382
+ kind: import_src$23.SpanKind.CLIENT,
15383
+ submodule: "getConnection",
15384
+ packageName: "mysql",
15385
+ packageType: PackageType.MYSQL,
15386
+ instrumentationName: self.INSTRUMENTATION_NAME,
15387
+ inputValue,
15388
+ isPreAppStart: false
15389
+ }, (spanInfo) => {
15390
+ const mockConnection = new TdMysqlConnectionMock(self, "pool", spanInfo, void 0);
15391
+ if (callback) {
15392
+ process.nextTick(() => callback(null, mockConnection));
15393
+ return;
15394
+ }
15395
+ return mockConnection;
15396
+ });
15397
+ }
15398
+ });
15399
+ else if (self.mode === TuskDriftMode.RECORD) return originalGetConnection.apply(namespace, [callback]);
15400
+ else return originalGetConnection.apply(namespace, [callback]);
15401
+ };
15402
+ };
15403
+ }
14484
15404
  _wrap(target, propertyName, wrapper) {
14485
15405
  wrap(target, propertyName, wrapper);
14486
15406
  }
@@ -19552,13 +20472,6 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19552
20472
  return originalHandleRequest.call(this, req, res, parsedUrl);
19553
20473
  }
19554
20474
  logger.debug(`[NextjsInstrumentation] Setting replay trace id`, replayTraceId);
19555
- if (self.replayHooks.extractShouldFetchEnvVars(req)) try {
19556
- const envVars = self.tuskDrift.requestEnvVarsSync(replayTraceId);
19557
- EnvVarTracker.setEnvVars(replayTraceId, envVars);
19558
- logger.debug(`[NextjsInstrumentation] Fetched env vars from CLI for trace ${replayTraceId}`);
19559
- } catch (error) {
19560
- logger.error(`[NextjsInstrumentation] Failed to fetch env vars from CLI:`, error);
19561
- }
19562
20475
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
19563
20476
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
19564
20477
  return import_src$11.context.with(ctxWithReplayTraceId, () => {
@@ -19713,10 +20626,8 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19713
20626
  decodedType: getDecodedType(outputValue.headers?.["content-type"] || "")
19714
20627
  },
19715
20628
  headers: { matchImportance: 0 }
19716
- },
19717
- metadata: { ENV_VARS: EnvVarTracker.getEnvVars(spanInfo.traceId) }
20629
+ }
19718
20630
  });
19719
- EnvVarTracker.clearEnvVars(spanInfo.traceId);
19720
20631
  const status = (capturedStatusCode || 200) >= 400 ? {
19721
20632
  code: import_src$11.SpanStatusCode.ERROR,
19722
20633
  message: `HTTP ${capturedStatusCode}`
@@ -19754,6 +20665,7 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19754
20665
  instrumentationName: self.INSTRUMENTATION_NAME,
19755
20666
  submoduleName: completeInputValue.method,
19756
20667
  inputValue: completeInputValue,
20668
+ environment: self.tuskDrift.getEnvironment(),
19757
20669
  outputValue,
19758
20670
  inputSchema,
19759
20671
  outputSchema,
@@ -24243,7 +25155,7 @@ var SpanTransformer = class SpanTransformer {
24243
25155
  * Return type is derived from protobuf schema but uses clean JSON.
24244
25156
  * We use JSON because serialized protobuf is extremely verbose and not readable.
24245
25157
  */
24246
- static transformSpanToCleanJSON(span) {
25158
+ static transformSpanToCleanJSON(span, environment) {
24247
25159
  const isRootSpan = !span.parentSpanId || span.kind === import_src$9.SpanKind.SERVER;
24248
25160
  const attributes = span.attributes;
24249
25161
  const packageName = SpanTransformer.extractPackageName(attributes);
@@ -24287,6 +25199,7 @@ var SpanTransformer = class SpanTransformer {
24287
25199
  instrumentationName,
24288
25200
  submoduleName: submoduleName || "",
24289
25201
  packageType: attributes[TdSpanAttributes.PACKAGE_TYPE] || void 0,
25202
+ environment,
24290
25203
  inputValue: inputData,
24291
25204
  outputValue: outputData,
24292
25205
  inputSchema,
@@ -24750,7 +25663,7 @@ var ApiSpanAdapter = class {
24750
25663
  const protoSpans = spans.map((span) => this.transformSpanToProtobuf(span));
24751
25664
  const request = {
24752
25665
  observableServiceId: this.observableServiceId,
24753
- environment: this.environment,
25666
+ environment: this.environment || "",
24754
25667
  sdkVersion: this.sdkVersion,
24755
25668
  sdkInstanceId: this.sdkInstanceId,
24756
25669
  spans: protoSpans
@@ -24777,6 +25690,7 @@ var ApiSpanAdapter = class {
24777
25690
  instrumentationName: cleanSpan.instrumentationName,
24778
25691
  submoduleName: cleanSpan.submoduleName,
24779
25692
  packageType: cleanSpan.packageType || PackageType.UNSPECIFIED,
25693
+ environment: this.environment,
24780
25694
  inputValue: toStruct(cleanSpan.inputValue),
24781
25695
  outputValue: toStruct(cleanSpan.outputValue),
24782
25696
  inputSchema: cleanSpan.inputSchema,
@@ -24802,12 +25716,12 @@ var ApiSpanAdapter = class {
24802
25716
  }
24803
25717
  mapSpanKind(kind) {
24804
25718
  switch (kind) {
24805
- case import_src$7.SpanKind.CLIENT: return SpanKind.CLIENT;
24806
- case import_src$7.SpanKind.SERVER: return SpanKind.SERVER;
24807
- case import_src$7.SpanKind.PRODUCER: return SpanKind.PRODUCER;
24808
- case import_src$7.SpanKind.CONSUMER: return SpanKind.CONSUMER;
24809
- case import_src$7.SpanKind.INTERNAL: return SpanKind.INTERNAL;
24810
- default: return SpanKind.UNSPECIFIED;
25719
+ case import_src$7.SpanKind.CLIENT: return SpanKind$1.CLIENT;
25720
+ case import_src$7.SpanKind.SERVER: return SpanKind$1.SERVER;
25721
+ case import_src$7.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
25722
+ case import_src$7.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
25723
+ case import_src$7.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
25724
+ default: return SpanKind$1.UNSPECIFIED;
24811
25725
  }
24812
25726
  }
24813
25727
  async shutdown() {
@@ -24822,6 +25736,7 @@ var TdSpanExporter = class {
24822
25736
  constructor(config) {
24823
25737
  this.adapters = [];
24824
25738
  this.mode = config.mode;
25739
+ this.environment = config.environment;
24825
25740
  this.setupDefaultAdapters(config);
24826
25741
  logger.debug(`TdSpanExporter initialized with ${this.adapters.length} adapter(s)`);
24827
25742
  }
@@ -24905,7 +25820,7 @@ var TdSpanExporter = class {
24905
25820
  return true;
24906
25821
  });
24907
25822
  logger.debug(`Filtered ${filteredSpansBasedOnLibraryName.length - filteredBlockedSpans.length} blocked/oversized span(s), ${filteredBlockedSpans.length} remaining`);
24908
- const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span));
25823
+ const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span, this.environment));
24909
25824
  if (this.adapters.length === 0) {
24910
25825
  logger.debug("No adapters configured");
24911
25826
  resultCallback({ code: import_src$5.ExportResultCode.SUCCESS });
@@ -32056,7 +32971,7 @@ var require_src = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/sdk-
32056
32971
  //#endregion
32057
32972
  //#region package.json
32058
32973
  var import_src$1 = /* @__PURE__ */ __toESM(require_src(), 1);
32059
- var version = "0.1.17";
32974
+ var version = "0.1.19";
32060
32975
 
32061
32976
  //#endregion
32062
32977
  //#region src/version.ts
@@ -32064,7 +32979,7 @@ const SDK_VERSION = version;
32064
32979
  const MIN_CLI_VERSION = "0.1.0";
32065
32980
 
32066
32981
  //#endregion
32067
- //#region node_modules/@use-tusk/drift-schemas/dist/communication-D4zqMBSI.js
32982
+ //#region node_modules/@use-tusk/drift-schemas/dist/communication-BY2KZhrg.js
32068
32983
  var import_commonjs = /* @__PURE__ */ __toESM(require_commonjs$1(), 1);
32069
32984
  var import_commonjs$1 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
32070
32985
  /**
@@ -33208,12 +34123,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33208
34123
  });
33209
34124
  await this.sendProtobufMessage(sdkMessage);
33210
34125
  }
33211
- getStackTrace() {
33212
- Error.stackTraceLimit = 100;
33213
- const s = (/* @__PURE__ */ new Error()).stack || "";
33214
- Error.stackTraceLimit = 10;
33215
- return s.split("\n").slice(2).filter((l) => !l.includes("ProtobufCommunicator")).join("\n");
33216
- }
33217
34126
  async requestMockAsync(mockRequest) {
33218
34127
  const requestId = this.generateRequestId();
33219
34128
  const cleanSpan = mockRequest.outboundSpan ? this.cleanSpan(mockRequest.outboundSpan) : void 0;
@@ -33246,7 +34155,7 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33246
34155
  /**
33247
34156
  * Generic synchronous request handler that spawns a child process.
33248
34157
  * @param sdkMessage The SDK message to send
33249
- * @param filePrefix Prefix for temporary files (e.g., 'envvar', 'mock')
34158
+ * @param filePrefix Prefix for temporary files (e.g., 'mock')
33250
34159
  * @param responseHandler Function to extract and return the desired response
33251
34160
  */
33252
34161
  executeSyncRequest(sdkMessage, filePrefix, responseHandler) {
@@ -33315,35 +34224,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33315
34224
  }
33316
34225
  }
33317
34226
  /**
33318
- * Request environment variables from CLI synchronously using a child process.
33319
- * This blocks the main thread, so it should be used carefully.
33320
- * Similar to requestMockSync but for environment variables.
33321
- */
33322
- requestEnvVarsSync(traceTestServerSpanId) {
33323
- const requestId = this.generateRequestId();
33324
- const envVarRequest = EnvVarRequest.create({ traceTestServerSpanId });
33325
- const sdkMessage = SDKMessage.create({
33326
- type: MessageType$1.ENV_VAR_REQUEST,
33327
- requestId,
33328
- payload: {
33329
- oneofKind: "envVarRequest",
33330
- envVarRequest
33331
- }
33332
- });
33333
- logger.debug(`[ProtobufCommunicator] Requesting env vars (sync) for trace: ${traceTestServerSpanId}`);
33334
- return this.executeSyncRequest(sdkMessage, "envvar", (cliMessage) => {
33335
- if (cliMessage.payload.oneofKind !== "envVarResponse") throw new Error(`Unexpected response type: ${cliMessage.type}`);
33336
- const envVarResponse = cliMessage.payload.envVarResponse;
33337
- if (!envVarResponse) throw new Error("No env var response received");
33338
- const envVars = {};
33339
- if (envVarResponse.envVars) Object.entries(envVarResponse.envVars).forEach(([key, value]) => {
33340
- envVars[key] = value;
33341
- });
33342
- logger.debug(`[ProtobufCommunicator] Received env vars (sync), count: ${Object.keys(envVars).length}`);
33343
- return envVars;
33344
- });
33345
- }
33346
- /**
33347
34227
  * This function uses a separate Node.js child process to communicate with the CLI over a socket.
33348
34228
  * The child process creates its own connection and event loop, allowing proper async socket handling.
33349
34229
  * The parent process blocks synchronously waiting for the child to complete.
@@ -33554,22 +34434,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33554
34434
  error: mockResponse.error || "Mock not found"
33555
34435
  });
33556
34436
  }
33557
- if (message.payload.oneofKind === "envVarResponse") {
33558
- const envVarResponse = message.payload.envVarResponse;
33559
- logger.debug(`[ProtobufCommunicator] Received env var response for requestId: ${requestId}`);
33560
- const pendingRequest = this.pendingRequests.get(requestId);
33561
- if (!pendingRequest) {
33562
- logger.warn("[ProtobufCommunicator] received env var response for unknown request:", requestId);
33563
- return;
33564
- }
33565
- this.pendingRequests.delete(requestId);
33566
- const envVars = {};
33567
- if (envVarResponse?.envVars) Object.entries(envVarResponse.envVars).forEach(([key, value]) => {
33568
- envVars[key] = value;
33569
- });
33570
- pendingRequest.resolve(envVars);
33571
- return;
33572
- }
33573
34437
  }
33574
34438
  /**
33575
34439
  * Extract response data from MockResponse
@@ -33869,10 +34733,6 @@ var TuskDriftCore = class TuskDriftCore {
33869
34733
  enabled: true,
33870
34734
  mode: this.mode
33871
34735
  });
33872
- new EnvInstrumentation({
33873
- enabled: this.config.recording?.enable_env_var_recording || false,
33874
- mode: this.mode
33875
- });
33876
34736
  new PostgresInstrumentation({
33877
34737
  enabled: true,
33878
34738
  mode: this.mode
@@ -33920,7 +34780,7 @@ var TuskDriftCore = class TuskDriftCore {
33920
34780
  observableServiceId: this.config.service?.id,
33921
34781
  apiKey: this.initParams.apiKey,
33922
34782
  tuskBackendBaseUrl: this.config.tusk_api?.url || "https://api.usetusk.ai",
33923
- environment: this.initParams.env || "unknown",
34783
+ environment: this.initParams.env,
33924
34784
  sdkVersion: SDK_VERSION,
33925
34785
  sdkInstanceId: this.generateSdkInstanceId()
33926
34786
  });
@@ -33938,6 +34798,34 @@ var TuskDriftCore = class TuskDriftCore {
33938
34798
  generateSdkInstanceId() {
33939
34799
  return `sdk-${OriginalGlobalUtils.getOriginalDate().getTime()}-${Math.random().toString(36).substr(2, 9)}`;
33940
34800
  }
34801
+ /**
34802
+ * Creates a pre-app-start span containing a snapshot of all environment variables.
34803
+ * Only runs in RECORD mode when env var recording is enabled.
34804
+ */
34805
+ createEnvVarsSnapshot() {
34806
+ if (this.mode !== TuskDriftMode.RECORD || !this.config.recording?.enable_env_var_recording) return;
34807
+ try {
34808
+ const envVarsSnapshot = {};
34809
+ for (const key of Object.keys(process.env)) envVarsSnapshot[key] = process.env[key];
34810
+ logger.debug(`Creating env vars snapshot with ${Object.keys(envVarsSnapshot).length} variables`);
34811
+ SpanUtils.createAndExecuteSpan(this.mode, () => {}, {
34812
+ name: "ENV_VARS_SNAPSHOT",
34813
+ kind: import_src.SpanKind.INTERNAL,
34814
+ packageName: "process.env",
34815
+ packageType: PackageType.UNSPECIFIED,
34816
+ instrumentationName: "TuskDriftCore",
34817
+ submodule: "env",
34818
+ inputValue: {},
34819
+ outputValue: { ENV_VARS: envVarsSnapshot },
34820
+ isPreAppStart: true
34821
+ }, (spanInfo) => {
34822
+ SpanUtils.endSpan(spanInfo.span, { code: import_src.SpanStatusCode.OK });
34823
+ logger.debug(`Env vars snapshot span created: ${spanInfo.spanId}`);
34824
+ });
34825
+ } catch (error) {
34826
+ logger.error("Failed to create env vars snapshot:", error);
34827
+ }
34828
+ }
33941
34829
  initialize(initParams) {
33942
34830
  initializeGlobalLogger({
33943
34831
  logLevel: initParams.logLevel || "info",
@@ -34014,6 +34902,7 @@ var TuskDriftCore = class TuskDriftCore {
34014
34902
  logger.debug(`Base directory: ${baseDirectory}`);
34015
34903
  this.registerDefaultInstrumentations();
34016
34904
  this.initializeTracing({ baseDirectory });
34905
+ this.createEnvVarsSnapshot();
34017
34906
  this.initialized = true;
34018
34907
  logger.info("SDK initialized successfully");
34019
34908
  }
@@ -34077,30 +34966,6 @@ var TuskDriftCore = class TuskDriftCore {
34077
34966
  };
34078
34967
  }
34079
34968
  }
34080
- /**
34081
- * Request environment variables from CLI for a specific trace (synchronously).
34082
- * This blocks the main thread, so it should be used carefully.
34083
- */
34084
- requestEnvVarsSync(traceTestServerSpanId) {
34085
- if (!this.isConnectedWithCLI) {
34086
- logger.error("Requesting sync env vars but CLI is not ready yet");
34087
- throw new Error("Requesting sync env vars but CLI is not ready yet");
34088
- }
34089
- if (!this.communicator || this.mode !== TuskDriftMode.REPLAY) {
34090
- logger.debug("Cannot request env vars: not in replay mode or no CLI connection");
34091
- return {};
34092
- }
34093
- try {
34094
- logger.debug(`Requesting env vars (sync) for trace: ${traceTestServerSpanId}`);
34095
- const envVars = this.communicator.requestEnvVarsSync(traceTestServerSpanId);
34096
- logger.debug(`Received env vars from CLI, count: ${Object.keys(envVars).length}`);
34097
- logger.debug(`First 10 env vars: ${JSON.stringify(Object.keys(envVars).slice(0, 10), null, 2)}`);
34098
- return envVars;
34099
- } catch (error) {
34100
- logger.error(`[TuskDrift] Error requesting env vars from CLI:`, error);
34101
- return {};
34102
- }
34103
- }
34104
34969
  requestMockSync(mockRequest) {
34105
34970
  if (!this.isConnectedWithCLI) {
34106
34971
  logger.error("Requesting sync mock but CLI is not ready yet");
@@ -34152,6 +35017,9 @@ var TuskDriftCore = class TuskDriftCore {
34152
35017
  getInitParams() {
34153
35018
  return this.initParams;
34154
35019
  }
35020
+ getEnvironment() {
35021
+ return this.initParams.env;
35022
+ }
34155
35023
  getTracer() {
34156
35024
  return import_src.trace.getTracer(TD_INSTRUMENTATION_LIBRARY_NAME);
34157
35025
  }