@brizz/sdk 0.1.1 → 0.1.2-rc.0

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.
Files changed (136) hide show
  1. package/README.md +339 -19
  2. package/dist/index.cjs +2936 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +178 -0
  5. package/dist/index.d.ts +177 -12
  6. package/dist/index.js +2895 -26
  7. package/dist/index.js.map +1 -1
  8. package/dist/loader.mjs +72 -0
  9. package/dist/preload.cjs +2786 -0
  10. package/dist/preload.cjs.map +1 -0
  11. package/dist/preload.d.cts +2 -0
  12. package/dist/preload.d.ts +2 -0
  13. package/dist/preload.js +2777 -0
  14. package/dist/preload.js.map +1 -0
  15. package/package.json +48 -35
  16. package/dist/index.d.ts.map +0 -1
  17. package/dist/internal/config.d.ts +0 -17
  18. package/dist/internal/config.d.ts.map +0 -1
  19. package/dist/internal/config.js +0 -94
  20. package/dist/internal/config.js.map +0 -1
  21. package/dist/internal/instrumentation/auto-init.d.ts +0 -3
  22. package/dist/internal/instrumentation/auto-init.d.ts.map +0 -1
  23. package/dist/internal/instrumentation/auto-init.js +0 -87
  24. package/dist/internal/instrumentation/auto-init.js.map +0 -1
  25. package/dist/internal/instrumentation/index.d.ts +0 -2
  26. package/dist/internal/instrumentation/index.d.ts.map +0 -1
  27. package/dist/internal/instrumentation/index.js +0 -6
  28. package/dist/internal/instrumentation/index.js.map +0 -1
  29. package/dist/internal/instrumentation/registry.d.ts +0 -30
  30. package/dist/internal/instrumentation/registry.d.ts.map +0 -1
  31. package/dist/internal/instrumentation/registry.js +0 -94
  32. package/dist/internal/instrumentation/registry.js.map +0 -1
  33. package/dist/internal/instrumentation/vercel-ai/index.d.ts +0 -4
  34. package/dist/internal/instrumentation/vercel-ai/index.d.ts.map +0 -1
  35. package/dist/internal/instrumentation/vercel-ai/index.js +0 -8
  36. package/dist/internal/instrumentation/vercel-ai/index.js.map +0 -1
  37. package/dist/internal/instrumentation/vercel-ai/instrumentation.d.ts +0 -16
  38. package/dist/internal/instrumentation/vercel-ai/instrumentation.d.ts.map +0 -1
  39. package/dist/internal/instrumentation/vercel-ai/instrumentation.js +0 -119
  40. package/dist/internal/instrumentation/vercel-ai/instrumentation.js.map +0 -1
  41. package/dist/internal/instrumentation/vercel-ai/patchers/base-patcher.d.ts +0 -24
  42. package/dist/internal/instrumentation/vercel-ai/patchers/base-patcher.d.ts.map +0 -1
  43. package/dist/internal/instrumentation/vercel-ai/patchers/base-patcher.js +0 -57
  44. package/dist/internal/instrumentation/vercel-ai/patchers/base-patcher.js.map +0 -1
  45. package/dist/internal/instrumentation/vercel-ai/patchers/embeddings-patcher.d.ts +0 -16
  46. package/dist/internal/instrumentation/vercel-ai/patchers/embeddings-patcher.d.ts.map +0 -1
  47. package/dist/internal/instrumentation/vercel-ai/patchers/embeddings-patcher.js +0 -58
  48. package/dist/internal/instrumentation/vercel-ai/patchers/embeddings-patcher.js.map +0 -1
  49. package/dist/internal/instrumentation/vercel-ai/patchers/generate-text-patcher.d.ts +0 -8
  50. package/dist/internal/instrumentation/vercel-ai/patchers/generate-text-patcher.d.ts.map +0 -1
  51. package/dist/internal/instrumentation/vercel-ai/patchers/generate-text-patcher.js +0 -59
  52. package/dist/internal/instrumentation/vercel-ai/patchers/generate-text-patcher.js.map +0 -1
  53. package/dist/internal/instrumentation/vercel-ai/patchers/index.d.ts +0 -5
  54. package/dist/internal/instrumentation/vercel-ai/patchers/index.d.ts.map +0 -1
  55. package/dist/internal/instrumentation/vercel-ai/patchers/index.js +0 -12
  56. package/dist/internal/instrumentation/vercel-ai/patchers/index.js.map +0 -1
  57. package/dist/internal/instrumentation/vercel-ai/patchers/stream-text-patcher.d.ts +0 -12
  58. package/dist/internal/instrumentation/vercel-ai/patchers/stream-text-patcher.d.ts.map +0 -1
  59. package/dist/internal/instrumentation/vercel-ai/patchers/stream-text-patcher.js +0 -41
  60. package/dist/internal/instrumentation/vercel-ai/patchers/stream-text-patcher.js.map +0 -1
  61. package/dist/internal/instrumentation/vercel-ai/semconv.d.ts +0 -53
  62. package/dist/internal/instrumentation/vercel-ai/semconv.d.ts.map +0 -1
  63. package/dist/internal/instrumentation/vercel-ai/semconv.js +0 -57
  64. package/dist/internal/instrumentation/vercel-ai/semconv.js.map +0 -1
  65. package/dist/internal/instrumentation/vercel-ai/stream-handler.d.ts +0 -13
  66. package/dist/internal/instrumentation/vercel-ai/stream-handler.d.ts.map +0 -1
  67. package/dist/internal/instrumentation/vercel-ai/stream-handler.js +0 -101
  68. package/dist/internal/instrumentation/vercel-ai/stream-handler.js.map +0 -1
  69. package/dist/internal/instrumentation/vercel-ai/telemetry-recorder.d.ts +0 -13
  70. package/dist/internal/instrumentation/vercel-ai/telemetry-recorder.d.ts.map +0 -1
  71. package/dist/internal/instrumentation/vercel-ai/telemetry-recorder.js +0 -115
  72. package/dist/internal/instrumentation/vercel-ai/telemetry-recorder.js.map +0 -1
  73. package/dist/internal/instrumentation/vercel-ai/types.d.ts +0 -197
  74. package/dist/internal/instrumentation/vercel-ai/types.d.ts.map +0 -1
  75. package/dist/internal/instrumentation/vercel-ai/types.js +0 -3
  76. package/dist/internal/instrumentation/vercel-ai/types.js.map +0 -1
  77. package/dist/internal/instrumentation/vercel-ai/utils.d.ts +0 -14
  78. package/dist/internal/instrumentation/vercel-ai/utils.d.ts.map +0 -1
  79. package/dist/internal/instrumentation/vercel-ai/utils.js +0 -243
  80. package/dist/internal/instrumentation/vercel-ai/utils.js.map +0 -1
  81. package/dist/internal/log/index.d.ts +0 -2
  82. package/dist/internal/log/index.d.ts.map +0 -1
  83. package/dist/internal/log/index.js +0 -7
  84. package/dist/internal/log/index.js.map +0 -1
  85. package/dist/internal/log/logging.d.ts +0 -21
  86. package/dist/internal/log/logging.d.ts.map +0 -1
  87. package/dist/internal/log/logging.js +0 -154
  88. package/dist/internal/log/logging.js.map +0 -1
  89. package/dist/internal/logger.d.ts +0 -23
  90. package/dist/internal/logger.d.ts.map +0 -1
  91. package/dist/internal/logger.js +0 -163
  92. package/dist/internal/logger.js.map +0 -1
  93. package/dist/internal/masking/index.d.ts +0 -4
  94. package/dist/internal/masking/index.d.ts.map +0 -1
  95. package/dist/internal/masking/index.js +0 -9
  96. package/dist/internal/masking/index.js.map +0 -1
  97. package/dist/internal/masking/patterns.d.ts +0 -3
  98. package/dist/internal/masking/patterns.d.ts.map +0 -1
  99. package/dist/internal/masking/patterns.js +0 -378
  100. package/dist/internal/masking/patterns.js.map +0 -1
  101. package/dist/internal/masking/types.d.ts +0 -33
  102. package/dist/internal/masking/types.d.ts.map +0 -1
  103. package/dist/internal/masking/types.js +0 -3
  104. package/dist/internal/masking/types.js.map +0 -1
  105. package/dist/internal/masking/utils.d.ts +0 -6
  106. package/dist/internal/masking/utils.d.ts.map +0 -1
  107. package/dist/internal/masking/utils.js +0 -232
  108. package/dist/internal/masking/utils.js.map +0 -1
  109. package/dist/internal/metric/index.d.ts +0 -2
  110. package/dist/internal/metric/index.d.ts.map +0 -1
  111. package/dist/internal/metric/index.js +0 -8
  112. package/dist/internal/metric/index.js.map +0 -1
  113. package/dist/internal/metric/metrics.d.ts +0 -18
  114. package/dist/internal/metric/metrics.d.ts.map +0 -1
  115. package/dist/internal/metric/metrics.js +0 -88
  116. package/dist/internal/metric/metrics.js.map +0 -1
  117. package/dist/internal/sdk.d.ts +0 -36
  118. package/dist/internal/sdk.d.ts.map +0 -1
  119. package/dist/internal/sdk.js +0 -159
  120. package/dist/internal/sdk.js.map +0 -1
  121. package/dist/internal/trace/index.d.ts +0 -3
  122. package/dist/internal/trace/index.d.ts.map +0 -1
  123. package/dist/internal/trace/index.js +0 -11
  124. package/dist/internal/trace/index.js.map +0 -1
  125. package/dist/internal/trace/processors/log-masked.d.ts +0 -16
  126. package/dist/internal/trace/processors/log-masked.d.ts.map +0 -1
  127. package/dist/internal/trace/processors/log-masked.js +0 -81
  128. package/dist/internal/trace/processors/log-masked.js.map +0 -1
  129. package/dist/internal/trace/processors/span-masked.d.ts +0 -16
  130. package/dist/internal/trace/processors/span-masked.d.ts.map +0 -1
  131. package/dist/internal/trace/processors/span-masked.js +0 -87
  132. package/dist/internal/trace/processors/span-masked.js.map +0 -1
  133. package/dist/internal/trace/tracing.d.ts +0 -18
  134. package/dist/internal/trace/tracing.d.ts.map +0 -1
  135. package/dist/internal/trace/tracing.js +0 -103
  136. package/dist/internal/trace/tracing.js.map +0 -1
