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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4989,31 +4989,31 @@ var require_SamplingResult = /* @__PURE__ */ __commonJS({ "node_modules/@opentel
4989
4989
  var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/span_kind.js": ((exports) => {
4990
4990
  Object.defineProperty(exports, "__esModule", { value: true });
4991
4991
  exports.SpanKind = void 0;
4992
- (function(SpanKind$24) {
4992
+ (function(SpanKind$25) {
4993
4993
  /** Default value. Indicates that the span is used internally. */
4994
- SpanKind$24[SpanKind$24["INTERNAL"] = 0] = "INTERNAL";
4994
+ SpanKind$25[SpanKind$25["INTERNAL"] = 0] = "INTERNAL";
4995
4995
  /**
4996
4996
  * Indicates that the span covers server-side handling of an RPC or other
4997
4997
  * remote request.
4998
4998
  */
4999
- SpanKind$24[SpanKind$24["SERVER"] = 1] = "SERVER";
4999
+ SpanKind$25[SpanKind$25["SERVER"] = 1] = "SERVER";
5000
5000
  /**
5001
5001
  * Indicates that the span covers the client-side wrapper around an RPC or
5002
5002
  * other remote request.
5003
5003
  */
5004
- SpanKind$24[SpanKind$24["CLIENT"] = 2] = "CLIENT";
5004
+ SpanKind$25[SpanKind$25["CLIENT"] = 2] = "CLIENT";
5005
5005
  /**
5006
5006
  * Indicates that the span describes producer sending a message to a
5007
5007
  * broker. Unlike client and server, there is no direct critical path latency
5008
5008
  * relationship between producer and consumer spans.
5009
5009
  */
5010
- SpanKind$24[SpanKind$24["PRODUCER"] = 3] = "PRODUCER";
5010
+ SpanKind$25[SpanKind$25["PRODUCER"] = 3] = "PRODUCER";
5011
5011
  /**
5012
5012
  * Indicates that the span describes consumer receiving a message from a
5013
5013
  * broker. Unlike client and server, there is no direct critical path latency
5014
5014
  * relationship between producer and consumer spans.
5015
5015
  */
5016
- SpanKind$24[SpanKind$24["CONSUMER"] = 4] = "CONSUMER";
5016
+ SpanKind$25[SpanKind$25["CONSUMER"] = 4] = "CONSUMER";
5017
5017
  })(exports.SpanKind || (exports.SpanKind = {}));
5018
5018
  }) });
5019
5019
 
@@ -5022,20 +5022,20 @@ var require_span_kind = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetr
5022
5022
  var require_status = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/api/build/src/trace/status.js": ((exports) => {
5023
5023
  Object.defineProperty(exports, "__esModule", { value: true });
5024
5024
  exports.SpanStatusCode = void 0;
5025
- (function(SpanStatusCode$13) {
5025
+ (function(SpanStatusCode$14) {
5026
5026
  /**
5027
5027
  * The default status.
5028
5028
  */
5029
- SpanStatusCode$13[SpanStatusCode$13["UNSET"] = 0] = "UNSET";
5029
+ SpanStatusCode$14[SpanStatusCode$14["UNSET"] = 0] = "UNSET";
5030
5030
  /**
5031
5031
  * The operation has been validated by an Application developer or
5032
5032
  * Operator to have completed successfully.
5033
5033
  */
5034
- SpanStatusCode$13[SpanStatusCode$13["OK"] = 1] = "OK";
5034
+ SpanStatusCode$14[SpanStatusCode$14["OK"] = 1] = "OK";
5035
5035
  /**
5036
5036
  * The operation contains an error.
5037
5037
  */
5038
- SpanStatusCode$13[SpanStatusCode$13["ERROR"] = 2] = "ERROR";
5038
+ SpanStatusCode$14[SpanStatusCode$14["ERROR"] = 2] = "ERROR";
5039
5039
  })(exports.SpanStatusCode || (exports.SpanStatusCode = {}));
5040
5040
  }) });
5041
5041
 
@@ -6209,7 +6209,7 @@ var JsonSchema$Type = class extends import_commonjs$7.MessageType {
6209
6209
  const JsonSchema = new JsonSchema$Type();
6210
6210
 
6211
6211
  //#endregion
6212
- //#region node_modules/@use-tusk/drift-schemas/dist/span-BZ89ct3l.js
6212
+ //#region node_modules/@use-tusk/drift-schemas/dist/span-CsBrzhI_.js
6213
6213
  var import_commonjs$6 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
6214
6214
  /**
6215
6215
  * Package type classification enum
@@ -6295,7 +6295,7 @@ let PackageType = /* @__PURE__ */ function(PackageType$1) {
6295
6295
  *
6296
6296
  * @generated from protobuf enum tusk.drift.core.v1.SpanKind
6297
6297
  */
6298
- let SpanKind = /* @__PURE__ */ function(SpanKind$1$1) {
6298
+ let SpanKind$1 = /* @__PURE__ */ function(SpanKind$1$1) {
6299
6299
  /**
6300
6300
  * @generated from protobuf enum value: SPAN_KIND_UNSPECIFIED = 0;
6301
6301
  */
@@ -6465,7 +6465,7 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6465
6465
  kind: "enum",
6466
6466
  T: () => [
6467
6467
  "tusk.drift.core.v1.SpanKind",
6468
- SpanKind,
6468
+ SpanKind$1,
6469
6469
  "SPAN_KIND_"
6470
6470
  ]
6471
6471
  },
@@ -6504,6 +6504,13 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6504
6504
  name: "metadata",
6505
6505
  kind: "message",
6506
6506
  T: () => Struct
6507
+ },
6508
+ {
6509
+ no: 24,
6510
+ name: "environment",
6511
+ kind: "scalar",
6512
+ opt: true,
6513
+ T: 9
6507
6514
  }
6508
6515
  ]);
