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