@@ -0,0 +1,2786 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/internal/logger.ts
26
+ var import_api = require("@opentelemetry/api");
27
+ var import_pino = __toESM(require("pino"), 1);
28
+ var DEFAULT_LOG_LEVEL = 2 /* WARN */;
29
+ var PinoLogger = class {
30
+ _level = DEFAULT_LOG_LEVEL;
31
+ _pinoLogger = null;
32
+ constructor() {
33
+ const envLevel = this.getLogLevelFromEnv();
34
+ this._level = envLevel;
35
+ }
36
+ /**
37
+ * Lazy initialization of Pino logger to ensure it's created AFTER Jest spies
38
+ * are set up during tests. This prevents the pino-pretty transport from
39
+ * bypassing stdout/stderr spies.
40
+ */
41
+ ensurePinoLogger() {
42
+ if (!this._pinoLogger) {
43
+ this._pinoLogger = (0, import_pino.default)({
44
+ name: "Brizz",
45
+ level: this.logLevelToPino(this._level),
46
+ // Disable transport in test environment to allow proper spy capture
47
+ transport: this.isProduction() || this.isTest() ? void 0 : {
48
+ target: "pino-pretty",
49
+ options: {
50
+ singleLine: true,
51
+ colorize: true,
52
+ translateTime: "HH:MM:ss",
53
+ ignore: "pid,hostname",
54
+ messageFormat: "[{name}] {msg}"
55
+ }
56
+ }
57
+ });
58
+ }
59
+ return this._pinoLogger;
60
+ }
61
+ isProduction() {
62
+ return process.env["NODE_ENV"] === "production";
63
+ }
64
+ isTest() {
65
+ return process.env["NODE_ENV"] === "test";
66
+ }
67
+ getLogLevelFromEnv() {
68
+ const envLevel = process.env["BRIZZ_LOG_LEVEL"];
69
+ return envLevel ? parseLogLevel(envLevel) : DEFAULT_LOG_LEVEL;
70
+ }
71
+ logLevelToPino(level) {
72
+ switch (level) {
73
+ case 4 /* DEBUG */:
74
+ return "debug";
75
+ case 3 /* INFO */:
76
+ return "info";
77
+ case 2 /* WARN */:
78
+ return "warn";
79
+ case 1 /* ERROR */:
80
+ return "error";
81
+ default:
82
+ return "silent";
83
+ }
84
+ }
85
+ formatMeta(meta) {
86
+ if (meta.length === 0) {
87
+ return {};
88
+ }
89
+ if (meta.length === 1 && typeof meta[0] === "object" && meta[0] !== null) {
90
+ return meta[0];
91
+ }
92
+ return { metadata: meta };
93
+ }
94
+ setLevel(level) {
95
+ this._level = level;
96
+ if (this._pinoLogger) {
97
+ this._pinoLogger.level = this.logLevelToPino(level);
98
+ }
99
+ }
100
+ getLevel() {
101
+ return this._level;
102
+ }
103
+ debug = (msg, ...meta) => {
104
+ if (this._level >= 4 /* DEBUG */) {
105
+ this.ensurePinoLogger().debug(this.formatMeta(meta), msg);
106
+ }
107
+ };
108
+ info = (msg, ...meta) => {
109
+ if (this._level >= 3 /* INFO */) {
110
+ this.ensurePinoLogger().info(this.formatMeta(meta), msg);
111
+ }
112
+ };
113
+ warn = (msg, ...meta) => {
114
+ if (this._level >= 2 /* WARN */) {
115
+ this.ensurePinoLogger().warn(this.formatMeta(meta), msg);
116
+ }
117
+ };
118
+ error = (msg, ...meta) => {
119
+ if (this._level >= 1 /* ERROR */) {
120
+ this.ensurePinoLogger().error(this.formatMeta(meta), msg);
121
+ }
122
+ };
123
+ };
124
+ function parseLogLevel(level) {
125
+ if (!level) {
126
+ return DEFAULT_LOG_LEVEL;
127
+ }
128
+ const normalizedLevel = level.toLowerCase().trim();
129
+ switch (normalizedLevel) {
130
+ case "debug":
131
+ return 4 /* DEBUG */;
132
+ case "info":
133
+ return 3 /* INFO */;
134
+ case "warn":
135
+ case "warning":
136
+ return 2 /* WARN */;
137
+ case "error":
138
+ return 1 /* ERROR */;
139
+ case "none":
140
+ case "off":
141
+ case "silent":
142
+ return 0 /* NONE */;
143
+ default: {
144
+ const numLevel = Number.parseInt(normalizedLevel, 10);
145
+ if (!Number.isNaN(numLevel) && numLevel >= 0 && numLevel <= 4) {
146
+ return numLevel;
147
+ }
148
+ return DEFAULT_LOG_LEVEL;
149
+ }
150
+ }
151
+ }
152
+ var logger = new PinoLogger();
153
+ function setLogLevel(level) {
154
+ const resolvedLevel = typeof level === "string" ? parseLogLevel(level) : level;
155
+ logger.setLevel(resolvedLevel);
156
+ }
157
+
158
+ // src/internal/sdk.ts
159
+ var import_resources2 = require("@opentelemetry/resources");
160
+ var import_sdk_node = require("@opentelemetry/sdk-node");
161
+
162
+ // src/internal/config.ts
163
+ function resolveConfig(options) {
164
+ const envLogLevel = process.env["BRIZZ_LOG_LEVEL"] || options.logLevel?.toString() || DEFAULT_LOG_LEVEL.toString();
165
+ let resolvedLogLevel;
166
+ if (envLogLevel) {
167
+ resolvedLogLevel = parseLogLevel(envLogLevel);
168
+ } else if (typeof options.logLevel === "string") {
169
+ resolvedLogLevel = parseLogLevel(options.logLevel);
170
+ } else {
171
+ resolvedLogLevel = options.logLevel || DEFAULT_LOG_LEVEL;
172
+ }
173
+ setLogLevel(resolvedLogLevel);
174
+ let maskingStatus;
175
+ if (options.masking === true) {
176
+ maskingStatus = "enabled";
177
+ } else if (options.masking === false) {
178
+ maskingStatus = "disabled";
179
+ } else if (typeof options.masking === "object") {
180
+ maskingStatus = "custom";
181
+ } else {
182
+ maskingStatus = "default-disabled";
183
+ }
184
+ logger.debug("Starting configuration resolution", {
185
+ appName: options.appName,
186
+ baseUrl: options.baseUrl,
187
+ hasApiKey: !!options.apiKey,
188
+ disableBatch: options.disableBatch,
189
+ logLevel: resolvedLogLevel,
190
+ headersCount: Object.keys(options.headers || {}).length,
191
+ masking: maskingStatus
192
+ });
193
+ let resolvedMasking;
194
+ if (options.masking === true) {
195
+ resolvedMasking = {
196
+ spanMasking: {},
197
+ eventMasking: {}
198
+ };
199
+ } else if (options.masking && typeof options.masking === "object") {
200
+ resolvedMasking = options.masking;
201
+ }
202
+ const resolvedConfig = {
203
+ ...options,
204
+ appName: process.env["BRIZZ_APP_NAME"] || options.appName || "unknown-app",
205
+ baseUrl: process.env["BRIZZ_BASE_URL"] || options.baseUrl || "https://telemetry.brizz.dev",
206
+ headers: { ...options.headers },
207
+ apiKey: process.env["BRIZZ_API_KEY"] || options.apiKey,
208
+ disableBatch: process.env["BRIZZ_DISABLE_BATCH"] === "true" || !!options.disableBatch,
209
+ logLevel: resolvedLogLevel,
210
+ masking: resolvedMasking
211
+ };
212
+ if (resolvedConfig.apiKey) {
213
+ resolvedConfig.headers["Authorization"] = `Bearer ${resolvedConfig.apiKey}`;
214
+ }
215
+ if (process.env["BRIZZ_HEADERS"]) {
216
+ try {
217
+ const envHeaders = JSON.parse(process.env["BRIZZ_HEADERS"]);
218
+ Object.assign(resolvedConfig.headers, envHeaders);
219
+ logger.debug("Added headers from environment variable", {
220
+ headers: Object.keys(envHeaders)
221
+ });
222
+ } catch (error) {
223
+ logger.error("Failed to parse BRIZZ_HEADERS environment variable", { error });
224
+ throw new Error("Invalid JSON in BRIZZ_HEADERS environment variable");
225
+ }
226
+ }
227
+ logger.debug("Configuration resolved with environment variables", {
228
+ appName: resolvedConfig.appName,
229
+ baseUrl: resolvedConfig.baseUrl,
230
+ hasApiKey: !!resolvedConfig.apiKey,
231
+ disableBatch: resolvedConfig.disableBatch,
232
+ envOverrides: {
233
+ hasEnvApiKey: !!process.env["BRIZZ_API_KEY"],
234
+ hasEnvBaseUrl: !!process.env["BRIZZ_BASE_URL"],
235
+ hasEnvBatch: !!process.env["BRIZZ_DISABLE_BATCH"],
236
+ hasEnvHeaders: !!process.env["BRIZZ_HEADERS"]
237
+ }
238
+ });
239
+ return resolvedConfig;
240
+ }
241
+
242
+ // src/internal/instrumentation/registry.ts
243
+ var import_instrumentation_anthropic = require("@traceloop/instrumentation-anthropic");
244
+ var import_instrumentation_bedrock = require("@traceloop/instrumentation-bedrock");
245
+ var import_instrumentation_chromadb = require("@traceloop/instrumentation-chromadb");
246
+ var import_instrumentation_cohere = require("@traceloop/instrumentation-cohere");
247
+ var import_instrumentation_langchain = require("@traceloop/instrumentation-langchain");
248
+ var import_instrumentation_llamaindex = require("@traceloop/instrumentation-llamaindex");
249
+ var import_instrumentation_openai = require("@traceloop/instrumentation-openai");
250
+ var import_instrumentation_pinecone = require("@traceloop/instrumentation-pinecone");
251
+ var import_instrumentation_qdrant = require("@traceloop/instrumentation-qdrant");
252
+ var import_instrumentation_together = require("@traceloop/instrumentation-together");
253
+ var import_instrumentation_vertexai = require("@traceloop/instrumentation-vertexai");
254
+
255
+ // src/internal/instrumentation/vercel-ai/instrumentation.ts
256
+ var import_instrumentation = require("@opentelemetry/instrumentation");
257
+
258
+ // src/internal/instrumentation/vercel-ai/patchers/base-patcher.ts
259
+ var import_api2 = require("@opentelemetry/api");
260
+
261
+ // src/internal/instrumentation/vercel-ai/semconv.ts
262
+ var ATTR_GEN_AI_SYSTEM = "gen_ai.system";
263
+ var ATTR_GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
264
+ var ATTR_GEN_AI_REQUEST_MODEL = "gen_ai.request.model";
265
+ var ATTR_GEN_AI_REQUEST_MAX_TOKENS = "gen_ai.request.max_tokens";
266
+ var ATTR_GEN_AI_REQUEST_TEMPERATURE = "gen_ai.request.temperature";
267
+ var ATTR_GEN_AI_REQUEST_TOP_P = "gen_ai.request.top_p";
268
+ var ATTR_GEN_AI_REQUEST_TOP_K = "gen_ai.request.top_k";
269
+ var ATTR_GEN_AI_REQUEST_STOP_SEQUENCES = "gen_ai.request.stop_sequences";
270
+ var ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY = "gen_ai.request.frequency_penalty";
271
+ var ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY = "gen_ai.request.presence_penalty";
272
+ var ATTR_GEN_AI_RESPONSE_ID = "gen_ai.response.id";
273
+ var ATTR_GEN_AI_RESPONSE_MODEL = "gen_ai.response.model";
274
+ var ATTR_GEN_AI_RESPONSE_FINISH_REASONS = "gen_ai.response.finish_reasons";
275
+ var ATTR_GEN_AI_TOKEN_TYPE = "gen_ai.token.type";
276
+ var ATTR_GEN_AI_PROMPT = "gen_ai.prompt";
277
+ var ATTR_GEN_AI_COMPLETION = "gen_ai.completion";
278
+ var ATTR_GEN_AI_OPENAI_API_BASE = "gen_ai.openai.api_base";
279
+ var ATTR_EVENT_NAME = "event.name";
280
+ var EVENT_GEN_AI_USER_MESSAGE = "gen_ai.user.message";
281
+ var EVENT_GEN_AI_ASSISTANT_MESSAGE = "gen_ai.assistant.message";
282
+ var EVENT_GEN_AI_SYSTEM_MESSAGE = "gen_ai.system.message";
283
+ var EVENT_GEN_AI_TOOL_MESSAGE = "gen_ai.tool.message";
284
+ var METRIC_GEN_AI_CLIENT_OPERATION_DURATION = "gen_ai.client.operation.duration";
285
+ var METRIC_GEN_AI_CLIENT_TOKEN_USAGE = "gen_ai.client.token.usage";
286
+ var OPERATION_NAME_CHAT = "chat";
287
+ var OPERATION_NAME_EMBEDDINGS = "embeddings";
288
+ var TOKEN_TYPE_INPUT = "input";
289
+ var TOKEN_TYPE_OUTPUT = "output";
290
+ var PROVIDER_OPENAI = "openai";
291
+ var PROVIDER_ANTHROPIC = "anthropic";
292
+ var PROVIDER_GOOGLE = "google";
293
+ var PROVIDER_AMAZON = "amazon";
294
+ var PROVIDER_AZURE = "azure";
295
+ var PROVIDER_VERCEL = "vercel";
296
+ var PROVIDER_UNKNOWN = "unknown";
297
+ var SPAN_NAME_GEN_AI_CHAT = "gen_ai.chat";
298
+ var SPAN_NAME_GEN_AI_EMBEDDINGS = "gen_ai.embeddings";
299
+
300
+ // src/internal/instrumentation/vercel-ai/utils.ts
301
+ function detectProvider(model) {
302
+ if (typeof model === "object" && model !== null) {
303
+ const modelObj = model;
304
+ if (modelObj.provider) {
305
+ return {
306
+ system: normalizeProviderName(modelObj.provider),
307
+ apiBase: extractApiBase(modelObj)
308
+ };
309
+ }
310
+ if (modelObj.modelId) {
311
+ return detectProviderFromModelId(modelObj.modelId);
312
+ }
313
+ }
314
+ if (typeof model === "string") {
315
+ return detectProviderFromModelId(model);
316
+ }
317
+ return { system: PROVIDER_UNKNOWN };
318
+ }
319
+ function detectProviderFromModelId(modelId) {
320
+ const lowerModel = modelId.toLowerCase();
321
+ if (lowerModel.startsWith("gpt-") || lowerModel.startsWith("text-davinci-") || lowerModel.startsWith("text-embedding-") || lowerModel.startsWith("dall-e") || lowerModel.startsWith("whisper-") || lowerModel.startsWith("tts-")) {
322
+ return { system: PROVIDER_OPENAI };
323
+ }
324
+ if (lowerModel.startsWith("claude-")) {
325
+ return { system: PROVIDER_ANTHROPIC };
326
+ }
327
+ if (lowerModel.startsWith("gemini-") || lowerModel.startsWith("palm-") || lowerModel.includes("bison") || lowerModel.includes("gecko")) {
328
+ return { system: PROVIDER_GOOGLE };
329
+ }
330
+ if (lowerModel.startsWith("amazon.") || lowerModel.startsWith("anthropic.claude-") || lowerModel.startsWith("ai21.") || lowerModel.startsWith("cohere.") || lowerModel.startsWith("meta.llama")) {
331
+ return { system: PROVIDER_AMAZON };
332
+ }
333
+ if (lowerModel.includes("azure") || lowerModel.includes(".openai.azure.com")) {
334
+ return { system: PROVIDER_AZURE };
335
+ }
336
+ const parts = modelId.split(/[-._/]/);
337
+ if (parts.length > 0 && parts[0]) {
338
+ return { system: normalizeProviderName(parts[0]) };
339
+ }
340
+ return { system: PROVIDER_UNKNOWN };
341
+ }
342
+ function normalizeProviderName(provider) {
343
+ const normalized = provider.toLowerCase().trim();
344
+ switch (normalized) {
345
+ case "openai":
346
+ case "open-ai":
347
+ case "open_ai": {
348
+ return PROVIDER_OPENAI;
349
+ }
350
+ case "anthropic":
351
+ case "claude": {
352
+ return PROVIDER_ANTHROPIC;
353
+ }
354
+ case "google":
355
+ case "vertex":
356
+ case "vertexai":
357
+ case "vertex-ai":
358
+ case "gemini": {
359
+ return PROVIDER_GOOGLE;
360
+ }
361
+ case "amazon":
362
+ case "aws":
363
+ case "bedrock":
364
+ case "amazon-bedrock": {
365
+ return PROVIDER_AMAZON;
366
+ }
367
+ case "azure":
368
+ case "azure-openai":
369
+ case "microsoft": {
370
+ return PROVIDER_AZURE;
371
+ }
372
+ case "vercel":
373
+ case "vercel-ai": {
374
+ return PROVIDER_VERCEL;
375
+ }
376
+ default: {
377
+ return normalized;
378
+ }
379
+ }
380
+ }
381
+ function extractApiBase(model) {
382
+ if (typeof model === "object" && model !== null) {
383
+ const anyModel = model;
384
+ return anyModel.apiBase || anyModel.baseURL || anyModel.endpoint || void 0;
385
+ }
386
+ return void 0;
387
+ }
388
+ function extractModelId(model) {
389
+ if (typeof model === "string") {
390
+ return model;
391
+ }
392
+ if (typeof model === "object" && model !== null) {
393
+ return model.modelId || "unknown";
394
+ }
395
+ return "unknown";
396
+ }
397
+ function messagesToAttributes(messages, prefix, captureContent) {
398
+ const attributes = {};
399
+ for (const [index, msg] of messages.entries()) {
400
+ const baseKey = `${prefix}.${index}`;
401
+ attributes[`${baseKey}.role`] = msg.role;
402
+ if (captureContent && msg.content) {
403
+ if (typeof msg.content === "string") {
404
+ attributes[`${baseKey}.content`] = msg.content;
405
+ } else if (Array.isArray(msg.content)) {
406
+ const textParts = msg.content.filter((part) => part.type === "text" && part.text).map((part) => part.text).join(" ");
407
+ if (textParts) {
408
+ attributes[`${baseKey}.content`] = textParts;
409
+ }
410
+ }
411
+ }
412
+ if (msg.toolInvocations && msg.toolInvocations.length > 0) {
413
+ attributes[`${baseKey}.tool_calls`] = msg.toolInvocations.length;
414
+ }
415
+ }
416
+ return attributes;
417
+ }
418
+ function promptToAttributes(prompt, captureContent) {
419
+ const attributes = {};
420
+ attributes[`${ATTR_GEN_AI_PROMPT}.0.role`] = "user";
421
+ if (captureContent) {
422
+ attributes[`${ATTR_GEN_AI_PROMPT}.0.content`] = prompt;
423
+ }
424
+ return attributes;
425
+ }
426
+ function completionToAttributes(text, finishReason, captureContent) {
427
+ const attributes = {};
428
+ attributes[`${ATTR_GEN_AI_COMPLETION}.0.role`] = "assistant";
429
+ if (captureContent) {
430
+ attributes[`${ATTR_GEN_AI_COMPLETION}.0.content`] = text;
431
+ }
432
+ if (finishReason) {
433
+ attributes[`${ATTR_GEN_AI_COMPLETION}.0.finish_reason`] = finishReason;
434
+ }
435
+ return attributes;
436
+ }
437
+ function tokenUsageToAttributes(usage) {
438
+ if (!usage) {
439
+ return {};
440
+ }
441
+ const attributes = {};
442
+ if (usage.inputTokens !== void 0) {
443
+ attributes["gen_ai.usage.prompt_tokens"] = usage.inputTokens;
444
+ attributes["gen_ai.usage.input_tokens"] = usage.inputTokens;
445
+ attributes["llm.usage.prompt_tokens"] = usage.inputTokens;
446
+ } else if (usage.promptTokens !== void 0) {
447
+ attributes["gen_ai.usage.prompt_tokens"] = usage.promptTokens;
448
+ attributes["gen_ai.usage.input_tokens"] = usage.promptTokens;
449
+ attributes["llm.usage.prompt_tokens"] = usage.promptTokens;
450
+ }
451
+ if (usage.outputTokens !== void 0) {
452
+ attributes["gen_ai.usage.completion_tokens"] = usage.outputTokens;
453
+ attributes["gen_ai.usage.output_tokens"] = usage.outputTokens;
454
+ attributes["llm.usage.completion_tokens"] = usage.outputTokens;
455
+ } else if (usage.completionTokens !== void 0) {
456
+ attributes["gen_ai.usage.completion_tokens"] = usage.completionTokens;
457
+ attributes["gen_ai.usage.output_tokens"] = usage.completionTokens;
458
+ attributes["llm.usage.completion_tokens"] = usage.completionTokens;
459
+ }
460
+ if (usage.totalTokens === void 0) {
461
+ const inputTokens = usage.inputTokens || usage.promptTokens;
462
+ const outputTokens = usage.outputTokens || usage.completionTokens;
463
+ if (inputTokens !== void 0 && outputTokens !== void 0) {
464
+ const totalTokens = inputTokens + outputTokens;
465
+ attributes["gen_ai.usage.total_tokens"] = totalTokens;
466
+ attributes["llm.usage.total_tokens"] = totalTokens;
467
+ }
468
+ } else {
469
+ attributes["gen_ai.usage.total_tokens"] = usage.totalTokens;
470
+ attributes["llm.usage.total_tokens"] = usage.totalTokens;
471
+ }
472
+ return attributes;
473
+ }
474
+ function shouldRecordError(error) {
475
+ if (error instanceof Error) {
476
+ const message = error.message.toLowerCase();
477
+ if (message.includes("abort") || message.includes("cancel")) {
478
+ return false;
479
+ }
480
+ }
481
+ return true;
482
+ }
483
+ function getEnvBool(name) {
484
+ const value = process.env[name];
485
+ if (value === void 0) {
486
+ return void 0;
487
+ }
488
+ return value.toLowerCase() === "true" || value === "1";
489
+ }
490
+
491
+ // src/internal/instrumentation/vercel-ai/patchers/base-patcher.ts
492
+ var BasePatcher = class {
493
+ constructor(context8) {
494
+ this.context = context8;
495
+ }
496
+ createSpan(spanName, params, operationName, additionalAttributes) {
497
+ const provider = detectProvider(params.model);
498
+ const modelId = extractModelId(params.model);
499
+ const span = this.context.tracer.startSpan(spanName, {
500
+ kind: import_api2.SpanKind.CLIENT,
501
+ attributes: {
502
+ [ATTR_GEN_AI_SYSTEM]: provider.system,
503
+ [ATTR_GEN_AI_OPERATION_NAME]: operationName,
504
+ [ATTR_GEN_AI_REQUEST_MODEL]: modelId,
505
+ ...params.maxTokens && { [ATTR_GEN_AI_REQUEST_MAX_TOKENS]: params.maxTokens },
506
+ ...params.temperature !== void 0 && {
507
+ [ATTR_GEN_AI_REQUEST_TEMPERATURE]: params.temperature
508
+ },
509
+ ...params.topP !== void 0 && { [ATTR_GEN_AI_REQUEST_TOP_P]: params.topP },
510
+ ...params.topK !== void 0 && { [ATTR_GEN_AI_REQUEST_TOP_K]: params.topK },
511
+ ...params.frequencyPenalty !== void 0 && {
512
+ [ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY]: params.frequencyPenalty
513
+ },
514
+ ...params.presencePenalty !== void 0 && {
515
+ [ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY]: params.presencePenalty
516
+ },
517
+ ...params.stopSequences && {
518
+ [ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]: params.stopSequences
519
+ },
520
+ ...provider.apiBase && { [ATTR_GEN_AI_OPENAI_API_BASE]: provider.apiBase },
521
+ ...additionalAttributes
522
+ }
523
+ });
524
+ return { span, provider, modelId };
525
+ }
526
+ handleError(error, span) {
527
+ if (shouldRecordError(error)) {
528
+ span.recordException(error);
529
+ span.setStatus({ code: import_api2.SpanStatusCode.ERROR, message: error.message });
530
+ }
531
+ }
532
+ finalizeDuration(span, startTime, config, provider, modelId, operationName) {
533
+ if (config.enableMetrics) {
534
+ const duration = (globalThis.performance.now() - startTime) / 1e3;
535
+ this.context.recordDurationMetric(duration, provider.system, modelId, operationName);
536
+ }
537
+ span.end();
538
+ }
539
+ };
540
+
541
+ // src/internal/instrumentation/vercel-ai/patchers/generate-text-patcher.ts
542
+ var import_api3 = require("@opentelemetry/api");
543
+ var GenerateTextPatcher = class extends BasePatcher {
544
+ patch(original) {
545
+ return async (params) => {
546
+ const config = this.context.getConfig();
547
+ const startTime = globalThis.performance.now();
548
+ const { span, provider, modelId } = this.createSpan(
549
+ SPAN_NAME_GEN_AI_CHAT,
550
+ params,
551
+ OPERATION_NAME_CHAT
552
+ );
553
+ if (params.prompt) {
554
+ span.setAttributes(
555
+ promptToAttributes(params.prompt, config.captureMessageContent || false)
556
+ );
557
+ } else if (params.messages) {
558
+ span.setAttributes(
559
+ messagesToAttributes(
560
+ params.messages,
561
+ "gen_ai.prompt",
562
+ config.captureMessageContent || false
563
+ )
564
+ );
565
+ if (config.emitEvents) {
566
+ this.context.emitMessageEvents(params.messages, provider.system, span);
567
+ }
568
+ }
569
+ try {
570
+ const result = await import_api3.context.with(
571
+ import_api3.trace.setSpan(import_api3.context.active(), span),
572
+ () => original(params)
573
+ );
574
+ if (result.response) {
575
+ span.setAttributes({
576
+ ...result.response.id && { [ATTR_GEN_AI_RESPONSE_ID]: result.response.id },
577
+ ...result.response.model && { [ATTR_GEN_AI_RESPONSE_MODEL]: result.response.model }
578
+ });
579
+ }
580
+ if (result.finishReason) {
581
+ span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [result.finishReason]);
582
+ }
583
+ span.setAttributes(
584
+ completionToAttributes(
585
+ result.text,
586
+ result.finishReason,
587
+ config.captureMessageContent || false
588
+ )
589
+ );
590
+ const usage = result.usage || result.totalUsage || result.steps?.[0]?.usage;
591
+ if (usage) {
592
+ span.setAttributes(tokenUsageToAttributes(usage));
593
+ if (config.enableMetrics) {
594
+ this.context.recordTokenMetrics(usage, provider.system, modelId);
595
+ }
596
+ }
597
+ if (config.emitEvents) {
598
+ this.context.emitAssistantMessageEvent(result.text, provider.system, span);
599
+ }
600
+ span.setStatus({ code: import_api3.SpanStatusCode.OK });
601
+ return result;
602
+ } catch (error) {
603
+ this.handleError(error, span);
604
+ throw error;
605
+ } finally {
606
+ this.finalizeDuration(span, startTime, config, provider, modelId, OPERATION_NAME_CHAT);
607
+ }
608
+ };
609
+ }
610
+ };
611
+
612
+ // src/internal/instrumentation/vercel-ai/patchers/stream-text-patcher.ts
613
+ var import_api4 = require("@opentelemetry/api");
614
+ var StreamTextPatcher = class extends BasePatcher {
615
+ constructor(context8, streamHandler) {
616
+ super(context8);
617
+ this.streamHandler = streamHandler;
618
+ }
619
+ patch(original) {
620
+ return async (params) => {
621
+ const config = this.context.getConfig();
622
+ const startTime = globalThis.performance.now();
623
+ const { span, provider, modelId } = this.createSpan(
624
+ SPAN_NAME_GEN_AI_CHAT,
625
+ params,
626
+ OPERATION_NAME_CHAT,
627
+ { "gen_ai.streaming": true }
628
+ );
629
+ if (params.prompt) {
630
+ span.setAttributes(
631
+ promptToAttributes(params.prompt, config.captureMessageContent || false)
632
+ );
633
+ } else if (params.messages) {
634
+ span.setAttributes(
635
+ messagesToAttributes(
636
+ params.messages,
637
+ "gen_ai.prompt",
638
+ config.captureMessageContent || false
639
+ )
640
+ );
641
+ if (config.emitEvents) {
642
+ this.context.emitMessageEvents(params.messages, provider.system, span);
643
+ }
644
+ }
645
+ try {
646
+ const stream = await import_api4.context.with(
647
+ import_api4.trace.setSpan(import_api4.context.active(), span),
648
+ () => original(params)
649
+ );
650
+ return this.streamHandler.wrapStream(stream, span, config, provider, modelId, startTime);
651
+ } catch (error) {
652
+ this.handleError(error, span);
653
+ span.end();
654
+ throw error;
655
+ }
656
+ };
657
+ }
658
+ };
659
+
660
+ // src/internal/instrumentation/vercel-ai/patchers/embeddings-patcher.ts
661
+ var import_api5 = require("@opentelemetry/api");
662
+ var EmbeddingsPatcher = class extends BasePatcher {
663
+ patch(original, isMany = false) {
664
+ return async (params) => {
665
+ const config = this.context.getConfig();
666
+ const startTime = globalThis.performance.now();
667
+ const additionalAttributes = isMany ? { "gen_ai.embeddings.count": params.values ? params.values.length : 0 } : {};
668
+ const { span, provider, modelId } = this.createSpan(
669
+ SPAN_NAME_GEN_AI_EMBEDDINGS,
670
+ params,
671
+ OPERATION_NAME_EMBEDDINGS,
672
+ additionalAttributes
673
+ );
674
+ if (!isMany && config.captureMessageContent && params.value) {
675
+ span.setAttribute("gen_ai.prompt.0.content", params.value);
676
+ }
677
+ try {
678
+ const result = await import_api5.context.with(
679
+ import_api5.trace.setSpan(import_api5.context.active(), span),
680
+ () => original(params)
681
+ );
682
+ if (result.response) {
683
+ span.setAttributes({
684
+ ...result.response.id && { [ATTR_GEN_AI_RESPONSE_ID]: result.response.id },
685
+ ...result.response.model && { [ATTR_GEN_AI_RESPONSE_MODEL]: result.response.model }
686
+ });
687
+ }
688
+ if (isMany) {
689
+ if (result.embeddings && result.embeddings.length > 0 && result.embeddings[0]) {
690
+ span.setAttribute("gen_ai.response.embedding_dimensions", result.embeddings[0].length);
691
+ }
692
+ } else {
693
+ if (result.embedding) {
694
+ span.setAttribute("gen_ai.response.embedding_dimensions", result.embedding.length);
695
+ }
696
+ }
697
+ if (result.usage) {
698
+ span.setAttributes(tokenUsageToAttributes(result.usage));
699
+ if (config.enableMetrics) {
700
+ this.context.recordTokenMetrics(result.usage, provider.system, modelId);
701
+ }
702
+ }
703
+ span.setStatus({ code: import_api5.SpanStatusCode.OK });
704
+ return result;
705
+ } catch (error) {
706
+ this.handleError(error, span);
707
+ throw error;
708
+ } finally {
709
+ this.finalizeDuration(span, startTime, config, provider, modelId, OPERATION_NAME_EMBEDDINGS);
710
+ }
711
+ };
712
+ }
713
+ };
714
+
715
+ // src/internal/instrumentation/vercel-ai/stream-handler.ts
716
+ var import_api6 = require("@opentelemetry/api");
717
+ var StreamHandler = class {
718
+ constructor(context8) {
719
+ this.context = context8;
720
+ }
721
+ wrapStream(stream, span, config, provider, modelId, startTime) {
722
+ const self = this;
723
+ let fullText = "";
724
+ let finishReason;
725
+ let usage;
726
+ let response;
727
+ const wrappedStream = new Proxy(stream, {
728
+ get(target, prop) {
729
+ if (prop === Symbol.asyncIterator) {
730
+ return async function* () {
731
+ try {
732
+ for await (const chunk of target) {
733
+ if (chunk.type === "text-delta" && chunk.textDelta) {
734
+ fullText += chunk.textDelta;
735
+ } else if (chunk.type === "finish") {
736
+ finishReason = chunk.finishReason;
737
+ usage = chunk.usage;
738
+ } else if (chunk.type === "response-metadata") {
739
+ response = chunk.response;
740
+ }
741
+ yield chunk;
742
+ }
743
+ } finally {
744
+ self.finalizeStream(
745
+ span,
746
+ config,
747
+ provider,
748
+ modelId,
749
+ startTime,
750
+ fullText,
751
+ finishReason,
752
+ usage,
753
+ response
754
+ );
755
+ }
756
+ };
757
+ }
758
+ if (prop === "textStream" || prop === "fullStream") {
759
+ const originalStream = target[prop];
760
+ return {
761
+ [Symbol.asyncIterator]: async function* () {
762
+ try {
763
+ for await (const chunk of originalStream) {
764
+ if (prop === "textStream") {
765
+ fullText += chunk;
766
+ }
767
+ yield chunk;
768
+ }
769
+ } finally {
770
+ const streamUsage = await target.usage.catch(() => null);
771
+ if (streamUsage) {
772
+ usage = streamUsage;
773
+ }
774
+ self.finalizeStream(
775
+ span,
776
+ config,
777
+ provider,
778
+ modelId,
779
+ startTime,
780
+ fullText,
781
+ finishReason,
782
+ usage,
783
+ response
784
+ );
785
+ }
786
+ }
787
+ };
788
+ }
789
+ const value = target[prop];
790
+ if (typeof value === "function") {
791
+ return value.bind(target);
792
+ }
793
+ return value;
794
+ }
795
+ });
796
+ return wrappedStream;
797
+ }
798
+ finalizeStream(span, config, provider, modelId, startTime, fullText, finishReason, usage, response) {
799
+ if (response) {
800
+ span.setAttributes({
801
+ ...response.id && { [ATTR_GEN_AI_RESPONSE_ID]: response.id },
802
+ ...response.model && { [ATTR_GEN_AI_RESPONSE_MODEL]: response.model }
803
+ });
804
+ }
805
+ if (finishReason) {
806
+ span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [finishReason]);
807
+ }
808
+ if (fullText) {
809
+ span.setAttributes(
810
+ completionToAttributes(
811
+ fullText,
812
+ finishReason,
813
+ config.captureMessageContent || false
814
+ )
815
+ );
816
+ }
817
+ if (usage) {
818
+ span.setAttributes(tokenUsageToAttributes(usage));
819
+ if (config.enableMetrics) {
820
+ this.context.recordTokenMetrics(usage, provider.system, modelId);
821
+ }
822
+ }
823
+ if (config.enableMetrics) {
824
+ const duration = (performance.now() - startTime) / 1e3;
825
+ this.context.recordDurationMetric(duration, provider.system, modelId, OPERATION_NAME_CHAT);
826
+ }
827
+ span.setStatus({ code: import_api6.SpanStatusCode.OK });
828
+ span.end();
829
+ }
830
+ };
831
+
832
+ // src/internal/instrumentation/vercel-ai/telemetry-recorder.ts
833
+ var import_api7 = require("@opentelemetry/api");
834
+ var import_api_logs = require("@opentelemetry/api-logs");
835
+ var TelemetryRecorder = class {
836
+ constructor(genaiClientOperationDuration, genaiClientTokenUsage, logger2) {
837
+ this.genaiClientOperationDuration = genaiClientOperationDuration;
838
+ this.genaiClientTokenUsage = genaiClientTokenUsage;
839
+ this.logger = logger2;
840
+ }
841
+ /**
842
+ * Record token usage metrics
843
+ */
844
+ recordTokenMetrics(usage, system, model) {
845
+ if (!this.genaiClientTokenUsage) {
846
+ return;
847
+ }
848
+ const commonAttrs = {
849
+ [ATTR_GEN_AI_SYSTEM]: system,
850
+ [ATTR_GEN_AI_REQUEST_MODEL]: model
851
+ };
852
+ const inputTokens = usage.inputTokens || usage.promptTokens;
853
+ const outputTokens = usage.outputTokens || usage.completionTokens;
854
+ if (inputTokens !== void 0) {
855
+ this.genaiClientTokenUsage.record(inputTokens, {
856
+ ...commonAttrs,
857
+ [ATTR_GEN_AI_TOKEN_TYPE]: TOKEN_TYPE_INPUT
858
+ });
859
+ }
860
+ if (outputTokens !== void 0) {
861
+ this.genaiClientTokenUsage.record(outputTokens, {
862
+ ...commonAttrs,
863
+ [ATTR_GEN_AI_TOKEN_TYPE]: TOKEN_TYPE_OUTPUT
864
+ });
865
+ }
866
+ }
867
+ /**
868
+ * Record operation duration metric
869
+ */
870
+ recordDurationMetric(duration, system, model, operation) {
871
+ if (!this.genaiClientOperationDuration) {
872
+ return;
873
+ }
874
+ this.genaiClientOperationDuration.record(duration, {
875
+ [ATTR_GEN_AI_SYSTEM]: system,
876
+ [ATTR_GEN_AI_REQUEST_MODEL]: model,
877
+ [ATTR_GEN_AI_OPERATION_NAME]: operation
878
+ });
879
+ }
880
+ /**
881
+ * Emit message events
882
+ */
883
+ emitMessageEvents(messages, system, span) {
884
+ if (!this.logger) {
885
+ return;
886
+ }
887
+ const ctx = import_api7.trace.setSpan(import_api7.context.active(), span);
888
+ for (const msg of messages) {
889
+ let eventName;
890
+ switch (msg.role) {
891
+ case "system": {
892
+ eventName = EVENT_GEN_AI_SYSTEM_MESSAGE;
893
+ break;
894
+ }
895
+ case "user": {
896
+ eventName = EVENT_GEN_AI_USER_MESSAGE;
897
+ break;
898
+ }
899
+ case "assistant": {
900
+ eventName = EVENT_GEN_AI_ASSISTANT_MESSAGE;
901
+ break;
902
+ }
903
+ case "tool":
904
+ case "function": {
905
+ eventName = EVENT_GEN_AI_TOOL_MESSAGE;
906
+ break;
907
+ }
908
+ default: {
909
+ continue;
910
+ }
911
+ }
912
+ this.logger.emit({
913
+ timestamp: Date.now(),
914
+ context: ctx,
915
+ severityNumber: import_api_logs.SeverityNumber.INFO,
916
+ attributes: {
917
+ [ATTR_EVENT_NAME]: eventName,
918
+ [ATTR_GEN_AI_SYSTEM]: system
919
+ },
920
+ body: {
921
+ role: msg.role,
922
+ content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
923
+ name: msg.name
924
+ }
925
+ });
926
+ }
927
+ }
928
+ /**
929
+ * Emit assistant message event
930
+ */
931
+ emitAssistantMessageEvent(text, system, span) {
932
+ if (!this.logger) {
933
+ return;
934
+ }
935
+ const ctx = import_api7.trace.setSpan(import_api7.context.active(), span);
936
+ this.logger.emit({
937
+ timestamp: Date.now(),
938
+ context: ctx,
939
+ severityNumber: import_api_logs.SeverityNumber.INFO,
940
+ attributes: {
941
+ [ATTR_EVENT_NAME]: EVENT_GEN_AI_ASSISTANT_MESSAGE,
942
+ [ATTR_GEN_AI_SYSTEM]: system
943
+ },
944
+ body: {
945
+ role: "assistant",
946
+ content: text
947
+ }
948
+ });
949
+ }
950
+ };
951
+
952
+ // src/internal/instrumentation/vercel-ai/instrumentation.ts
953
+ var PACKAGE_NAME = "@brizz/vercel-ai-instrumentation";
954
+ var PACKAGE_VERSION = "0.1.0";
955
+ var VercelAIInstrumentation = class _VercelAIInstrumentation extends import_instrumentation.InstrumentationBase {
956
+ _genaiClientOperationDuration;
957
+ _genaiClientTokenUsage;
958
+ _telemetryRecorder;
959
+ _streamHandler;
960
+ _patchers = /* @__PURE__ */ new Map();
961
+ // Holds last patched namespace when available (reserved for future factory wrapping)
962
+ _vercelAiNamespace = null;
963
+ static _WRAPPED_SYMBOL = Symbol.for("brizz.vercel-ai.patched");
964
+ constructor(config = {}) {
965
+ super(PACKAGE_NAME, PACKAGE_VERSION, config);
966
+ const cfg = this.getConfig();
967
+ const envCC = getEnvBool("OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT");
968
+ if (envCC !== void 0) {
969
+ cfg.captureMessageContent = envCC;
970
+ }
971
+ this._initializeComponents();
972
+ }
973
+ setConfig(config = {}) {
974
+ const {
975
+ captureMessageContent = true,
976
+ enableMetrics = true,
977
+ emitEvents = true,
978
+ ...validConfig
979
+ } = config;
980
+ const fullConfig = {
981
+ ...validConfig,
982
+ captureMessageContent,
983
+ enableMetrics,
984
+ emitEvents
985
+ };
986
+ super.setConfig(fullConfig);
987
+ }
988
+ _initializeComponents() {
989
+ this._telemetryRecorder = new TelemetryRecorder(
990
+ this._genaiClientOperationDuration,
991
+ this._genaiClientTokenUsage,
992
+ this.logger
993
+ );
994
+ this._streamHandler = new StreamHandler({
995
+ recordTokenMetrics: this._telemetryRecorder.recordTokenMetrics.bind(this._telemetryRecorder),
996
+ recordDurationMetric: this._telemetryRecorder.recordDurationMetric.bind(
997
+ this._telemetryRecorder
998
+ )
999
+ });
1000
+ const patcherContext = {
1001
+ tracer: this.tracer,
1002
+ getConfig: this.getConfig.bind(this),
1003
+ recordTokenMetrics: this._telemetryRecorder.recordTokenMetrics.bind(this._telemetryRecorder),
1004
+ recordDurationMetric: this._telemetryRecorder.recordDurationMetric.bind(
1005
+ this._telemetryRecorder
1006
+ ),
1007
+ emitMessageEvents: this._telemetryRecorder.emitMessageEvents.bind(this._telemetryRecorder),
1008
+ emitAssistantMessageEvent: this._telemetryRecorder.emitAssistantMessageEvent.bind(
1009
+ this._telemetryRecorder
1010
+ )
1011
+ };
1012
+ this._patchers.set("generateText", new GenerateTextPatcher(patcherContext));
1013
+ this._patchers.set("streamText", new StreamTextPatcher(patcherContext, this._streamHandler));
1014
+ this._patchers.set("embed", new EmbeddingsPatcher(patcherContext));
1015
+ this._patchers.set("embedMany", new EmbeddingsPatcher(patcherContext));
1016
+ }
1017
+ init() {
1018
+ return [
1019
+ new import_instrumentation.InstrumentationNodeModuleDefinition(
1020
+ "ai",
1021
+ [">=4.0.0 <6"],
1022
+ (moduleExports) => {
1023
+ logger.info("Starting instrumentation of Vercel AI SDK module");
1024
+ this._vercelAiNamespace = moduleExports;
1025
+ const patched = this._patchModuleExports(moduleExports);
1026
+ return patched ?? moduleExports;
1027
+ },
1028
+ (moduleExports) => {
1029
+ logger.debug("Uninstrumenting @vercel/ai module");
1030
+ return moduleExports;
1031
+ }
1032
+ )
1033
+ ];
1034
+ }
1035
+ _updateMetricInstruments() {
1036
+ const config = this.getConfig();
1037
+ if (!config.enableMetrics) {
1038
+ return;
1039
+ }
1040
+ this._genaiClientOperationDuration = this.meter.createHistogram(
1041
+ METRIC_GEN_AI_CLIENT_OPERATION_DURATION,
1042
+ {
1043
+ description: "GenAI operation duration",
1044
+ unit: "s",
1045
+ advice: {
1046
+ explicitBucketBoundaries: [
1047
+ 0.01,
1048
+ 0.02,
1049
+ 0.04,
1050
+ 0.08,
1051
+ 0.16,
1052
+ 0.32,
1053
+ 0.64,
1054
+ 1.28,
1055
+ 2.56,
1056
+ 5.12,
1057
+ 10.24,
1058
+ 20.48,
1059
+ 40.96,
1060
+ 81.92
1061
+ ]
1062
+ }
1063
+ }
1064
+ );
1065
+ this._genaiClientTokenUsage = this.meter.createHistogram(METRIC_GEN_AI_CLIENT_TOKEN_USAGE, {
1066
+ description: "Measures number of input and output tokens used",
1067
+ unit: "{token}",
1068
+ advice: {
1069
+ explicitBucketBoundaries: [
1070
+ 1,
1071
+ 4,
1072
+ 16,
1073
+ 64,
1074
+ 256,
1075
+ 1024,
1076
+ 4096,
1077
+ 16384,
1078
+ 65536,
1079
+ 262144,
1080
+ 1048576,
1081
+ 4194304,
1082
+ 16777216,
1083
+ 67108864
1084
+ ]
1085
+ }
1086
+ });
1087
+ this._telemetryRecorder = new TelemetryRecorder(
1088
+ this._genaiClientOperationDuration,
1089
+ this._genaiClientTokenUsage,
1090
+ this.logger
1091
+ );
1092
+ }
1093
+ /**
1094
+ * Patch known AI SDK functions in-place on the provided module exports object.
1095
+ * This approach is compatible with both CJS and ESM module loaders.
1096
+ */
1097
+ _patchModuleExports(moduleExports) {
1098
+ if (!moduleExports || typeof moduleExports !== "object") {
1099
+ return null;
1100
+ }
1101
+ let inPlacePatched = true;
1102
+ const wrapFunction = (name, isEmbedMany = false) => {
1103
+ const current = moduleExports[name];
1104
+ if (typeof current !== "function") {
1105
+ return;
1106
+ }
1107
+ const currentFn = current;
1108
+ if (currentFn[_VercelAIInstrumentation._WRAPPED_SYMBOL]) {
1109
+ return;
1110
+ }
1111
+ const descriptor = Object.getOwnPropertyDescriptor(moduleExports, name);
1112
+ if (descriptor && (!descriptor.writable || !descriptor.configurable) && !descriptor.set) {
1113
+ inPlacePatched = false;
1114
+ return;
1115
+ }
1116
+ const patcher = this._patchers.get(name);
1117
+ if (!patcher) {
1118
+ return;
1119
+ }
1120
+ const patched = isEmbedMany ? patcher.patch(currentFn, true) : patcher.patch(currentFn);
1121
+ try {
1122
+ Object.defineProperty(patched, _VercelAIInstrumentation._WRAPPED_SYMBOL, {
1123
+ value: true,
1124
+ enumerable: false,
1125
+ configurable: false
1126
+ });
1127
+ } catch {
1128
+ }
1129
+ try {
1130
+ moduleExports[name] = patched;
1131
+ } catch {
1132
+ inPlacePatched = false;
1133
+ }
1134
+ };
1135
+ wrapFunction("generateText");
1136
+ wrapFunction("streamText");
1137
+ wrapFunction("embed");
1138
+ wrapFunction("embedMany", true);
1139
+ if (!inPlacePatched) {
1140
+ const proxiedModule = new Proxy(moduleExports, {
1141
+ get: (target, prop, receiver) => {
1142
+ const originalValue = Reflect.get(target, prop, receiver);
1143
+ if (typeof originalValue === "function" && typeof prop === "string" && this._patchers.has(prop)) {
1144
+ const patcher = this._patchers.get(prop);
1145
+ const isEmbedMany = prop === "embedMany";
1146
+ const wrapped = isEmbedMany ? patcher.patch(originalValue, true) : patcher.patch(originalValue);
1147
+ return wrapped;
1148
+ }
1149
+ return originalValue;
1150
+ }
1151
+ });
1152
+ return proxiedModule;
1153
+ }
1154
+ return moduleExports;
1155
+ }
1156
+ /**
1157
+ * Manual instrumentation hook for bundlers/Next.js. Applies in-place wrapping
1158
+ * on the provided module namespace.
1159
+ */
1160
+ manuallyInstrument(module3) {
1161
+ try {
1162
+ const result = this._patchModuleExports(module3);
1163
+ if (result !== null) {
1164
+ logger.debug("Applied manual Vercel AI instrumentation");
1165
+ this._vercelAiNamespace = result;
1166
+ return result;
1167
+ }
1168
+ logger.warn("Manual Vercel AI instrumentation received invalid module");
1169
+ return module3;
1170
+ } catch (error) {
1171
+ logger.error(`Failed manual Vercel AI instrumentation: ${String(error)}`);
1172
+ return this._vercelAiNamespace || module3;
1173
+ }
1174
+ }
1175
+ /**
1176
+ * Wrap a created provider/client instance (factory return) when possible.
1177
+ * Call this from wrappers that construct provider clients (e.g., OpenAI SDK).
1178
+ */
1179
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1180
+ wrapFactoryReturn(instance) {
1181
+ return instance;
1182
+ }
1183
+ };
1184
+
1185
+ // src/internal/instrumentation/registry.ts
1186
+ var InstrumentationRegistry = class _InstrumentationRegistry {
1187
+ static instance;
1188
+ manualModules = null;
1189
+ static getInstance() {
1190
+ if (!_InstrumentationRegistry.instance) {
1191
+ _InstrumentationRegistry.instance = new _InstrumentationRegistry();
1192
+ }
1193
+ return _InstrumentationRegistry.instance;
1194
+ }
1195
+ /**
1196
+ * Set manual instrumentation modules for Next.js/Webpack environments
1197
+ */
1198
+ setManualModules(modules) {
1199
+ this.manualModules = modules;
1200
+ logger.info("Manual instrumentation modules configured for Next.js/Webpack compatibility");
1201
+ }
1202
+ /**
1203
+ * Helper to load instrumentation with optional manual module
1204
+ */
1205
+ loadInstrumentation(InstrumentationClass, name, manualModule, exceptionLogger) {
1206
+ try {
1207
+ const inst = new InstrumentationClass({
1208
+ exceptionLogger: exceptionLogger || ((error) => logger.error(`Exception in instrumentation: ${String(error)}`))
1209
+ });
1210
+ if (manualModule) {
1211
+ inst.manuallyInstrument(manualModule);
1212
+ logger.debug(`Manual instrumentation enabled for ${name}`);
1213
+ }
1214
+ return inst;
1215
+ } catch (error) {
1216
+ logger.error(`Failed to load ${name} instrumentation: ${String(error)}`);
1217
+ return null;
1218
+ }
1219
+ }
1220
+ /**
1221
+ * Get manual instrumentations only.
1222
+ * Auto-instrumentations are handled at import time.
1223
+ */
1224
+ getManualInstrumentations() {
1225
+ if (!this.manualModules || Object.keys(this.manualModules).length === 0) {
1226
+ logger.debug("No manual instrumentation modules configured");
1227
+ return [];
1228
+ }
1229
+ const instrumentations = [];
1230
+ const exceptionLogger = (error) => {
1231
+ logger.error(`Exception in manual instrumentation: ${String(error)}`);
1232
+ };
1233
+ this.loadManualInstrumentations(instrumentations, exceptionLogger);
1234
+ logger.info(`Loaded ${instrumentations.length} manual instrumentations`);
1235
+ return instrumentations;
1236
+ }
1237
+ /**
1238
+ * Load manual instrumentations only (with modules provided by user).
1239
+ * @private
1240
+ */
1241
+ loadManualInstrumentations(instrumentations, exceptionLogger) {
1242
+ const instrumentationConfigs = [
1243
+ { class: import_instrumentation_openai.OpenAIInstrumentation, name: "OpenAI", module: this.manualModules?.openAI },
1244
+ { class: import_instrumentation_anthropic.AnthropicInstrumentation, name: "Anthropic", module: this.manualModules?.anthropic },
1245
+ { class: import_instrumentation_cohere.CohereInstrumentation, name: "Cohere", module: this.manualModules?.cohere },
1246
+ {
1247
+ class: import_instrumentation_vertexai.VertexAIInstrumentation,
1248
+ name: "Vertex AI",
1249
+ module: this.manualModules?.google_vertexai
1250
+ },
1251
+ { class: import_instrumentation_bedrock.BedrockInstrumentation, name: "Bedrock", module: this.manualModules?.bedrock },
1252
+ { class: import_instrumentation_pinecone.PineconeInstrumentation, name: "Pinecone", module: this.manualModules?.pinecone },
1253
+ { class: import_instrumentation_langchain.LangChainInstrumentation, name: "LangChain", module: this.manualModules?.langchain },
1254
+ {
1255
+ class: import_instrumentation_llamaindex.LlamaIndexInstrumentation,
1256
+ name: "LlamaIndex",
1257
+ module: this.manualModules?.llamaindex
1258
+ },
1259
+ { class: import_instrumentation_chromadb.ChromaDBInstrumentation, name: "ChromaDB", module: this.manualModules?.chromadb },
1260
+ { class: import_instrumentation_qdrant.QdrantInstrumentation, name: "Qdrant", module: this.manualModules?.qdrant },
1261
+ { class: import_instrumentation_together.TogetherInstrumentation, name: "Together", module: this.manualModules?.together },
1262
+ { class: VercelAIInstrumentation, name: "Vercel AI", module: this.manualModules?.vercelAI }
1263
+ ];
1264
+ for (const config of instrumentationConfigs) {
1265
+ if (config.module) {
1266
+ const instrumentation = this.loadInstrumentation(
1267
+ config.class,
1268
+ config.name,
1269
+ config.module,
1270
+ exceptionLogger
1271
+ );
1272
+ if (instrumentation) {
1273
+ instrumentations.push(instrumentation);
1274
+ }
1275
+ }
1276
+ }
1277
+ }
1278
+ };
1279
+
1280
+ // src/internal/log/logging.ts
1281
+ var import_api_logs2 = require("@opentelemetry/api-logs");
1282
+ var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
1283
+ var import_resources = require("@opentelemetry/resources");
1284
+ var import_sdk_logs2 = require("@opentelemetry/sdk-logs");
1285
+
1286
+ // src/internal/log/processors/log-processor.ts
1287
+ var import_api9 = require("@opentelemetry/api");
1288
+ var import_sdk_logs = require("@opentelemetry/sdk-logs");
1289
+
1290
+ // src/internal/masking/patterns.ts
1291
+ var DEFAULT_PII_PATTERNS = [
1292
+ // Email addresses
1293
+ {
1294
+ name: "email_addresses",
1295
+ pattern: String.raw`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`
1296
+ },
1297
+ // Phone numbers (US format)
1298
+ {
1299
+ name: "us_phone_numbers",
1300
+ pattern: String.raw`(?:^|[\s])(?:\+?1[-.\s]*)?(?:\([0-9]{3}\)\s?[0-9]{3}[-.\s]?[0-9]{4}|[0-9]{3}[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}|[0-9]{10})(?=[\s]|$)`
1301
+ },
1302
+ // Social Security Numbers
1303
+ {
1304
+ name: "ssn",
1305
+ pattern: String.raw`\b(?!000|666|9\d{2})\d{3}[-\s]?(?!00)\d{2}[-\s]?(?!0000)\d{4}\b`
1306
+ },
1307
+ // Credit card numbers
1308
+ {
1309
+ name: "credit_cards",
1310
+ pattern: String.raw`\b(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\\d{3})\\d{11})\b`
1311
+ },
1312
+ {
1313
+ name: "credit_cards_with_separators",
1314
+ pattern: String.raw`\b(?:4\\d{3}|5[1-5]\\d{2}|3[47]\\d{2})[-\s]?\\d{4}[-\s]?\\d{4}[-\s]?\\d{4}\b`
1315
+ },
1316
+ // IP addresses (IPv4)
1317
+ {
1318
+ name: "ipv4_addresses",
1319
+ pattern: String.raw`\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?!\.[0-9])\b`
1320
+ },
1321
+ // API keys/tokens
1322
+ {
1323
+ name: "generic_api_keys",
1324
+ pattern: String.raw`\b(?:[Aa][Pp][Ii][_-]?[Kk][Ee][Yy]|[Tt][Oo][Kk][Ee][Nn]|[Ss][Ee][Cc][Rr][Ee][Tt])[_-]?[=:]?\s*["']?(?:[a-zA-Z0-9\-_.]{20,})["']?\b`
1325
+ },
1326
+ {
1327
+ name: "openai_keys",
1328
+ pattern: String.raw`\bsk[-_][a-zA-Z0-9]{20,}\b`
1329
+ },
1330
+ {
1331
+ name: "base64_secrets",
1332
+ pattern: String.raw`\b[A-Za-z0-9+/]{64,}={0,2}\b`
1333
+ },
1334
+ // AWS Keys
1335
+ {
1336
+ name: "aws_access_keys",
1337
+ pattern: String.raw`\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b`
1338
+ },
1339
+ {
1340
+ name: "aws_secret_keys",
1341
+ pattern: String.raw`\b[A-Za-z0-9/+=]*[A-Z][A-Za-z0-9/+=]*[a-z][A-Za-z0-9/+=]*[/+=][A-Za-z0-9/+=]{30,}\b`
1342
+ },
1343
+ // GitHub tokens
1344
+ {
1345
+ name: "github_tokens",
1346
+ pattern: String.raw`\bghp_[a-zA-Z0-9]{36}\b`
1347
+ },
1348
+ // Slack tokens
1349
+ {
1350
+ name: "slack_tokens",
1351
+ pattern: String.raw`\bxox[baprs]-[0-9]{10,13}-[0-9]{10,13}-[a-zA-Z0-9]{24,34}\b`
1352
+ },
1353
+ // Stripe keys
1354
+ {
1355
+ name: "stripe_keys",
1356
+ pattern: String.raw`\b(?:sk|pk)_(?:test|live)_[a-zA-Z0-9]{24,}\b`
1357
+ },
1358
+ // JWT tokens
1359
+ {
1360
+ name: "jwt_tokens",
1361
+ pattern: String.raw`\beyJ[A-Za-z0-9_-]{2,}\\.[A-Za-z0-9_-]{2,}\\.[A-Za-z0-9_-]{2,}\b`
1362
+ },
1363
+ // MAC addresses
1364
+ {
1365
+ name: "mac_addresses",
1366
+ pattern: String.raw`\b(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}\b`
1367
+ },
1368
+ // IPv6 addresses
1369
+ {
1370
+ name: "ipv6_addresses",
1371
+ pattern: String.raw`\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b`
1372
+ },
1373
+ // Medical records
1374
+ {
1375
+ name: "medical_record_numbers",
1376
+ pattern: String.raw`\b(?:[Mm][Rr][Nn])[-\s]?\d{6,10}\b`
1377
+ },
1378
+ // Bitcoin addresses
1379
+ {
1380
+ name: "bitcoin_addresses",
1381
+ pattern: String.raw`\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b`
1382
+ },
1383
+ // Ethereum addresses
1384
+ {
1385
+ name: "ethereum_addresses",
1386
+ pattern: String.raw`\b0x[a-fA-F0-9]{40}(?![a-fA-F0-9])\b`
1387
+ },
1388
+ // UUIDs
1389
+ {
1390
+ name: "uuids",
1391
+ pattern: String.raw`\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(?![0-9a-fA-F-])\b`
1392
+ },
1393
+ // Database connection strings
1394
+ {
1395
+ name: "database_connections",
1396
+ pattern: String.raw`\b(?:[Mm][Oo][Nn][Gg][Oo][Dd][Bb]|[Pp][Oo][Ss][Tt][Gg][Rr][Ee][Ss]|[Mm][Yy][Ss][Qq][Ll]|[Rr][Ee][Dd][Ii][Ss]|[Mm][Ss][Ss][Qq][Ll]|[Oo][Rr][Aa][Cc][Ll][Ee]):\\/\\/[^\\s]+\b`
1397
+ },
1398
+ // Private keys
1399
+ {
1400
+ name: "rsa_private_keys",
1401
+ pattern: "-----BEGIN (?:RSA )?PRIVATE KEY-----"
1402
+ },
1403
+ {
1404
+ name: "pgp_private_keys",
1405
+ pattern: "-----BEGIN PGP PRIVATE KEY BLOCK-----"
1406
+ },
1407
+ {
1408
+ name: "certificates",
1409
+ pattern: "-----BEGIN CERTIFICATE-----"
1410
+ },
1411
+ // Date of birth patterns
1412
+ {
1413
+ name: "date_of_birth_us",
1414
+ pattern: String.raw`\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])[-/](?:19|20)\\d{2}\b`
1415
+ },
1416
+ {
1417
+ name: "date_of_birth_iso",
1418
+ pattern: String.raw`\b(?:19|20)\\d{2}[-/](?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])\b`
1419
+ },
1420
+ // US Identification Numbers
1421
+ {
1422
+ name: "us_passport_numbers",
1423
+ pattern: String.raw`\b[A-Z]?\\d{6,9}\b`
1424
+ },
1425
+ {
1426
+ name: "drivers_license",
1427
+ pattern: String.raw`\b[A-Z]{1,2}\\d{3,8}[-\s]?\\d{2,5}[-\s]?\\d{2,5}[-\s]?\\d{1,5}[-\s]?\\d?\b`
1428
+ },
1429
+ {
1430
+ name: "bank_account_numbers",
1431
+ pattern: String.raw`\b\\d{10,17}\b`
1432
+ },
1433
+ {
1434
+ name: "aba_routing_numbers",
1435
+ pattern: String.raw`\b((0[0-9])|(1[0-2])|(2[1-9])|(3[0-2])|(6[1-9])|(7[0-2])|80)([0-9]{7})\b`
1436
+ },
1437
+ {
1438
+ name: "health_insurance_numbers",
1439
+ pattern: String.raw`\b\\d{10}[A-Z]\b`
1440
+ },
1441
+ {
1442
+ name: "employee_ids",
1443
+ pattern: String.raw`\b(?:[Ee][Mm][Pp]|[Ee][Mm][Pp][Ll][Oo][Yy][Ee][Ee]|[Ee])[-\s]?\\d{5,8}\b`
1444
+ },
1445
+ {
1446
+ name: "tax_ein",
1447
+ pattern: String.raw`\b\\d{2}-\\d{7}\b`
1448
+ },
1449
+ {
1450
+ name: "medicare_beneficiary_id",
1451
+ pattern: String.raw`\b[1-9][A-Z][A-Z0-9]\\d-[A-Z][A-Z0-9]\\d-[A-Z][A-Z0-9]\\d{2}\b`
1452
+ },
1453
+ {
1454
+ name: "national_provider_id",
1455
+ pattern: String.raw`\b1\\d{9}\b`
1456
+ },
1457
+ {
1458
+ name: "dea_numbers",
1459
+ pattern: String.raw`\b[A-Z]{2}\\d{7}\b`
1460
+ },
1461
+ {
1462
+ name: "itin",
1463
+ pattern: String.raw`\b9\\d{2}(?:[ \\-]?)[7,8]\\d(?:[ \\-]?)\\d{4}\b`
1464
+ },
1465
+ // Vehicle and Location
1466
+ {
1467
+ name: "vin_numbers",
1468
+ pattern: String.raw`\b[A-HJ-NPR-Z0-9]{17}\b`
1469
+ },
1470
+ {
1471
+ name: "coordinates",
1472
+ pattern: String.raw`\b[-+]?(?:[0-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?),\\s*[-+]?(?:1[0-7]\\d(?:\\.\\d+)?|180(?:\\.0+)?|[0-9]?\\d(?:\\.\\d+)?)\b`
1473
+ },
1474
+ {
1475
+ name: "us_license_plates",
1476
+ pattern: String.raw`\b[A-Z]{1,3}[-\s]\\d{1,4}[A-Z]?\b|\b\\d{1,2}[A-Z]{1,3}\\d{1,4}\b`
1477
+ },
1478
+ {
1479
+ name: "us_zip_codes",
1480
+ pattern: String.raw`\b(\\d{5}-\\d{4}|\\d{5})\b`
1481
+ },
1482
+ {
1483
+ name: "us_street_addresses",
1484
+ pattern: String.raw`\b\\d{1,8}\b[\\s\\S]{10,100}?\b(AK|AL|AR|AZ|CA|CO|CT|DC|DE|FL|GA|HI|IA|ID|IL|IN|KS|KY|LA|MA|MD|ME|MI|MN|MO|MS|MT|NC|ND|NE|NH|NJ|NM|NV|NY|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VA|VT|WA|WI|WV|WY)\b\\s\\d{5}\b`
1485
+ },
1486
+ // International Banking
1487
+ {
1488
+ name: "iban",
1489
+ pattern: String.raw`\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}([A-Z0-9]?){0,16}\b`
1490
+ },
1491
+ {
1492
+ name: "swift_bic",
1493
+ pattern: String.raw`\b[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?\b`
1494
+ },
1495
+ // Additional API Keys and Tokens
1496
+ {
1497
+ name: "google_oauth",
1498
+ pattern: String.raw`\bya29\\.[a-zA-Z0-9_-]{60,}\b`
1499
+ },
1500
+ {
1501
+ name: "firebase_tokens",
1502
+ pattern: String.raw`\bAAAA[A-Za-z0-9_-]{100,}\b`
1503
+ },
1504
+ {
1505
+ name: "google_app_ids",
1506
+ pattern: String.raw`\b[0-9]+-\w+\.apps\.googleusercontent\.com\b`
1507
+ },
1508
+ {
1509
+ name: "facebook_secrets",
1510
+ pattern: String.raw`\b(facebook_secret|FACEBOOK_SECRET|facebook_app_secret|FACEBOOK_APP_SECRET)[a-z_ =\\s"'\\:]{0,5}[^a-zA-Z0-9][a-f0-9]{32}[^a-zA-Z0-9]`
1511
+ },
1512
+ {
1513
+ name: "github_keys",
1514
+ pattern: String.raw`\b(GITHUB_SECRET|GITHUB_KEY|github_secret|github_key|github_token|GITHUB_TOKEN|github_api_key|GITHUB_API_KEY)[a-z_ =\\s\"'\\:]{0,10}[^a-zA-Z0-9][a-zA-Z0-9]{40}[^a-zA-Z0-9]`
1515
+ },
1516
+ {
1517
+ name: "heroku_keys",
1518
+ pattern: String.raw`\b(heroku_api_key|HEROKU_API_KEY|heroku_secret|HEROKU_SECRET)[a-z_ =\\s\"'\\:]{0,10}[^a-zA-Z0-9-]\\w{8}(?:-\\w{4}){3}-\\w{12}[^a-zA-Z0-9\\-]`
1519
+ },
1520
+ {
1521
+ name: "slack_api_keys",
1522
+ pattern: String.raw`\b(slack_api_key|SLACK_API_KEY|slack_key|SLACK_KEY)[a-z_ =\\s\"'\\:]{0,10}[^a-f0-9][a-f0-9]{32}[^a-f0-9]`
1523
+ },
1524
+ {
1525
+ name: "slack_api_tokens",
1526
+ pattern: String.raw`\b(xox[pb](?:-[a-zA-Z0-9]+){4,})\b`
1527
+ },
1528
+ // Extended Private Keys and Certificates
1529
+ {
1530
+ name: "dsa_private_keys",
1531
+ pattern: String.raw`-----BEGIN DSA PRIVATE KEY-----(?:[a-zA-Z0-9\+\=\/"']|\s)+?-----END DSA PRIVATE KEY-----`
1532
+ },
1533
+ {
1534
+ name: "ec_private_keys",
1535
+ pattern: String.raw`-----BEGIN (?:EC|ECDSA) PRIVATE KEY-----(?:[a-zA-Z0-9\+\=\/"']|\s)+?-----END (?:EC|ECDSA) PRIVATE KEY-----`
1536
+ },
1537
+ {
1538
+ name: "encrypted_private_keys",
1539
+ pattern: String.raw`-----BEGIN ENCRYPTED PRIVATE KEY-----(?:.|\s)+?-----END ENCRYPTED PRIVATE KEY-----`
1540
+ },
1541
+ {
1542
+ name: "ssl_certificates",
1543
+ pattern: String.raw`-----BEGIN CERTIFICATE-----(?:.|\n)+?\s-----END CERTIFICATE-----`
1544
+ },
1545
+ {
1546
+ name: "ssh_dss_public",
1547
+ pattern: String.raw`\bssh-dss [0-9A-Za-z+/]+[=]{2}\b`
1548
+ },
1549
+ {
1550
+ name: "ssh_rsa_public",
1551
+ pattern: String.raw`\bssh-rsa AAAA[0-9A-Za-z+/]+[=]{0,3} [^@]+@[^@]+\b`
1552
+ },
1553
+ {
1554
+ name: "putty_ssh_keys",
1555
+ pattern: String.raw`PuTTY-User-Key-File-2: ssh-(?:rsa|dss)\s*Encryption: none(?:.|\s?)*?Private-MAC:`
1556
+ },
1557
+ // International Phone Numbers
1558
+ {
1559
+ name: "france_phone_numbers",
1560
+ pattern: String.raw`\b([0O]?[1lI][1lI])?[3E][3E][0O]?[\\dOIlZEASB]{9}\b`
1561
+ },
1562
+ {
1563
+ name: "german_phone_numbers",
1564
+ pattern: String.raw`\b[\d\w]\d{2}[\d\w]{6}\d[\d\w]\b`
1565
+ },
1566
+ {
1567
+ name: "uk_phone_numbers",
1568
+ pattern: String.raw`\b([0O]?[1lI][1lI])?[4A][4A][\\dOIlZEASB]{10,11}\b`
1569
+ },
1570
+ // International IDs
1571
+ {
1572
+ name: "uk_drivers_license",
1573
+ pattern: String.raw`\b[A-Z]{5}\d{6}[A-Z]{2}\d{1}[A-Z]{2}\b`
1574
+ },
1575
+ {
1576
+ name: "uk_passport",
1577
+ pattern: String.raw`\b\\d{10}GB[RP]\\d{7}[UMF]{1}\\d{9}\b`
1578
+ },
1579
+ {
1580
+ name: "argentina_dni",
1581
+ pattern: String.raw`\b\\d{2}\\.\\d{3}\\.\\d{3}\b`
1582
+ },
1583
+ {
1584
+ name: "australia_tfn",
1585
+ pattern: String.raw`\b[Tt][Ff][Nn](:|:\\s|\\s|)(\\d{8,9})\b`
1586
+ },
1587
+ {
1588
+ name: "canada_passport",
1589
+ pattern: String.raw`\b[\\w]{2}[\\d]{6}\b`
1590
+ },
1591
+ {
1592
+ name: "croatia_vat",
1593
+ pattern: String.raw`\bHR\\d{11}\b`
1594
+ },
1595
+ {
1596
+ name: "czech_vat",
1597
+ pattern: String.raw`\bCZ\\d{8,10}\b`
1598
+ },
1599
+ {
1600
+ name: "denmark_personal_id",
1601
+ pattern: String.raw`\b(?:\\d{10}|\\d{6}[-\\s]\\d{4})\b`
1602
+ },
1603
+ {
1604
+ name: "france_national_id",
1605
+ pattern: String.raw`\b\\d{12}\b`
1606
+ },
1607
+ {
1608
+ name: "france_ssn",
1609
+ pattern: String.raw`\b(?:\\d{13}|\\d{13}\\s\\d{2})\b`
1610
+ },
1611
+ {
1612
+ name: "france_passport",
1613
+ pattern: String.raw`\b\\d{2}11\\d{5}\b`
1614
+ },
1615
+ {
1616
+ name: "california_drivers_license",
1617
+ pattern: String.raw`\b[A-Z]{1}\\d{7}\b`
1618
+ },
1619
+ // Medical and Healthcare
1620
+ {
1621
+ name: "hipaa_ndc",
1622
+ pattern: String.raw`\b\\d{4,5}-\\d{3,4}-\\d{1,2}\b`
1623
+ },
1624
+ // Security and Network
1625
+ {
1626
+ name: "cve_numbers",
1627
+ pattern: String.raw`\b[Cc][Vv][Ee]-\\d{4}-\\d{4,7}\b`
1628
+ },
1629
+ {
1630
+ name: "microsoft_oauth",
1631
+ pattern: String.raw`https://login\.microsoftonline\.com/common/oauth2/v2\.0/token|https://login\.windows\.net/common/oauth2/token`
1632
+ },
1633
+ {
1634
+ name: "postgres_connections",
1635
+ pattern: String.raw`\b(?:[Pp][Oo][Ss][Tt][Gg][Rr][Ee][Ss]|[Pp][Gg][Ss][Qq][Ll])\\:\\/\\/`
1636
+ },
1637
+ {
1638
+ name: "box_links",
1639
+ pattern: String.raw`https://app\.box\.com/[s|l]/\S+`
1640
+ },
1641
+ {
1642
+ name: "dropbox_links",
1643
+ pattern: String.raw`https://www\.dropbox\.com/(?:s|l)/\S+`
1644
+ },
1645
+ // Credit Card Variants
1646
+ {
1647
+ name: "amex_cards",
1648
+ pattern: String.raw`\b3[47][0-9]{13}\b`
1649
+ },
1650
+ {
1651
+ name: "visa_cards",
1652
+ pattern: String.raw`\b4[0-9]{12}(?:[0-9]{3})?\b`
1653
+ },
1654
+ {
1655
+ name: "discover_cards",
1656
+ pattern: String.raw`\b65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}\b`
1657
+ },
1658
+ {
1659
+ name: "enhanced_credit_cards",
1660
+ pattern: String.raw`\b((4\\d{3}|5[1-5]\\d{2}|2\\d{3}|3[47]\\d{1,2})[\\s\\-]?\\d{4,6}[\\s\\-]?\\d{4,6}?([\\s\\-]\\d{3,4})?(\\d{3})?)\b`
1661
+ },
1662
+ // Bank Routing Numbers (US specific)
1663
+ {
1664
+ name: "bbva_routing_ca",
1665
+ pattern: String.raw`\\b321170538\\b`
1666
+ },
1667
+ {
1668
+ name: "boa_routing_ca",
1669
+ pattern: String.raw`\\b(?:121|026)00(?:0|9)(?:358|593)\\b`
1670
+ },
1671
+ {
1672
+ name: "chase_routing_ca",
1673
+ pattern: String.raw`\\b322271627\\b`
1674
+ },
1675
+ {
1676
+ name: "citibank_routing_ca",
1677
+ pattern: String.raw`\\b32(?:11|22)71(?:18|72)4\\b`
1678
+ },
1679
+ {
1680
+ name: "usbank_routing_ca",
1681
+ pattern: String.raw`\\b12(?:1122676|2235821)\\b`
1682
+ },
1683
+ {
1684
+ name: "united_bank_routing_ca",
1685
+ pattern: String.raw`\\b122243350\\b`
1686
+ },
1687
+ {
1688
+ name: "wells_fargo_routing_ca",
1689
+ pattern: String.raw`\\b121042882\\b`
1690
+ },
1691
+ // Unrealistic alphanumeric identifiers
1692
+ {
1693
+ name: "generic_non_usual",
1694
+ pattern: String.raw`(?:^|\s)(?=[A-Za-z0-9_\)\*\=@]*[A-Za-z])(?=[A-Za-z0-9_\)\*\=@]*[0-9])([A-Za-z0-9_\)\*\=@]{5,})(?=\s|$)`
1695
+ }
1696
+ ];
1697
+
1698
+ // src/internal/masking/utils.ts
1699
+ function isValidPatternName(name) {
1700
+ return /^[a-zA-Z0-9_]+$/.test(name);
1701
+ }
1702
+ function isLikelyReDoSPattern(pattern) {
1703
+ const dangerousPatterns = [
1704
+ // Nested quantifiers like (a+)+, (a*)+, (a+)*
1705
+ /\([^)]*[+*]\)[+*]/,
1706
+ // Alternation with overlapping groups like (a|a)*
1707
+ /\([^)]*\|[^)]*\)[+*]/,
1708
+ // Complex backtracking patterns - but more specific
1709
+ /\([^)]*[+*][^)]*[+*][^)]*\)[+*]/
1710
+ ];
1711
+ return dangerousPatterns.some((dangerous) => dangerous.test(pattern));
1712
+ }
1713
+ function getGroupedPattern(patternEntry) {
1714
+ let name = patternEntry.name;
1715
+ if (!name || name === "") {
1716
+ name = `pattern_${Math.random().toString(16).slice(2)}`;
1717
+ }
1718
+ if (!isValidPatternName(name)) {
1719
+ throw new Error(
1720
+ `Pattern name '${name}' must only contain alphanumeric characters and underscores`
1721
+ );
1722
+ }
1723
+ if (isLikelyReDoSPattern(patternEntry.pattern)) {
1724
+ throw new Error(`Potentially dangerous ReDoS pattern detected: '${patternEntry.pattern}'`);
1725
+ }
1726
+ try {
1727
+ new RegExp(patternEntry.pattern);
1728
+ } catch (error) {
1729
+ throw new Error(`Invalid regex pattern '${patternEntry.pattern}': ${String(error)}`);
1730
+ }
1731
+ return `(?<${name}>${patternEntry.pattern})`;
1732
+ }
1733
+ function isIPatternEntry(obj) {
1734
+ return typeof obj === "object" && obj !== null && typeof obj.pattern === "string" && (obj.name === void 0 || typeof obj.name === "string");
1735
+ }
1736
+ function isIEventMaskingRule(obj) {
1737
+ return typeof obj === "object" && obj !== null && typeof obj.mode === "string" && Array.isArray(obj.patterns) && obj.patterns.every(
1738
+ (p) => isIPatternEntry(p) || typeof p === "string"
1739
+ ) && (obj.attributePattern === void 0 || typeof obj.attributePattern === "string");
1740
+ }
1741
+ function convertPatternsToPatternEntries(patterns) {
1742
+ const patternEntries = [];
1743
+ for (const pattern of patterns) {
1744
+ if (typeof pattern === "string") {
1745
+ patternEntries.push({ pattern, name: "" });
1746
+ } else if (isIPatternEntry(pattern)) {
1747
+ patternEntries.push(pattern);
1748
+ } else {
1749
+ throw new Error("Patterns must be either strings or PatternEntry instances");
1750
+ }
1751
+ }
1752
+ return patternEntries;
1753
+ }
1754
+ function compilePatternEntries(patternEntries) {
1755
+ const patternGroups = [];
1756
+ for (const patternEntry of patternEntries) {
1757
+ try {
1758
+ patternGroups.push(getGroupedPattern(patternEntry));
1759
+ } catch (error) {
1760
+ logger.warn(`Invalid pattern '${patternEntry.name}': ${patternEntry.pattern}`, error);
1761
+ continue;
1762
+ }
1763
+ }
1764
+ if (patternGroups.length === 0) {
1765
+ return null;
1766
+ }
1767
+ try {
1768
+ return new RegExp(patternGroups.join("|"));
1769
+ } catch (error) {
1770
+ logger.warn("Failed to compile pattern entries into regex", error);
1771
+ return null;
1772
+ }
1773
+ }
1774
+ function getCompiledAttributeNamePattern(rule) {
1775
+ if (!rule.attributePattern) {
1776
+ logger.debug("No attribute pattern provided, using default .*");
1777
+ return /.*/;
1778
+ }
1779
+ let compiledPatternString = rule.attributePattern;
1780
+ if (isIEventMaskingRule(rule) && rule.eventNamePattern) {
1781
+ compiledPatternString = `(${compiledPatternString})|(${rule.eventNamePattern})`;
1782
+ }
1783
+ return new RegExp(compiledPatternString);
1784
+ }
1785
+ function shouldContinueExecution(startTime, iterations, timeoutMs) {
1786
+ if (Date.now() - startTime > timeoutMs) {
1787
+ logger.warn("Regex execution timed out - potential ReDoS pattern detected");
1788
+ return false;
1789
+ }
1790
+ const maxIterations = 1e3;
1791
+ if (iterations > maxIterations) {
1792
+ logger.warn("Regex execution exceeded maximum iterations - potential ReDoS pattern detected");
1793
+ return false;
1794
+ }
1795
+ return true;
1796
+ }
1797
+ function createGlobalPattern(pattern) {
1798
+ return new RegExp(
1799
+ pattern.source,
1800
+ pattern.flags.includes("g") ? pattern.flags : pattern.flags + "g"
1801
+ );
1802
+ }
1803
+ function executeRegexWithTimeout(pattern, value, timeoutMs = 100) {
1804
+ const matches = [];
1805
+ const globalPattern = createGlobalPattern(pattern);
1806
+ const startTime = Date.now();
1807
+ let match;
1808
+ let iterations = 0;
1809
+ while ((match = globalPattern.exec(value)) !== null) {
1810
+ if (!shouldContinueExecution(startTime, ++iterations, timeoutMs)) {
1811
+ break;
1812
+ }
1813
+ matches.push(match);
1814
+ if (match[0].length === 0) {
1815
+ globalPattern.lastIndex = match.index + 1;
1816
+ }
1817
+ }
1818
+ return matches;
1819
+ }
1820
+ function maskStringByPattern(value, pattern, mode = "full") {
1821
+ const matches = [];
1822
+ try {
1823
+ const regexMatches = executeRegexWithTimeout(pattern, value);
1824
+ for (const match of regexMatches) {
1825
+ matches.push({
1826
+ start: match.index,
1827
+ end: match.index + match[0].length,
1828
+ text: match[0],
1829
+ groups: match.groups
1830
+ });
1831
+ }
1832
+ } catch (error) {
1833
+ logger.warn("Regex execution failed, skipping masking", error);
1834
+ return value;
1835
+ }
1836
+ for (const matchInfo of matches.reverse()) {
1837
+ let patternName = "unknown";
1838
+ if (matchInfo.groups) {
1839
+ for (const [groupName, groupValue] of Object.entries(matchInfo.groups)) {
1840
+ if (groupValue !== void 0) {
1841
+ if (groupName.includes("_") && /\d$/.test(groupName)) {
1842
+ const parts = groupName.split("_");
1843
+ patternName = parts[0] || groupName;
1844
+ } else {
1845
+ patternName = groupName;
1846
+ }
1847
+ break;
1848
+ }
1849
+ }
1850
+ }
1851
+ logger.info(`Masking detected: pattern '${patternName}' found match in value`);
1852
+ const masked = mode === "partial" ? matchInfo.text[0] + "*****" : "*****";
1853
+ value = value.slice(0, matchInfo.start) + masked + value.slice(matchInfo.end);
1854
+ }
1855
+ return value;
1856
+ }
1857
+ function maskStringByPatternBasedRule(value, rule) {
1858
+ const patternEntries = convertPatternsToPatternEntries(rule.patterns);
1859
+ if (patternEntries.length === 0) {
1860
+ logger.warn("No patterns provided for masking rule, returning original value");
1861
+ return value;
1862
+ }
1863
+ const mode = rule.mode;
1864
+ if (!patternEntries || patternEntries.length === 0) {
1865
+ return mode === "partial" && value ? value[0] + "*****" : "*****";
1866
+ }
1867
+ const compiledPatterns = compilePatternEntries(patternEntries);
1868
+ if (!compiledPatterns) {
1869
+ return value;
1870
+ }
1871
+ return maskStringByPattern(value, compiledPatterns, mode);
1872
+ }
1873
+ function maskValue(value, rule) {
1874
+ if (typeof value === "string") {
1875
+ return maskStringByPatternBasedRule(value, rule);
1876
+ } else if (typeof value === "boolean" || typeof value === "number") {
1877
+ return maskStringByPatternBasedRule(String(value), rule);
1878
+ } else if (Array.isArray(value)) {
1879
+ return value.map((v) => maskStringByPatternBasedRule(String(v), rule));
1880
+ } else if (value !== null && typeof value === "object") {
1881
+ const result = {};
1882
+ for (const [k, v] of Object.entries(value)) {
1883
+ result[k] = maskValue(v, rule);
1884
+ }
1885
+ return result;
1886
+ } else {
1887
+ throw new Error(`Unsupported value type for masking: ${typeof value}`);
1888
+ }
1889
+ }
1890
+ function maskAttributes(attributes, rules, outputOriginalValue = false) {
1891
+ if (!attributes || Object.keys(attributes).length === 0) {
1892
+ return {};
1893
+ }
1894
+ const maskedAttributes = { ...attributes };
1895
+ for (const rule of rules) {
1896
+ const compiledAttributeNamePattern = getCompiledAttributeNamePattern(rule);
1897
+ const attributesToMask = compiledAttributeNamePattern ? Object.keys(maskedAttributes).filter((attr) => compiledAttributeNamePattern.test(attr)) : Object.keys(maskedAttributes);
1898
+ for (const attribute of attributesToMask) {
1899
+ const value = maskedAttributes[attribute];
1900
+ if (value === null || value === void 0) {
1901
+ continue;
1902
+ }
1903
+ if (outputOriginalValue) {
1904
+ logger.debug(`Masking attribute '${attribute}' with original value`, { value });
1905
+ }
1906
+ maskedAttributes[attribute] = maskValue(value, rule);
1907
+ }
1908
+ }
1909
+ return maskedAttributes;
1910
+ }
1911
+
1912
+ // src/internal/semantic-conventions.ts
1913
+ var import_api8 = require("@opentelemetry/api");
1914
+ var BRIZZ = "brizz";
1915
+ var PROPERTIES = "properties";
1916
+ var PROPERTIES_CONTEXT_KEY = (0, import_api8.createContextKey)(PROPERTIES);
1917
+
1918
+ // src/internal/log/processors/log-processor.ts
1919
+ var DEFAULT_LOG_MASKING_RULES = [
1920
+ {
1921
+ mode: "partial",
1922
+ attributePattern: "event.name",
1923
+ patterns: DEFAULT_PII_PATTERNS
1924
+ }
1925
+ ];
1926
+ var BrizzSimpleLogRecordProcessor = class extends import_sdk_logs.SimpleLogRecordProcessor {
1927
+ config;
1928
+ constructor(exporter, config) {
1929
+ super(exporter);
1930
+ this.config = config;
1931
+ }
1932
+ onEmit(logRecord) {
1933
+ const maskingConfig = this.config.masking?.eventMasking;
1934
+ if (maskingConfig) {
1935
+ maskLog(logRecord, maskingConfig);
1936
+ }
1937
+ const associationProperties = import_api9.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1938
+ if (associationProperties) {
1939
+ for (const [key, value] of Object.entries(associationProperties)) {
1940
+ logRecord.setAttribute(`${BRIZZ}.${key}`, value);
1941
+ }
1942
+ }
1943
+ super.onEmit(logRecord);
1944
+ }
1945
+ };
1946
+ var BrizzBatchLogRecordProcessor = class extends import_sdk_logs.BatchLogRecordProcessor {
1947
+ config;
1948
+ constructor(exporter, config) {
1949
+ super(exporter);
1950
+ this.config = config;
1951
+ }
1952
+ onEmit(logRecord) {
1953
+ const maskingConfig = this.config.masking?.eventMasking;
1954
+ if (maskingConfig) {
1955
+ maskLog(logRecord, maskingConfig);
1956
+ }
1957
+ const associationProperties = import_api9.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1958
+ if (associationProperties) {
1959
+ for (const [key, value] of Object.entries(associationProperties)) {
1960
+ logRecord.setAttribute(`${BRIZZ}.${key}`, value);
1961
+ }
1962
+ }
1963
+ super.onEmit(logRecord);
1964
+ }
1965
+ };
1966
+ function maskLog(logRecord, config) {
1967
+ if (!logRecord.attributes) {
1968
+ return logRecord;
1969
+ }
1970
+ let rules = config.rules || [];
1971
+ if (!config.disableDefaultRules) {
1972
+ rules = [...DEFAULT_LOG_MASKING_RULES, ...rules];
1973
+ }
1974
+ try {
1975
+ if (logRecord.attributes && Object.keys(logRecord.attributes).length > 0) {
1976
+ const attributesRecord = {};
1977
+ for (const [key, value] of Object.entries(logRecord.attributes)) {
1978
+ attributesRecord[key] = value;
1979
+ }
1980
+ const maskedAttributes = maskAttributes(attributesRecord, rules);
1981
+ if (maskedAttributes) {
1982
+ const newAttributes = {};
1983
+ for (const [key, value] of Object.entries(maskedAttributes)) {
1984
+ newAttributes[key] = value;
1985
+ }
1986
+ logRecord.setAttributes(newAttributes);
1987
+ }
1988
+ }
1989
+ if (config.maskBody && logRecord.body !== void 0 && logRecord.body !== null) {
1990
+ let maskedBody = logRecord.body;
1991
+ for (const rule of rules) {
1992
+ maskedBody = maskValue(maskedBody, rule);
1993
+ }
1994
+ logRecord.setBody(maskedBody);
1995
+ }
1996
+ return logRecord;
1997
+ } catch (error) {
1998
+ logger.error("Error masking log record:", error);
1999
+ return logRecord;
2000
+ }
2001
+ }
2002
+
2003
+ // src/internal/log/logging.ts
2004
+ var LoggingModule = class _LoggingModule {
2005
+ static instance = null;
2006
+ logExporter = null;
2007
+ logProcessor = null;
2008
+ loggerProvider = null;
2009
+ static getInstance() {
2010
+ if (!_LoggingModule.instance) {
2011
+ throw new Error("Brizz must be initialized before accessing LoggingModule");
2012
+ }
2013
+ return _LoggingModule.instance;
2014
+ }
2015
+ /**
2016
+ * Initialize the logging module with the provided configuration
2017
+ */
2018
+ setup(config) {
2019
+ logger.info("Setting up logging module");
2020
+ this.initLogExporter(config);
2021
+ this.initLogProcessor(config);
2022
+ this.initLoggerProvider(config);
2023
+ _LoggingModule.instance = this;
2024
+ logger.info("Logging module setup completed");
2025
+ }
2026
+ /**
2027
+ * Initialize the log exporter
2028
+ */
2029
+ initLogExporter(config) {
2030
+ if (this.logExporter) {
2031
+ logger.debug("Log exporter already initialized, skipping re-initialization");
2032
+ return;
2033
+ }
2034
+ if (config.customLogExporter) {
2035
+ logger.debug("Using custom log exporter");
2036
+ this.logExporter = config.customLogExporter;
2037
+ logger.debug("Custom log exporter initialized successfully");
2038
+ return;
2039
+ }
2040
+ const logsUrl = config.baseUrl.replace(/\/$/, "") + "/v1/logs";
2041
+ logger.debug("Initializing default OTLP log exporter", { url: logsUrl });
2042
+ const headers = { ...config.headers };
2043
+ this.logExporter = new import_exporter_logs_otlp_http.OTLPLogExporter({
2044
+ url: logsUrl,
2045
+ headers
2046
+ });
2047
+ logger.debug("OTLP log exporter initialized successfully");
2048
+ }
2049
+ /**
2050
+ * Initialize the log processor with masking support
2051
+ */
2052
+ initLogProcessor(config) {
2053
+ if (this.logProcessor) {
2054
+ logger.debug("Log processor already initialized, skipping re-initialization");
2055
+ return;
2056
+ }
2057
+ if (!this.logExporter) {
2058
+ throw new Error("Log exporter must be initialized before processor");
2059
+ }
2060
+ logger.debug("Initializing log processor", {
2061
+ disableBatch: config.disableBatch,
2062
+ hasMasking: !!config.masking?.eventMasking
2063
+ });
2064
+ this.logProcessor = config.disableBatch ? new BrizzSimpleLogRecordProcessor(this.logExporter, config) : new BrizzBatchLogRecordProcessor(this.logExporter, config);
2065
+ logger.debug("Log processor initialized successfully");
2066
+ }
2067
+ /**
2068
+ * Initialize the logger provider
2069
+ */
2070
+ initLoggerProvider(config) {
2071
+ if (this.loggerProvider) {
2072
+ logger.debug("Logger provider already initialized, skipping re-initialization");
2073
+ return;
2074
+ }
2075
+ if (!this.logProcessor) {
2076
+ throw new Error("Log processor must be initialized before logger provider");
2077
+ }
2078
+ logger.debug("Creating resource with service name", {
2079
+ serviceName: config.appName
2080
+ });
2081
+ const resource = (0, import_resources.resourceFromAttributes)({
2082
+ "service.name": config.appName
2083
+ });
2084
+ logger.debug("Creating logger provider with resource");
2085
+ this.loggerProvider = new import_sdk_logs2.LoggerProvider({
2086
+ resource,
2087
+ processors: [this.logProcessor]
2088
+ });
2089
+ logger.debug("Logger provider initialization completed");
2090
+ }
2091
+ /**
2092
+ * Emit a custom event to the telemetry pipeline
2093
+ */
2094
+ emitEvent(name, attributes, body, severityNumber = import_api_logs2.SeverityNumber.INFO) {
2095
+ logger.debug("Attempting to emit event", {
2096
+ name,
2097
+ hasAttributes: !!attributes,
2098
+ attributesCount: attributes ? Object.keys(attributes).length : 0,
2099
+ hasBody: !!body,
2100
+ severityNumber
2101
+ });
2102
+ if (!this.loggerProvider) {
2103
+ logger.error("Cannot emit event: Logger provider not initialized");
2104
+ throw new Error("Logging module not initialized");
2105
+ }
2106
+ const logAttributes = { "event.name": name };
2107
+ if (attributes) {
2108
+ Object.assign(logAttributes, attributes);
2109
+ logger.debug("Combined log attributes", { attributes: Object.keys(logAttributes) });
2110
+ }
2111
+ logger.debug("Getting logger instance for brizz_events");
2112
+ const eventLogger = this.loggerProvider.getLogger("brizz.events");
2113
+ logger.debug("Emitting log record with eventName", { eventName: name });
2114
+ try {
2115
+ eventLogger.emit({
2116
+ eventName: name,
2117
+ attributes: logAttributes,
2118
+ severityNumber,
2119
+ body
2120
+ });
2121
+ logger.debug("Event successfully emitted", { eventName: name });
2122
+ } catch (error) {
2123
+ logger.error(`Failed to emit event '${name}'`, { error, eventName: name });
2124
+ logger.error("Log record that failed", {
2125
+ eventName: name,
2126
+ hasAttributes: logAttributes,
2127
+ severityNumber,
2128
+ hasBody: body
2129
+ });
2130
+ throw error instanceof Error ? error : new Error(String(error));
2131
+ }
2132
+ }
2133
+ /**
2134
+ * Check if the module is initialized
2135
+ */
2136
+ isInitialized() {
2137
+ return this.loggerProvider !== null;
2138
+ }
2139
+ /**
2140
+ * Get the logger provider
2141
+ */
2142
+ getLoggerProvider() {
2143
+ return this.loggerProvider;
2144
+ }
2145
+ /**
2146
+ * Shutdown the logging module
2147
+ */
2148
+ async shutdown() {
2149
+ logger.debug("Shutting down logging module");
2150
+ if (this.loggerProvider) {
2151
+ await this.loggerProvider.shutdown();
2152
+ this.loggerProvider = null;
2153
+ }
2154
+ this.logProcessor = null;
2155
+ this.logExporter = null;
2156
+ if (_LoggingModule.instance === this) {
2157
+ _LoggingModule.instance = null;
2158
+ }
2159
+ logger.debug("Logging module shutdown completed");
2160
+ }
2161
+ };
2162
+
2163
+ // src/internal/metric/metrics.ts
2164
+ var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
2165
+ var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
2166
+ var MetricsModule = class _MetricsModule {
2167
+ static instance = null;
2168
+ metricsExporter = null;
2169
+ metricsReader = null;
2170
+ static getInstance() {
2171
+ if (!_MetricsModule.instance) {
2172
+ throw new Error("Brizz must be initialized before accessing MetricsModule");
2173
+ }
2174
+ return _MetricsModule.instance;
2175
+ }
2176
+ /**
2177
+ * Initialize the metrics module with the provided configuration
2178
+ */
2179
+ setup(config) {
2180
+ logger.info("Setting up metrics module");
2181
+ this.initMetricsReader(config);
2182
+ _MetricsModule.instance = this;
2183
+ logger.info("Metrics module setup completed");
2184
+ }
2185
+ /**
2186
+ * Initialize the metrics exporter
2187
+ */
2188
+ initMetricsExporter(config) {
2189
+ if (this.metricsExporter) {
2190
+ logger.debug("Metrics exporter already initialized, skipping re-initialization");
2191
+ return;
2192
+ }
2193
+ const metricsUrl = config.baseUrl.replace(/\/$/, "") + "/v1/metrics";
2194
+ logger.debug("Initializing metrics exporter", { url: metricsUrl });
2195
+ this.metricsExporter = new import_exporter_metrics_otlp_http.OTLPMetricExporter({
2196
+ url: metricsUrl,
2197
+ headers: config.headers
2198
+ });
2199
+ logger.debug("Metrics exporter initialized successfully");
2200
+ }
2201
+ /**
2202
+ * Initialize the metrics reader
2203
+ */
2204
+ initMetricsReader(config) {
2205
+ if (this.metricsReader) {
2206
+ logger.debug("Metrics reader already initialized, skipping re-initialization");
2207
+ return;
2208
+ }
2209
+ if (config.customMetricReader) {
2210
+ logger.debug("Using custom metric reader");
2211
+ this.metricsReader = config.customMetricReader;
2212
+ logger.debug("Custom metric reader initialized successfully");
2213
+ return;
2214
+ }
2215
+ logger.debug(
2216
+ "Using default metrics flow - creating OTLP exporter and PeriodicExportingMetricReader"
2217
+ );
2218
+ this.initMetricsExporter(config);
2219
+ if (!this.metricsExporter) {
2220
+ throw new Error("Failed to initialize metrics exporter");
2221
+ }
2222
+ this.metricsReader = new import_sdk_metrics.PeriodicExportingMetricReader({
2223
+ exporter: this.metricsExporter
2224
+ });
2225
+ logger.debug("Default metrics reader initialized successfully");
2226
+ }
2227
+ /**
2228
+ * Get the metrics exporter
2229
+ */
2230
+ getMetricsExporter() {
2231
+ if (!this.metricsExporter) {
2232
+ throw new Error("Metrics module not initialized");
2233
+ }
2234
+ return this.metricsExporter;
2235
+ }
2236
+ /**
2237
+ * Get the metrics reader
2238
+ */
2239
+ getMetricsReader() {
2240
+ if (!this.metricsReader) {
2241
+ throw new Error("Metrics module not initialized");
2242
+ }
2243
+ return this.metricsReader;
2244
+ }
2245
+ /**
2246
+ * Shutdown the metrics module
2247
+ */
2248
+ shutdown() {
2249
+ logger.debug("Shutting down metrics module");
2250
+ this.metricsReader = null;
2251
+ this.metricsExporter = null;
2252
+ if (_MetricsModule.instance === this) {
2253
+ _MetricsModule.instance = null;
2254
+ }
2255
+ logger.debug("Metrics module shutdown completed");
2256
+ }
2257
+ };
2258
+ function getMetricsReader() {
2259
+ return MetricsModule.getInstance().getMetricsReader();
2260
+ }
2261
+
2262
+ // src/internal/trace/tracing.ts
2263
+ var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
2264
+
2265
+ // src/internal/trace/processors/span-processor.ts
2266
+ var import_api10 = require("@opentelemetry/api");
2267
+ var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
2268
+ var DEFAULT_MASKING_RULES = [
2269
+ {
2270
+ mode: "partial",
2271
+ attributePattern: "gen_ai.prompt",
2272
+ patterns: DEFAULT_PII_PATTERNS
2273
+ },
2274
+ {
2275
+ mode: "partial",
2276
+ attributePattern: "gen_ai.completion",
2277
+ patterns: DEFAULT_PII_PATTERNS
2278
+ },
2279
+ {
2280
+ mode: "partial",
2281
+ attributePattern: "traceloop.entity.input",
2282
+ patterns: DEFAULT_PII_PATTERNS
2283
+ },
2284
+ {
2285
+ mode: "partial",
2286
+ attributePattern: "traceloop.entity.output",
2287
+ patterns: DEFAULT_PII_PATTERNS
2288
+ }
2289
+ ];
2290
+ var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanProcessor {
2291
+ config;
2292
+ constructor(spanExporter, config) {
2293
+ super(spanExporter);
2294
+ this.config = config;
2295
+ }
2296
+ // Will work with the following code:
2297
+ // const span = tracer.startSpan('sensitive-operation',{attributes:{
2298
+ // 'user.password': 'secret123',
2299
+ // 'user.email': 'user@example.com',
2300
+ // }});
2301
+ //
2302
+ // Won't work because onStart is called before attributes are set:
2303
+ // span.setAttributes({
2304
+ // 'user.password': 'secret123',
2305
+ // 'user.email': 'user@example.com'
2306
+ // });
2307
+ onStart(span, parentContext) {
2308
+ const maskingConfig = this.config.masking?.spanMasking;
2309
+ if (maskingConfig) {
2310
+ maskSpan(span, maskingConfig);
2311
+ }
2312
+ const associationProperties = import_api10.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2313
+ if (associationProperties) {
2314
+ for (const [key, value] of Object.entries(associationProperties)) {
2315
+ span.setAttribute(`${BRIZZ}.${key}`, value);
2316
+ }
2317
+ }
2318
+ super.onStart(span, parentContext);
2319
+ }
2320
+ };
2321
+ var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProcessor {
2322
+ config;
2323
+ constructor(spanExporter, config) {
2324
+ super(spanExporter);
2325
+ this.config = config;
2326
+ }
2327
+ onStart(span, parentContext) {
2328
+ const maskingConfig = this.config.masking?.spanMasking;
2329
+ if (maskingConfig) {
2330
+ maskSpan(span, maskingConfig);
2331
+ }
2332
+ const associationProperties = import_api10.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2333
+ if (associationProperties) {
2334
+ for (const [key, value] of Object.entries(associationProperties)) {
2335
+ span.setAttribute(`${BRIZZ}.${key}`, value);
2336
+ }
2337
+ }
2338
+ super.onStart(span, parentContext);
2339
+ }
2340
+ };
2341
+ function maskSpan(span, config) {
2342
+ if (!span.attributes || Object.keys(span.attributes).length === 0) {
2343
+ return span;
2344
+ }
2345
+ let rules = config.rules || [];
2346
+ if (!config.disableDefaultRules) {
2347
+ rules = [...DEFAULT_MASKING_RULES, ...rules];
2348
+ }
2349
+ try {
2350
+ const attributesRecord = {};
2351
+ for (const [key, value] of Object.entries(span.attributes)) {
2352
+ attributesRecord[key] = value;
2353
+ }
2354
+ const maskedAttributes = maskAttributes(attributesRecord, rules);
2355
+ if (maskedAttributes && Object.keys(maskedAttributes).length > 0) {
2356
+ const merged = { ...span.attributes };
2357
+ for (const [key, value] of Object.entries(maskedAttributes)) {
2358
+ merged[key] = value;
2359
+ }
2360
+ span.setAttributes(merged);
2361
+ }
2362
+ return span;
2363
+ } catch (error) {
2364
+ logger.error("Error masking span:", error);
2365
+ return span;
2366
+ }
2367
+ }
2368
+
2369
+ // src/internal/trace/tracing.ts
2370
+ var TracingModule = class _TracingModule {
2371
+ static instance = null;
2372
+ spanExporter = null;
2373
+ spanProcessor = null;
2374
+ static getInstance() {
2375
+ if (!_TracingModule.instance) {
2376
+ throw new Error("Brizz must be initialized before accessing TracingModule");
2377
+ }
2378
+ return _TracingModule.instance;
2379
+ }
2380
+ /**
2381
+ * Initialize the tracing module with the provided configuration
2382
+ */
2383
+ setup(config) {
2384
+ logger.info("Setting up tracing module");
2385
+ this.initSpanExporter(config);
2386
+ this.initSpanProcessor(config);
2387
+ _TracingModule.instance = this;
2388
+ logger.info("Tracing module setup completed");
2389
+ }
2390
+ /**
2391
+ * Initialize the span exporter
2392
+ */
2393
+ initSpanExporter(config) {
2394
+ if (this.spanExporter) {
2395
+ logger.debug("Span exporter already initialized, skipping re-initialization");
2396
+ return;
2397
+ }
2398
+ if (config.customSpanExporter) {
2399
+ logger.debug("Using custom span exporter");
2400
+ this.spanExporter = config.customSpanExporter;
2401
+ logger.debug("Custom span exporter initialized successfully");
2402
+ return;
2403
+ }
2404
+ const tracesUrl = config.baseUrl.replace(/\/$/, "") + "/v1/traces";
2405
+ logger.debug("Initializing default OTLP span exporter", { url: tracesUrl });
2406
+ this.spanExporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({
2407
+ url: tracesUrl,
2408
+ headers: config.headers
2409
+ });
2410
+ logger.debug("OTLP span exporter initialized successfully");
2411
+ }
2412
+ /**
2413
+ * Initialize the span processor with masking support
2414
+ */
2415
+ initSpanProcessor(config) {
2416
+ if (this.spanProcessor) {
2417
+ logger.debug("Span processor already initialized, skipping re-initialization");
2418
+ return;
2419
+ }
2420
+ if (!this.spanExporter) {
2421
+ throw new Error("Span exporter must be initialized before processor");
2422
+ }
2423
+ logger.debug("Initializing span processor", {
2424
+ disableBatch: config.disableBatch,
2425
+ hasMasking: !!config.masking?.spanMasking
2426
+ });
2427
+ this.spanProcessor = config.disableBatch ? new BrizzSimpleSpanProcessor(this.spanExporter, config) : new BrizzBatchSpanProcessor(this.spanExporter, config);
2428
+ logger.debug("Span processor initialized successfully");
2429
+ }
2430
+ /**
2431
+ * Get the span exporter
2432
+ */
2433
+ getSpanExporter() {
2434
+ if (!this.spanExporter) {
2435
+ throw new Error("Tracing module not initialized");
2436
+ }
2437
+ return this.spanExporter;
2438
+ }
2439
+ /**
2440
+ * Get the span processor
2441
+ */
2442
+ getSpanProcessor() {
2443
+ if (!this.spanProcessor) {
2444
+ throw new Error("Tracing module not initialized");
2445
+ }
2446
+ return this.spanProcessor;
2447
+ }
2448
+ async shutdown() {
2449
+ logger.debug("Shutting down tracing module");
2450
+ if (this.spanProcessor) {
2451
+ await this.spanProcessor.shutdown();
2452
+ this.spanProcessor = null;
2453
+ }
2454
+ if (this.spanExporter) {
2455
+ await this.spanExporter.shutdown();
2456
+ this.spanExporter = null;
2457
+ }
2458
+ _TracingModule.instance = null;
2459
+ logger.debug("Tracing module shutdown completed");
2460
+ }
2461
+ };
2462
+ function getSpanProcessor() {
2463
+ return TracingModule.getInstance().getSpanProcessor();
2464
+ }
2465
+
2466
+ // src/internal/trace/session.ts
2467
+ var import_api11 = require("@opentelemetry/api");
2468
+
2469
+ // src/internal/sdk.ts
2470
+ var _Brizz = class __Brizz {
2471
+ static instance = null;
2472
+ /** Flag indicating if SDK initialization has completed successfully */
2473
+ _initialized = false;
2474
+ /** OpenTelemetry sdk instance */
2475
+ _sdk = null;
2476
+ static getInstance() {
2477
+ if (!__Brizz.instance) {
2478
+ throw new Error("Brizz must be initialized before accessing TracingModule");
2479
+ }
2480
+ return __Brizz.instance;
2481
+ }
2482
+ /**
2483
+ * Initialize the Brizz SDK with the provided configuration.
2484
+ *
2485
+ * @param {IBrizzInitializeOptions} options - Configuration options for the SDK
2486
+ * @throws {Error} - If initialization fails
2487
+ *
2488
+ * @example
2489
+ * ```typescript
2490
+ * Brizz.initialize({
2491
+ * appName: 'my-app',
2492
+ * baseUrl: 'http://localhost:4318',
2493
+ * apiKey: 'your-api-key'
2494
+ * });
2495
+ * ```
2496
+ */
2497
+ initialize(options) {
2498
+ if (this._initialized) {
2499
+ logger.warn("Brizz SDK already initialized");
2500
+ return;
2501
+ }
2502
+ logger.info("Starting Brizz SDK initialization");
2503
+ try {
2504
+ const resolvedConfig = resolveConfig(options);
2505
+ this.initializeModules(resolvedConfig);
2506
+ this.setupInstrumentation(options);
2507
+ this.createAndStartNodeSDK(options, resolvedConfig);
2508
+ this._initialized = true;
2509
+ logger.info("Brizz SDK initialization completed successfully", {
2510
+ moduleSystem: this.detectModuleSystem()
2511
+ });
2512
+ } catch (error) {
2513
+ logger.error("Failed to initialize Brizz SDK", { error });
2514
+ throw new Error(`Failed to initialize SDK: ${String(error)}`);
2515
+ }
2516
+ }
2517
+ /**
2518
+ * Set up instrumentation registry and configure manual modules.
2519
+ * @private
2520
+ */
2521
+ setupInstrumentation(options) {
2522
+ const registry = InstrumentationRegistry.getInstance();
2523
+ if (options.instrumentModules && Object.keys(options.instrumentModules).length > 0) {
2524
+ registry.setManualModules(options.instrumentModules);
2525
+ }
2526
+ }
2527
+ /**
2528
+ * Create and start NodeSDK if not disabled.
2529
+ * Only handles manual instrumentations now - auto instrumentations are loaded at import time.
2530
+ * @private
2531
+ */
2532
+ createAndStartNodeSDK(options, resolvedConfig) {
2533
+ if (options.disableNodeSdk) {
2534
+ logger.info("NodeSDK disabled - only telemetry modules initialized");
2535
+ return;
2536
+ }
2537
+ const registry = InstrumentationRegistry.getInstance();
2538
+ const manualInstrumentations = registry.getManualInstrumentations();
2539
+ this._sdk = new import_sdk_node.NodeSDK({
2540
+ spanProcessors: [getSpanProcessor()],
2541
+ metricReader: getMetricsReader(),
2542
+ resource: (0, import_resources2.resourceFromAttributes)({
2543
+ "service.name": resolvedConfig.appName
2544
+ }),
2545
+ instrumentations: manualInstrumentations
2546
+ });
2547
+ this._sdk.start();
2548
+ if (manualInstrumentations.length > 0) {
2549
+ logger.info(`NodeSDK started with ${manualInstrumentations.length} manual instrumentations`);
2550
+ } else {
2551
+ logger.info("NodeSDK started - using auto-instrumentations loaded at import time");
2552
+ }
2553
+ }
2554
+ /**
2555
+ * Initialize telemetry modules.
2556
+ *
2557
+ * Sets up the tracing, metrics, and logging modules with their
2558
+ * respective exporters and processors.
2559
+ *
2560
+ * @param {IResolvedBrizzConfig} config - Resolved configuration
2561
+ * @private
2562
+ */
2563
+ initializeModules(config) {
2564
+ logger.info("Initializing telemetry modules");
2565
+ logger.debug("Initializing tracing module");
2566
+ const tracingModule = new TracingModule();
2567
+ tracingModule.setup(config);
2568
+ logger.debug("Initializing metrics module");
2569
+ const metricsModule = new MetricsModule();
2570
+ metricsModule.setup(config);
2571
+ logger.debug("Initializing logging module");
2572
+ const loggingModule = new LoggingModule();
2573
+ loggingModule.setup(config);
2574
+ logger.info("All telemetry modules initialized successfully");
2575
+ }
2576
+ /**
2577
+ * Detect the current module system (ESM or CJS) using reliable indicators
2578
+ *
2579
+ * @returns {string} - 'ESM' or 'CJS'
2580
+ * @private
2581
+ */
2582
+ detectModuleSystem() {
2583
+ const inCJS = typeof module !== "undefined" && typeof exports !== "undefined" && typeof require === "function" && typeof __filename === "string" && typeof __dirname === "string" && this === (typeof exports !== "undefined" ? exports : void 0);
2584
+ return inCJS ? "CJS" : "ESM";
2585
+ }
2586
+ /**
2587
+ * Gracefully shutdown the Brizz SDK.
2588
+ *
2589
+ * This method stops all telemetry collection, flushes any pending data,
2590
+ * and releases resources. Should be called before application termination.
2591
+ *
2592
+ * @returns {Promise<void>} - Resolves when shutdown is complete
2593
+ * @throws {Error} - If shutdown fails
2594
+ *
2595
+ * @example
2596
+ * ```typescript
2597
+ * // Shutdown before app exit
2598
+ * await Brizz.shutdown();
2599
+ * ```
2600
+ */
2601
+ async shutdown() {
2602
+ if (!this._initialized) {
2603
+ logger.warn("Brizz SDK not initialized");
2604
+ return;
2605
+ }
2606
+ try {
2607
+ await this.shutdownModules();
2608
+ await this._sdk?.shutdown();
2609
+ this._initialized = false;
2610
+ this._sdk = null;
2611
+ __Brizz.instance = null;
2612
+ logger.info("Brizz SDK shut down successfully");
2613
+ } catch (error) {
2614
+ if (error instanceof Error && error.message.includes("ENOTFOUND")) {
2615
+ logger.debug(`Network error during shutdown (expected in tests): ${error.message}`);
2616
+ } else {
2617
+ logger.error(`Failed to shutdown Brizz SDK: ${String(error)}`);
2618
+ throw error;
2619
+ }
2620
+ }
2621
+ }
2622
+ /**
2623
+ * Shutdown all telemetry modules.
2624
+ * @private
2625
+ */
2626
+ async shutdownModules() {
2627
+ logger.info("Shutting down telemetry modules");
2628
+ try {
2629
+ try {
2630
+ const tracingModule = TracingModule.getInstance();
2631
+ await tracingModule.shutdown();
2632
+ } catch {
2633
+ logger.debug("Tracing module already shut down or not initialized");
2634
+ }
2635
+ try {
2636
+ const metricsModule = MetricsModule.getInstance();
2637
+ metricsModule.shutdown();
2638
+ } catch {
2639
+ logger.debug("Metrics module already shut down or not initialized");
2640
+ }
2641
+ try {
2642
+ const loggingModule = LoggingModule.getInstance();
2643
+ await loggingModule.shutdown();
2644
+ } catch {
2645
+ logger.debug("Logging module already shut down or not initialized");
2646
+ }
2647
+ logger.info("All telemetry modules shut down successfully");
2648
+ } catch (error) {
2649
+ logger.error("Error shutting down modules", { error });
2650
+ throw error;
2651
+ }
2652
+ }
2653
+ };
2654
+ var Brizz = new _Brizz();
2655
+
2656
+ // src/node/loader.ts
2657
+ var import_node_module = __toESM(require("module"), 1);
2658
+ var import_import_in_the_middle = require("import-in-the-middle");
2659
+ var loaderDebug = (() => {
2660
+ const isDebug = process.env["BRIZZ_ESM_DEBUG"] === "true" || process.env["BRIZZ_LOG_LEVEL"] === "debug";
2661
+ return {
2662
+ log: (msg, data) => {
2663
+ if (!isDebug) {
2664
+ return;
2665
+ }
2666
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2667
+ const dataStr = data ? ` ${JSON.stringify(data)}` : "";
2668
+ console.log(`[${timestamp}] [ESM-LOADER] ${msg}${dataStr}`);
2669
+ },
2670
+ error: (msg, error) => {
2671
+ if (!isDebug) {
2672
+ return;
2673
+ }
2674
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2675
+ const errorStr = error instanceof Error ? ` ${error.message}` : error ? ` ${JSON.stringify(error)}` : "";
2676
+ console.error(`[${timestamp}] [ESM-LOADER] ERROR: ${msg}${errorStr}`);
2677
+ }
2678
+ };
2679
+ })();
2680
+ var LOADER_REGISTERED_KEY = Symbol.for("__brizz_esm_loader_registered__");
2681
+ function checkLoaderAPISupport() {
2682
+ const [major, minor] = process.versions.node.split(".").map(Number);
2683
+ if (major === void 0 || minor === void 0) {
2684
+ loaderDebug.log("Failed to detect Node version, assuming loader API is supported");
2685
+ return true;
2686
+ }
2687
+ const supported = major >= 21 || major === 20 && minor >= 6 || major === 18 && minor >= 19;
2688
+ loaderDebug.log("Loader API support check:", {
2689
+ nodeVersion: `${major}.${minor}`,
2690
+ supportsLoaderAPI: supported
2691
+ });
2692
+ return supported;
2693
+ }
2694
+ function maybeRegisterESMLoader() {
2695
+ if (globalThis[LOADER_REGISTERED_KEY] === true) {
2696
+ loaderDebug.log("ESM loader already registered, skipping");
2697
+ return false;
2698
+ }
2699
+ globalThis[LOADER_REGISTERED_KEY] = true;
2700
+ loaderDebug.log("Starting ESM loader registration...");
2701
+ if (!checkLoaderAPISupport()) {
2702
+ loaderDebug.log("Node.js version does not support loader API, skipping");
2703
+ return false;
2704
+ }
2705
+ try {
2706
+ loaderDebug.log("Creating MessageChannel for import-in-the-middle...");
2707
+ const { addHookMessagePort } = (0, import_import_in_the_middle.createAddHookMessageChannel)();
2708
+ loaderDebug.log("Registering import-in-the-middle/hook.mjs...");
2709
+ import_node_module.default.register("import-in-the-middle/hook.mjs", {
2710
+ data: { addHookMessagePort },
2711
+ transferList: [addHookMessagePort]
2712
+ });
2713
+ loaderDebug.log("ESM loader successfully registered!");
2714
+ return true;
2715
+ } catch (error) {
2716
+ loaderDebug.error("Failed to register ESM loader:", error);
2717
+ globalThis[LOADER_REGISTERED_KEY] = false;
2718
+ return false;
2719
+ }
2720
+ }
2721
+ if (globalThis[LOADER_REGISTERED_KEY] !== true) {
2722
+ loaderDebug.log("Loader module imported, attempting to register...");
2723
+ maybeRegisterESMLoader();
2724
+ }
2725
+
2726
+ // src/node/runtime.ts
2727
+ function detectRuntime() {
2728
+ const [major, minor] = process.versions.node.split(".").map(Number);
2729
+ const noNodeJSGlobals = typeof __filename === "undefined" && typeof __dirname === "undefined";
2730
+ const noModuleSystem = typeof module === "undefined" && typeof exports === "undefined";
2731
+ const hasRequire = typeof require === "function";
2732
+ const isESM = noNodeJSGlobals && noModuleSystem;
2733
+ const isCJS = hasRequire && typeof module !== "undefined" && typeof exports !== "undefined" && typeof __filename === "string" && typeof __dirname === "string";
2734
+ const supportsLoaderAPI = (major ?? 0) >= 21 || (major ?? 0) === 20 && (minor ?? 0) >= 6 || (major ?? 0) === 18 && (minor ?? 0) >= 19;
2735
+ const supportsRegister = !!process.features?.typescript || !!globalThis.module?.register;
2736
+ logger.debug("Runtime detection results:", {
2737
+ nodeVersion: `${major ?? 0}.${minor ?? 0}`,
2738
+ isESM,
2739
+ isCJS,
2740
+ supportsLoaderAPI,
2741
+ supportsRegister,
2742
+ detectionLogic: {
2743
+ noNodeJSGlobals,
2744
+ noModuleSystem,
2745
+ hasRequire,
2746
+ esmCondition: `${noNodeJSGlobals} && ${noModuleSystem} = ${isESM}`,
2747
+ cjsCondition: `require && module && exports && __filename && __dirname = ${isCJS}`
2748
+ },
2749
+ checks: {
2750
+ __filename: typeof __filename,
2751
+ __dirname: typeof __dirname,
2752
+ require: typeof require,
2753
+ module: typeof module,
2754
+ exports: typeof exports,
2755
+ "process.features": process.features,
2756
+ "globalThis.module": globalThis.module
2757
+ }
2758
+ });
2759
+ return {
2760
+ isESM,
2761
+ isCJS,
2762
+ nodeVersion: process.versions.node,
2763
+ supportsLoaderAPI,
2764
+ supportsRegister
2765
+ };
2766
+ }
2767
+
2768
+ // src/preload.ts
2769
+ var runtime = detectRuntime();
2770
+ if (runtime.isESM && runtime.supportsLoaderAPI) {
2771
+ maybeRegisterESMLoader();
2772
+ }
2773
+ try {
2774
+ Brizz.initialize({
2775
+ apiKey: process.env["BRIZZ_API_KEY"],
2776
+ baseUrl: process.env["BRIZZ_BASE_URL"],
2777
+ appName: process.env["BRIZZ_APP_NAME"] || process.env["OTEL_SERVICE_NAME"],
2778
+ logLevel: process.env["BRIZZ_LOG_LEVEL"] || DEFAULT_LOG_LEVEL.toString(),
2779
+ // Enable auto-instrumentation by default in preload mode
2780
+ disableNodeSdk: false
2781
+ });
2782
+ logger.info(`SDK auto-initialized for ${runtime.isESM ? "ESM" : "CJS"} runtime`);
2783
+ } catch (error) {
2784
+ logger.warn("Failed to auto-initialize SDK:", { error });
2785
+ }
2786
+ //# sourceMappingURL=preload.cjs.map