6509
6516
  }
@@ -6601,6 +6608,9 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6601
6608
  case 23:
6602
6609
  message.metadata = Struct.internalBinaryRead(reader, reader.uint32(), options, message.metadata);
6603
6610
  break;
6611
+ case 24:
6612
+ message.environment = reader.string();
6613
+ break;
6604
6614
  default:
6605
6615
  let u = options.readUnknownField;
6606
6616
  if (u === "throw") throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
@@ -6634,6 +6644,7 @@ var Span$Type = class extends import_commonjs$6.MessageType {
6634
6644
  if (message.duration) Duration.internalBinaryWrite(message.duration, writer.tag(21, import_commonjs$6.WireType.LengthDelimited).fork(), options).join();
6635
6645
  if (message.isRootSpan !== false) writer.tag(22, import_commonjs$6.WireType.Varint).bool(message.isRootSpan);
6636
6646
  if (message.metadata) Struct.internalBinaryWrite(message.metadata, writer.tag(23, import_commonjs$6.WireType.LengthDelimited).fork(), options).join();
6647
+ if (message.environment !== void 0) writer.tag(24, import_commonjs$6.WireType.LengthDelimited).string(message.environment);
6637
6648
  let u = options.writeUnknownFields;
6638
6649
  if (u !== false) (u == true ? import_commonjs$6.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
6639
6650
  return writer;
@@ -6997,12 +7008,12 @@ const Trace = new Trace$Type();
6997
7008
  const toStruct = (obj) => obj ? objectToProtobufStruct(obj) : void 0;
6998
7009
  const mapOtToPb = (k) => {
6999
7010
  switch (k) {
7000
- case import_src$34.SpanKind.INTERNAL: return SpanKind.INTERNAL;
7001
- case import_src$34.SpanKind.SERVER: return SpanKind.SERVER;
7002
- case import_src$34.SpanKind.CLIENT: return SpanKind.CLIENT;
7003
- case import_src$34.SpanKind.PRODUCER: return SpanKind.PRODUCER;
7004
- case import_src$34.SpanKind.CONSUMER: return SpanKind.CONSUMER;
7005
- default: return SpanKind.UNSPECIFIED;
7011
+ case import_src$34.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
7012
+ case import_src$34.SpanKind.SERVER: return SpanKind$1.SERVER;
7013
+ case import_src$34.SpanKind.CLIENT: return SpanKind$1.CLIENT;
7014
+ case import_src$34.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
7015
+ case import_src$34.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
7016
+ default: return SpanKind$1.UNSPECIFIED;
7006
7017
  }
7007
7018
  };
7008
7019
  /**
@@ -7586,7 +7597,7 @@ var SpanUtils = class SpanUtils {
7586
7597
  return originalFunctionCall();
7587
7598
  }
7588
7599
  }
7589
- const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
7600
+ const { name, kind, packageName, instrumentationName, packageType, submodule, inputValue, outputValue, inputSchemaMerges, isPreAppStart, metadata, stopRecordingChildSpans } = options;
7590
7601
  let spanInfo = null;
7591
7602
  try {
7592
7603
  spanInfo = SpanUtils.createSpan({
@@ -7600,6 +7611,7 @@ var SpanUtils = class SpanUtils {
7600
7611
  [TdSpanAttributes.INSTRUMENTATION_NAME]: instrumentationName,
7601
7612
  [TdSpanAttributes.PACKAGE_TYPE]: packageType,
7602
7613
  [TdSpanAttributes.INPUT_VALUE]: createSpanInputValue(inputValue),
7614
+ ...outputValue && { [TdSpanAttributes.OUTPUT_VALUE]: JSON.stringify(outputValue) },
7603
7615
  [TdSpanAttributes.IS_PRE_APP_START]: isPreAppStart,
7604
7616
  ...inputSchemaMerges && { [TdSpanAttributes.INPUT_SCHEMA_MERGES]: JSON.stringify(inputSchemaMerges) },
7605
7617
  ...metadata && { [TdSpanAttributes.METADATA]: JSON.stringify(metadata) }
@@ -7864,7 +7876,10 @@ function getDecodedType(contentType) {
7864
7876
  logger.debug(`Invalid Content-Type header: ${contentType}`);
7865
7877
  return;
7866
7878
  }
7867
- return CONTENT_TYPE_MAPPING[contentTypeString.toLowerCase().split(";")[0].trim()];
7879
+ const mainType = contentTypeString.toLowerCase().split(";")[0].trim();
7880
+ const decodedType = CONTENT_TYPE_MAPPING[mainType];
7881
+ if (decodedType !== void 0) return decodedType;
7882
+ if (mainType.includes("json")) return DecodedType.JSON;
7868
7883
  }
7869
7884
  const ACCEPTABLE_CONTENT_TYPES = new Set([DecodedType.JSON, DecodedType.PLAIN_TEXT]);
7870
7885
 
@@ -7963,30 +7978,6 @@ var TdHttpMockSocket = class extends events.EventEmitter {
7963
7978
  }
7964
7979
  };
7965
7980
 
7966
- //#endregion
7967
- //#region src/instrumentation/core/trackers/EnvVarTracker.ts
7968
- var EnvVarTracker = class {
7969
- static setEnvVar({ traceId, key, value }) {
7970
- this.envVars.set(traceId, {
7971
- ...this.envVars.get(traceId) || {},
7972
- [key]: value
7973
- });
7974
- }
7975
- static setEnvVars(traceId, envVars) {
7976
- this.envVars.set(traceId, envVars);
7977
- }
7978
- static getEnvVar(traceId, key) {
7979
- return this.envVars.get(traceId)?.[key];
7980
- }
7981
- static getEnvVars(traceId) {
7982
- return this.envVars.get(traceId);
7983
- }
7984
- static clearEnvVars(traceId) {
7985
- this.envVars.delete(traceId);
7986
- }
7987
- };
7988
- EnvVarTracker.envVars = /* @__PURE__ */ new Map();
7989
-
7990
7981
  //#endregion
7991
7982
  //#region src/instrumentation/core/trackers/DateTracker.ts
7992
7983
  /**
@@ -8209,10 +8200,17 @@ var JsonSchemaHelper = class JsonSchemaHelper {
8209
8200
  static decodeDataWithMerges(data, schemaMerges) {
8210
8201
  if (!schemaMerges) return data;
8211
8202
  const decodedData = { ...data };
8212
- for (const [key, schema] of Object.entries(schemaMerges)) if (schema.encoding && schema.decodedType && data[key] !== void 0) try {
8203
+ for (const [key, schema] of Object.entries(schemaMerges)) if (schema.encoding && data[key] !== void 0) try {
8213
8204
  let decodedValue = data[key];
8214
- if (schema.encoding === EncodingType.BASE64 && typeof decodedValue === "string") decodedValue = Buffer.from(decodedValue, "base64").toString("utf8");
8215
- if (schema.decodedType === DecodedType.JSON && typeof decodedValue === "string") decodedValue = JSON.parse(decodedValue);
8205
+ if (typeof decodedValue === "string") {
8206
+ if (schema.encoding === EncodingType.BASE64) decodedValue = Buffer.from(decodedValue, "base64").toString("utf8");
8207
+ if (schema.decodedType === DecodedType.JSON) decodedValue = JSON.parse(decodedValue);
8208
+ else if (!schema.decodedType) try {
8209
+ decodedValue = JSON.parse(decodedValue);
8210
+ } catch {
8211
+ logger.debug(`[JsonSchemaHelper] Failed to parse JSON for key: ${key}, no decodedType specified`);
8212
+ }
8213
+ }
8216
8214
  decodedData[key] = decodedValue;
8217
8215
  } catch (error) {
8218
8216
  logger.debug(`[JsonSchemaHelper] Failed to decode ${key}:`, error);
@@ -8280,6 +8278,7 @@ function convertMockRequestDataToCleanSpanData(mockRequestData, tuskDrift, input
8280
8278
  return {
8281
8279
  ...mockRequestData,
8282
8280
  parentSpanId: "",
8281
+ environment: tuskDrift.getEnvironment(),
8283
8282
  inputValueHash,
8284
8283
  inputSchema,
8285
8284
  inputSchemaHash,
@@ -8676,13 +8675,6 @@ var HttpReplayHooks = class {
8676
8675
  return traceIdHeader ? String(traceIdHeader) : null;
8677
8676
  }
8678
8677
  /**
8679
- * Check if we should fetch env vars from CLI
8680
- */
8681
- extractShouldFetchEnvVars(req) {
8682
- const fetchHeader = req.headers["x-td-fetch-env-vars"] || req.headers["X-TD-FETCH-ENV-VARS"];
8683
- return fetchHeader === "true" || fetchHeader === true;
8684
- }
8685
- /**
8686
8678
  * Handle outbound HTTP requests in replay mode
8687
8679
  * Uses TdMockClientRequest for simplified mocking approach
8688
8680
  */
@@ -9971,7 +9963,7 @@ var require_commonjs$1 = /* @__PURE__ */ __commonJS({ "node_modules/@protobuf-ts
9971
9963
  }) });
9972
9964
 
9973
9965
  //#endregion
9974
- //#region node_modules/@use-tusk/drift-schemas/dist/span_export_service-XwF6hpEK.js
9966
+ //#region node_modules/@use-tusk/drift-schemas/dist/span_export_service-CmkFvTqD.js
9975
9967
  var import_commonjs$4 = /* @__PURE__ */ __toESM(require_commonjs$1(), 1);
9976
9968
  var import_commonjs$5 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
9977
9969
  var ExportSpansRequest$Type = class extends import_commonjs$5.MessageType {
@@ -10661,13 +10653,6 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10661
10653
  return originalHandler.call(this);
10662
10654
  }
10663
10655
  logger.debug(`[HttpInstrumentation] Setting replay trace id`, replayTraceId);
10664
- if (this.replayHooks.extractShouldFetchEnvVars(req)) try {
10665
- const envVars = this.tuskDrift.requestEnvVarsSync(replayTraceId);
10666
- EnvVarTracker.setEnvVars(replayTraceId, envVars);
10667
- logger.debug(`[HttpInstrumentation] Fetched env vars from CLI for trace ${replayTraceId}`);
10668
- } catch (error) {
10669
- logger.error(`[HttpInstrumentation] Failed to fetch env vars from CLI:`, error);
10670
- }
10671
10656
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
10672
10657
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
10673
10658
  return import_src$28.context.with(ctxWithReplayTraceId, () => {
@@ -10810,10 +10795,8 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10810
10795
  },
10811
10796
  headers: { matchImportance: 0 }
10812
10797
  },
10813
- metadata: { ENV_VARS: EnvVarTracker.getEnvVars(spanInfo.traceId) },
10814
10798
  ...spanData.transformMetadata && { transformMetadata: spanData.transformMetadata }
10815
10799
  });
10816
- EnvVarTracker.clearEnvVars(spanInfo.traceId);
10817
10800
  const status = statusCode >= 400 ? {
10818
10801
  code: import_src$28.SpanStatusCode.ERROR,
10819
10802
  message: `HTTP ${statusCode}`
@@ -10859,6 +10842,7 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
10859
10842
  instrumentationName: "HttpInstrumentation",
10860
10843
  submoduleName: completeInputValue.method || inputValue.method,
10861
10844
  inputValue: completeInputValue,
10845
+ environment: self.tuskDrift.getEnvironment(),
10862
10846
  outputValue,
10863
10847
  inputSchema,
10864
10848
  outputSchema,
@@ -11379,96 +11363,6 @@ var HttpInstrumentation = class extends TdInstrumentationBase {
11379
11363
  }
11380
11364
  };
11381
11365
 
11382
- //#endregion
11383
- //#region src/instrumentation/libraries/env/Instrumentation.ts
11384
- /**
11385
- * Environment variable instrumentation that records and replays process.env access.
11386
- * In record mode, captures environment variable values.
11387
- * In replay mode, returns previously recorded values for deterministic behavior.
11388
- */
11389
- var EnvInstrumentation = class extends TdInstrumentationBase {
11390
- constructor(config = {}) {
11391
- super("env", config);
11392
- this.isInPatchedCall = false;
11393
- this.mode = config.mode || TuskDriftMode.DISABLED;
11394
- }
11395
- init() {
11396
- this.patchProcessEnv();
11397
- return [];
11398
- }
11399
- patchProcessEnv() {
11400
- if (this.mode === TuskDriftMode.DISABLED || !this._config.enabled) return;
11401
- this.originalProcessEnv = process.env;
11402
- const envProxy = new Proxy(this.originalProcessEnv, {
11403
- get: (target, property, receiver) => {
11404
- return this._handleEnvAccess(target, property);
11405
- },
11406
- set: (target, property, value, receiver) => {
11407
- target[property] = value;
11408
- return true;
11409
- },
11410
- deleteProperty: (target, property) => {
11411
- delete target[property];
11412
- return true;
11413
- },
11414
- ownKeys: (target) => {
11415
- return Reflect.ownKeys(target);
11416
- },
11417
- getOwnPropertyDescriptor: (target, property) => {
11418
- return Reflect.getOwnPropertyDescriptor(target, property);
11419
- },
11420
- has: (target, property) => {
11421
- return Reflect.has(target, property);
11422
- }
11423
- });
11424
- process.env = envProxy;
11425
- }
11426
- _handleEnvAccess(target, key) {
11427
- if (this.isInPatchedCall) return target[key];
11428
- if (!TuskDriftCore.getInstance().isAppReady()) return target[key];
11429
- this.isInPatchedCall = true;
11430
- try {
11431
- return this._handleEnvAccessInMode(target, key);
11432
- } finally {
11433
- this.isInPatchedCall = false;
11434
- }
11435
- }
11436
- _handleEnvAccessInMode(target, key) {
11437
- let currentSpanInfo = null;
11438
- try {
11439
- currentSpanInfo = SpanUtils.getCurrentSpanInfo();
11440
- } catch (error) {
11441
- logger.error(`EnvInstrumentation error getting current span info:`, error);
11442
- }
11443
- if (!currentSpanInfo) return target[key];
11444
- if (this.mode === TuskDriftMode.REPLAY) return this._handleReplayMode(target, key);
11445
- else if (this.mode === TuskDriftMode.RECORD) return this._handleRecordMode(currentSpanInfo, target, key);
11446
- else return target[key];
11447
- }
11448
- _handleReplayMode(target, key) {
11449
- const replayTraceId = SpanUtils.getCurrentReplayTraceId();
11450
- if (!replayTraceId) return target[key];
11451
- const envVar = EnvVarTracker.getEnvVar(replayTraceId, key);
11452
- if (envVar) {
11453
- logger.debug(`Returning env var ${key} for trace ${replayTraceId}: ${envVar}`);
11454
- return envVar;
11455
- }
11456
- return target[key];
11457
- }
11458
- _handleRecordMode(spanInfo, target, key) {
11459
- try {
11460
- EnvVarTracker.setEnvVar({
11461
- traceId: spanInfo.traceId,
11462
- key,
11463
- value: target[key] || void 0
11464
- });
11465
- } catch (error) {
11466
- logger.error(`EnvInstrumentation error storing env var:`, error);
11467
- }
11468
- return target[key];
11469
- }
11470
- };
11471
-
11472
11366
  //#endregion
11473
11367
  //#region src/instrumentation/libraries/date/Instrumentation.ts
11474
11368
  var import_src$27 = /* @__PURE__ */ __toESM(require_src$7(), 1);
@@ -19553,13 +19447,6 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19553
19447
  return originalHandleRequest.call(this, req, res, parsedUrl);
19554
19448
  }
19555
19449
  logger.debug(`[NextjsInstrumentation] Setting replay trace id`, replayTraceId);
19556
- if (self.replayHooks.extractShouldFetchEnvVars(req)) try {
19557
- const envVars = self.tuskDrift.requestEnvVarsSync(replayTraceId);
19558
- EnvVarTracker.setEnvVars(replayTraceId, envVars);
19559
- logger.debug(`[NextjsInstrumentation] Fetched env vars from CLI for trace ${replayTraceId}`);
19560
- } catch (error) {
19561
- logger.error(`[NextjsInstrumentation] Failed to fetch env vars from CLI:`, error);
19562
- }
19563
19450
  const ctxWithReplayTraceId = SpanUtils.setCurrentReplayTraceId(replayTraceId);
19564
19451
  if (!ctxWithReplayTraceId) throw new Error("Error setting current replay trace id");
19565
19452
  return import_src$11.context.with(ctxWithReplayTraceId, () => {
@@ -19714,10 +19601,8 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19714
19601
  decodedType: getDecodedType(outputValue.headers?.["content-type"] || "")
19715
19602
  },
19716
19603
  headers: { matchImportance: 0 }
19717
- },
19718
- metadata: { ENV_VARS: EnvVarTracker.getEnvVars(spanInfo.traceId) }
19604
+ }
19719
19605
  });
19720
- EnvVarTracker.clearEnvVars(spanInfo.traceId);
19721
19606
  const status = (capturedStatusCode || 200) >= 400 ? {
19722
19607
  code: import_src$11.SpanStatusCode.ERROR,
19723
19608
  message: `HTTP ${capturedStatusCode}`
@@ -19755,6 +19640,7 @@ var NextjsInstrumentation = class extends TdInstrumentationBase {
19755
19640
  instrumentationName: self.INSTRUMENTATION_NAME,
19756
19641
  submoduleName: completeInputValue.method,
19757
19642
  inputValue: completeInputValue,
19643
+ environment: self.tuskDrift.getEnvironment(),
19758
19644
  outputValue,
19759
19645
  inputSchema,
19760
19646
  outputSchema,
@@ -24244,7 +24130,7 @@ var SpanTransformer = class SpanTransformer {
24244
24130
  * Return type is derived from protobuf schema but uses clean JSON.
24245
24131
  * We use JSON because serialized protobuf is extremely verbose and not readable.
24246
24132
  */
24247
- static transformSpanToCleanJSON(span) {
24133
+ static transformSpanToCleanJSON(span, environment) {
24248
24134
  const isRootSpan = !span.parentSpanId || span.kind === import_src$9.SpanKind.SERVER;
24249
24135
  const attributes = span.attributes;
24250
24136
  const packageName = SpanTransformer.extractPackageName(attributes);
@@ -24288,6 +24174,7 @@ var SpanTransformer = class SpanTransformer {
24288
24174
  instrumentationName,
24289
24175
  submoduleName: submoduleName || "",
24290
24176
  packageType: attributes[TdSpanAttributes.PACKAGE_TYPE] || void 0,
24177
+ environment,
24291
24178
  inputValue: inputData,
24292
24179
  outputValue: outputData,
24293
24180
  inputSchema,
@@ -24751,7 +24638,7 @@ var ApiSpanAdapter = class {
24751
24638
  const protoSpans = spans.map((span) => this.transformSpanToProtobuf(span));
24752
24639
  const request = {
24753
24640
  observableServiceId: this.observableServiceId,
24754
- environment: this.environment,
24641
+ environment: this.environment || "",
24755
24642
  sdkVersion: this.sdkVersion,
24756
24643
  sdkInstanceId: this.sdkInstanceId,
24757
24644
  spans: protoSpans
@@ -24778,6 +24665,7 @@ var ApiSpanAdapter = class {
24778
24665
  instrumentationName: cleanSpan.instrumentationName,
24779
24666
  submoduleName: cleanSpan.submoduleName,
24780
24667
  packageType: cleanSpan.packageType || PackageType.UNSPECIFIED,
24668
+ environment: this.environment,
24781
24669
  inputValue: toStruct(cleanSpan.inputValue),
24782
24670
  outputValue: toStruct(cleanSpan.outputValue),
24783
24671
  inputSchema: cleanSpan.inputSchema,
@@ -24803,12 +24691,12 @@ var ApiSpanAdapter = class {
24803
24691
  }
24804
24692
  mapSpanKind(kind) {
24805
24693
  switch (kind) {
24806
- case import_src$7.SpanKind.CLIENT: return SpanKind.CLIENT;
24807
- case import_src$7.SpanKind.SERVER: return SpanKind.SERVER;
24808
- case import_src$7.SpanKind.PRODUCER: return SpanKind.PRODUCER;
24809
- case import_src$7.SpanKind.CONSUMER: return SpanKind.CONSUMER;
24810
- case import_src$7.SpanKind.INTERNAL: return SpanKind.INTERNAL;
24811
- default: return SpanKind.UNSPECIFIED;
24694
+ case import_src$7.SpanKind.CLIENT: return SpanKind$1.CLIENT;
24695
+ case import_src$7.SpanKind.SERVER: return SpanKind$1.SERVER;
24696
+ case import_src$7.SpanKind.PRODUCER: return SpanKind$1.PRODUCER;
24697
+ case import_src$7.SpanKind.CONSUMER: return SpanKind$1.CONSUMER;
24698
+ case import_src$7.SpanKind.INTERNAL: return SpanKind$1.INTERNAL;
24699
+ default: return SpanKind$1.UNSPECIFIED;
24812
24700
  }
24813
24701
  }
24814
24702
  async shutdown() {
@@ -24823,6 +24711,7 @@ var TdSpanExporter = class {
24823
24711
  constructor(config) {
24824
24712
  this.adapters = [];
24825
24713
  this.mode = config.mode;
24714
+ this.environment = config.environment;
24826
24715
  this.setupDefaultAdapters(config);
24827
24716
  logger.debug(`TdSpanExporter initialized with ${this.adapters.length} adapter(s)`);
24828
24717
  }
@@ -24906,7 +24795,7 @@ var TdSpanExporter = class {
24906
24795
  return true;
24907
24796
  });
24908
24797
  logger.debug(`Filtered ${filteredSpansBasedOnLibraryName.length - filteredBlockedSpans.length} blocked/oversized span(s), ${filteredBlockedSpans.length} remaining`);
24909
- const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span));
24798
+ const cleanSpans = filteredBlockedSpans.map((span) => SpanTransformer.transformSpanToCleanJSON(span, this.environment));
24910
24799
  if (this.adapters.length === 0) {
24911
24800
  logger.debug("No adapters configured");
24912
24801
  resultCallback({ code: import_src$5.ExportResultCode.SUCCESS });
@@ -32057,7 +31946,7 @@ var require_src = /* @__PURE__ */ __commonJS({ "node_modules/@opentelemetry/sdk-
32057
31946
  //#endregion
32058
31947
  //#region package.json
32059
31948
  var import_src$1 = /* @__PURE__ */ __toESM(require_src(), 1);
32060
- var version = "0.1.16";
31949
+ var version = "0.1.18";
32061
31950
 
32062
31951
  //#endregion
32063
31952
  //#region src/version.ts
@@ -32065,7 +31954,7 @@ const SDK_VERSION = version;
32065
31954
  const MIN_CLI_VERSION = "0.1.0";
32066
31955
 
32067
31956
  //#endregion
32068
- //#region node_modules/@use-tusk/drift-schemas/dist/communication-D4zqMBSI.js
31957
+ //#region node_modules/@use-tusk/drift-schemas/dist/communication-BY2KZhrg.js
32069
31958
  var import_commonjs = /* @__PURE__ */ __toESM(require_commonjs$1(), 1);
32070
31959
  var import_commonjs$1 = /* @__PURE__ */ __toESM(require_commonjs$2(), 1);
32071
31960
  /**
@@ -33209,12 +33098,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33209
33098
  });
33210
33099
  await this.sendProtobufMessage(sdkMessage);
33211
33100
  }
33212
- getStackTrace() {
33213
- Error.stackTraceLimit = 100;
33214
- const s = (/* @__PURE__ */ new Error()).stack || "";
33215
- Error.stackTraceLimit = 10;
33216
- return s.split("\n").slice(2).filter((l) => !l.includes("ProtobufCommunicator")).join("\n");
33217
- }
33218
33101
  async requestMockAsync(mockRequest) {
33219
33102
  const requestId = this.generateRequestId();
33220
33103
  const cleanSpan = mockRequest.outboundSpan ? this.cleanSpan(mockRequest.outboundSpan) : void 0;
@@ -33247,7 +33130,7 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33247
33130
  /**
33248
33131
  * Generic synchronous request handler that spawns a child process.
33249
33132
  * @param sdkMessage The SDK message to send
33250
- * @param filePrefix Prefix for temporary files (e.g., 'envvar', 'mock')
33133
+ * @param filePrefix Prefix for temporary files (e.g., 'mock')
33251
33134
  * @param responseHandler Function to extract and return the desired response
33252
33135
  */
33253
33136
  executeSyncRequest(sdkMessage, filePrefix, responseHandler) {
@@ -33316,35 +33199,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33316
33199
  }
33317
33200
  }
33318
33201
  /**
33319
- * Request environment variables from CLI synchronously using a child process.
33320
- * This blocks the main thread, so it should be used carefully.
33321
- * Similar to requestMockSync but for environment variables.
33322
- */
33323
- requestEnvVarsSync(traceTestServerSpanId) {
33324
- const requestId = this.generateRequestId();
33325
- const envVarRequest = EnvVarRequest.create({ traceTestServerSpanId });
33326
- const sdkMessage = SDKMessage.create({
33327
- type: MessageType$1.ENV_VAR_REQUEST,
33328
- requestId,
33329
- payload: {
33330
- oneofKind: "envVarRequest",
33331
- envVarRequest
33332
- }
33333
- });
33334
- logger.debug(`[ProtobufCommunicator] Requesting env vars (sync) for trace: ${traceTestServerSpanId}`);
33335
- return this.executeSyncRequest(sdkMessage, "envvar", (cliMessage) => {
33336
- if (cliMessage.payload.oneofKind !== "envVarResponse") throw new Error(`Unexpected response type: ${cliMessage.type}`);
33337
- const envVarResponse = cliMessage.payload.envVarResponse;
33338
- if (!envVarResponse) throw new Error("No env var response received");
33339
- const envVars = {};
33340
- if (envVarResponse.envVars) Object.entries(envVarResponse.envVars).forEach(([key, value]) => {
33341
- envVars[key] = value;
33342
- });
33343
- logger.debug(`[ProtobufCommunicator] Received env vars (sync), count: ${Object.keys(envVars).length}`);
33344
- return envVars;
33345
- });
33346
- }
33347
- /**
33348
33202
  * This function uses a separate Node.js child process to communicate with the CLI over a socket.
33349
33203
  * The child process creates its own connection and event loop, allowing proper async socket handling.
33350
33204
  * The parent process blocks synchronously waiting for the child to complete.
@@ -33555,22 +33409,6 @@ var ProtobufCommunicator = class ProtobufCommunicator {
33555
33409
  error: mockResponse.error || "Mock not found"
33556
33410
  });
33557
33411
  }
33558
- if (message.payload.oneofKind === "envVarResponse") {
33559
- const envVarResponse = message.payload.envVarResponse;
33560
- logger.debug(`[ProtobufCommunicator] Received env var response for requestId: ${requestId}`);
33561
- const pendingRequest = this.pendingRequests.get(requestId);
33562
- if (!pendingRequest) {
33563
- logger.warn("[ProtobufCommunicator] received env var response for unknown request:", requestId);
33564
- return;
33565
- }
33566
- this.pendingRequests.delete(requestId);
33567
- const envVars = {};
33568
- if (envVarResponse?.envVars) Object.entries(envVarResponse.envVars).forEach(([key, value]) => {
33569
- envVars[key] = value;
33570
- });
33571
- pendingRequest.resolve(envVars);
33572
- return;
33573
- }
33574
33412
  }
33575
33413
  /**
33576
33414
  * Extract response data from MockResponse
@@ -33870,10 +33708,6 @@ var TuskDriftCore = class TuskDriftCore {
33870
33708
  enabled: true,
33871
33709
  mode: this.mode
33872
33710
  });
33873
- new EnvInstrumentation({
33874
- enabled: this.config.recording?.enable_env_var_recording || false,
33875
- mode: this.mode
33876
- });
33877
33711
  new PostgresInstrumentation({
33878
33712
  enabled: true,
33879
33713
  mode: this.mode
@@ -33921,7 +33755,7 @@ var TuskDriftCore = class TuskDriftCore {
33921
33755
  observableServiceId: this.config.service?.id,
33922
33756
  apiKey: this.initParams.apiKey,
33923
33757
  tuskBackendBaseUrl: this.config.tusk_api?.url || "https://api.usetusk.ai",
33924
- environment: this.initParams.env || "unknown",
33758
+ environment: this.initParams.env,
33925
33759
  sdkVersion: SDK_VERSION,
33926
33760
  sdkInstanceId: this.generateSdkInstanceId()
33927
33761
  });
@@ -33939,6 +33773,34 @@ var TuskDriftCore = class TuskDriftCore {
33939
33773
  generateSdkInstanceId() {
33940
33774
  return `sdk-${OriginalGlobalUtils.getOriginalDate().getTime()}-${Math.random().toString(36).substr(2, 9)}`;
33941
33775
  }
33776
+ /**
33777
+ * Creates a pre-app-start span containing a snapshot of all environment variables.
33778
+ * Only runs in RECORD mode when env var recording is enabled.
33779
+ */
33780
+ createEnvVarsSnapshot() {
33781
+ if (this.mode !== TuskDriftMode.RECORD || !this.config.recording?.enable_env_var_recording) return;
33782
+ try {
33783
+ const envVarsSnapshot = {};
33784
+ for (const key of Object.keys(process.env)) envVarsSnapshot[key] = process.env[key];
33785
+ logger.debug(`Creating env vars snapshot with ${Object.keys(envVarsSnapshot).length} variables`);
33786
+ SpanUtils.createAndExecuteSpan(this.mode, () => {}, {
33787
+ name: "ENV_VARS_SNAPSHOT",
33788
+ kind: import_src.SpanKind.INTERNAL,
33789
+ packageName: "process.env",
33790
+ packageType: PackageType.UNSPECIFIED,
33791
+ instrumentationName: "TuskDriftCore",
33792
+ submodule: "env",
33793
+ inputValue: {},
33794
+ outputValue: { ENV_VARS: envVarsSnapshot },
33795
+ isPreAppStart: true
33796
+ }, (spanInfo) => {
33797
+ SpanUtils.endSpan(spanInfo.span, { code: import_src.SpanStatusCode.OK });
33798
+ logger.debug(`Env vars snapshot span created: ${spanInfo.spanId}`);
33799
+ });
33800
+ } catch (error) {
33801
+ logger.error("Failed to create env vars snapshot:", error);
33802
+ }
33803
+ }
33942
33804
  initialize(initParams) {
33943
33805
  initializeGlobalLogger({
33944
33806
  logLevel: initParams.logLevel || "info",
@@ -34015,6 +33877,7 @@ var TuskDriftCore = class TuskDriftCore {
34015
33877
  logger.debug(`Base directory: ${baseDirectory}`);
34016
33878
  this.registerDefaultInstrumentations();
34017
33879
  this.initializeTracing({ baseDirectory });
33880
+ this.createEnvVarsSnapshot();
34018
33881
  this.initialized = true;
34019
33882
  logger.info("SDK initialized successfully");
34020
33883
  }
@@ -34078,30 +33941,6 @@ var TuskDriftCore = class TuskDriftCore {
34078
33941
  };
34079
33942
  }
34080
33943
  }
34081
- /**
34082
- * Request environment variables from CLI for a specific trace (synchronously).
34083
- * This blocks the main thread, so it should be used carefully.
34084
- */
34085
- requestEnvVarsSync(traceTestServerSpanId) {
34086
- if (!this.isConnectedWithCLI) {
34087
- logger.error("Requesting sync env vars but CLI is not ready yet");
34088
- throw new Error("Requesting sync env vars but CLI is not ready yet");
34089
- }
34090
- if (!this.communicator || this.mode !== TuskDriftMode.REPLAY) {
34091
- logger.debug("Cannot request env vars: not in replay mode or no CLI connection");
34092
- return {};
34093
- }
34094
- try {
34095
- logger.debug(`Requesting env vars (sync) for trace: ${traceTestServerSpanId}`);
34096
- const envVars = this.communicator.requestEnvVarsSync(traceTestServerSpanId);
34097
- logger.debug(`Received env vars from CLI, count: ${Object.keys(envVars).length}`);
34098
- logger.debug(`First 10 env vars: ${JSON.stringify(Object.keys(envVars).slice(0, 10), null, 2)}`);
34099
- return envVars;
34100
- } catch (error) {
34101
- logger.error(`[TuskDrift] Error requesting env vars from CLI:`, error);
34102
- return {};
34103
- }
34104
- }
34105
33944
  requestMockSync(mockRequest) {
34106
33945
  if (!this.isConnectedWithCLI) {
34107
33946
  logger.error("Requesting sync mock but CLI is not ready yet");
@@ -34153,6 +33992,9 @@ var TuskDriftCore = class TuskDriftCore {
34153
33992
  getInitParams() {
34154
33993
  return this.initParams;
34155
33994
  }
33995
+ getEnvironment() {
33996
+ return this.initParams.env;
33997
+ }
34156
33998
  getTracer() {
34157
33999
  return import_src.trace.getTracer(TD_INSTRUMENTATION_LIBRARY_NAME);
34158
34000
  }