@brizz/sdk 0.1.21 → 0.1.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esm = (fn, res) => function __init() {
9
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
+ };
8
11
  var __export = (target, all) => {
9
12
  for (var name in all)
10
13
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -15,17 +18,961 @@ var __copyProps = (to, from, except, desc) => {
15
18
  if (!__hasOwnProp.call(to, key) && key !== except)
16
19
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
20
  }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/internal/logger.ts
34
+ function parseLogLevel(level) {
35
+ if (!level) {
36
+ return DEFAULT_LOG_LEVEL;
37
+ }
38
+ const normalizedLevel = level.toLowerCase().trim();
39
+ switch (normalizedLevel) {
40
+ case "debug":
41
+ return 4 /* DEBUG */;
42
+ case "info":
43
+ return 3 /* INFO */;
44
+ case "warn":
45
+ case "warning":
46
+ return 2 /* WARN */;
47
+ case "error":
48
+ return 1 /* ERROR */;
49
+ case "none":
50
+ case "off":
51
+ case "silent":
52
+ return 0 /* NONE */;
53
+ default: {
54
+ const numLevel = Number.parseInt(normalizedLevel, 10);
55
+ if (!Number.isNaN(numLevel) && numLevel >= 0 && numLevel <= 4) {
56
+ return numLevel;
57
+ }
58
+ return DEFAULT_LOG_LEVEL;
59
+ }
60
+ }
61
+ }
62
+ function setLogLevel(level) {
63
+ const resolvedLevel = typeof level === "string" ? parseLogLevel(level) : level;
64
+ logger.setLevel(resolvedLevel);
65
+ }
66
+ function getLogLevel() {
67
+ return logger.getLevel();
68
+ }
69
+ var import_api, import_pino, LogLevel, DEFAULT_LOG_LEVEL, PinoLogger, logger;
70
+ var init_logger = __esm({
71
+ "src/internal/logger.ts"() {
72
+ "use strict";
73
+ import_api = require("@opentelemetry/api");
74
+ import_pino = __toESM(require("pino"), 1);
75
+ LogLevel = /* @__PURE__ */ ((LogLevel2) => {
76
+ LogLevel2[LogLevel2["NONE"] = 0] = "NONE";
77
+ LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
78
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
79
+ LogLevel2[LogLevel2["INFO"] = 3] = "INFO";
80
+ LogLevel2[LogLevel2["DEBUG"] = 4] = "DEBUG";
81
+ return LogLevel2;
82
+ })(LogLevel || {});
83
+ DEFAULT_LOG_LEVEL = 2 /* WARN */;
84
+ PinoLogger = class {
85
+ _level = DEFAULT_LOG_LEVEL;
86
+ _pinoLogger = null;
87
+ constructor() {
88
+ const envLevel = this.getLogLevelFromEnv();
89
+ this._level = envLevel;
90
+ }
91
+ /**
92
+ * Lazy initialization of Pino logger to ensure it's created AFTER Jest spies
93
+ * are set up during tests. This prevents the pino-pretty transport from
94
+ * bypassing stdout/stderr spies.
95
+ */
96
+ ensurePinoLogger() {
97
+ if (!this._pinoLogger) {
98
+ this._pinoLogger = (0, import_pino.default)({
99
+ name: "Brizz",
100
+ level: this.logLevelToPino(this._level),
101
+ // Disable transport in test environment to allow proper spy capture
102
+ transport: this.isProduction() || this.isTest() ? void 0 : {
103
+ target: "pino-pretty",
104
+ options: {
105
+ singleLine: true,
106
+ colorize: true,
107
+ translateTime: "HH:MM:ss",
108
+ ignore: "pid,hostname",
109
+ messageFormat: "[{name}] {msg}"
110
+ }
111
+ }
112
+ });
113
+ }
114
+ return this._pinoLogger;
115
+ }
116
+ isProduction() {
117
+ return process.env["NODE_ENV"] === "production";
118
+ }
119
+ isTest() {
120
+ return process.env["NODE_ENV"] === "test";
121
+ }
122
+ getLogLevelFromEnv() {
123
+ const envLevel = process.env["BRIZZ_LOG_LEVEL"];
124
+ return envLevel ? parseLogLevel(envLevel) : DEFAULT_LOG_LEVEL;
125
+ }
126
+ logLevelToPino(level) {
127
+ switch (level) {
128
+ case 4 /* DEBUG */:
129
+ return "debug";
130
+ case 3 /* INFO */:
131
+ return "info";
132
+ case 2 /* WARN */:
133
+ return "warn";
134
+ case 1 /* ERROR */:
135
+ return "error";
136
+ default:
137
+ return "silent";
138
+ }
139
+ }
140
+ formatMeta(meta) {
141
+ if (meta.length === 0) {
142
+ return {};
143
+ }
144
+ if (meta.length === 1 && typeof meta[0] === "object" && meta[0] !== null) {
145
+ return meta[0];
146
+ }
147
+ return { metadata: meta };
148
+ }
149
+ setLevel(level) {
150
+ this._level = level;
151
+ if (this._pinoLogger) {
152
+ this._pinoLogger.level = this.logLevelToPino(level);
153
+ }
154
+ }
155
+ getLevel() {
156
+ return this._level;
157
+ }
158
+ debug = (msg, ...meta) => {
159
+ if (this._level >= 4 /* DEBUG */) {
160
+ this.ensurePinoLogger().debug(this.formatMeta(meta), msg);
161
+ }
162
+ };
163
+ info = (msg, ...meta) => {
164
+ if (this._level >= 3 /* INFO */) {
165
+ this.ensurePinoLogger().info(this.formatMeta(meta), msg);
166
+ }
167
+ };
168
+ warn = (msg, ...meta) => {
169
+ if (this._level >= 2 /* WARN */) {
170
+ this.ensurePinoLogger().warn(this.formatMeta(meta), msg);
171
+ }
172
+ };
173
+ error = (msg, ...meta) => {
174
+ if (this._level >= 1 /* ERROR */) {
175
+ this.ensurePinoLogger().error(this.formatMeta(meta), msg);
176
+ }
177
+ };
178
+ };
179
+ logger = new PinoLogger();
180
+ }
181
+ });
182
+
183
+ // src/internal/semantic-conventions.ts
184
+ var import_api2, BRIZZ, PROPERTIES, SESSION_ID, PROPERTIES_CONTEXT_KEY, SESSION_OBJECT_CONTEXT_KEY, SESSION_INPUT, SESSION_OUTPUT, SESSION_INPUT_CONTEXT, SESSION_OUTPUT_CONTEXT, SESSION_SPAN_NAME, SESSION_TITLE_SPAN_NAME, SESSION_TITLE_GENERATION, SESSION_TITLE;
185
+ var init_semantic_conventions = __esm({
186
+ "src/internal/semantic-conventions.ts"() {
187
+ "use strict";
188
+ import_api2 = require("@opentelemetry/api");
189
+ BRIZZ = "brizz";
190
+ PROPERTIES = "properties";
191
+ SESSION_ID = "session.id";
192
+ PROPERTIES_CONTEXT_KEY = (0, import_api2.createContextKey)(PROPERTIES);
193
+ SESSION_OBJECT_CONTEXT_KEY = (0, import_api2.createContextKey)("brizz.session.object");
194
+ SESSION_INPUT = "brizz.session.input";
195
+ SESSION_OUTPUT = "brizz.session.output";
196
+ SESSION_INPUT_CONTEXT = "brizz.session.input.context";
197
+ SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
198
+ SESSION_SPAN_NAME = "brizz.start_session";
199
+ SESSION_TITLE_SPAN_NAME = "brizz.session_title";
200
+ SESSION_TITLE_GENERATION = "session.title_generation";
201
+ SESSION_TITLE = "brizz.session.title";
202
+ }
203
+ });
204
+
205
+ // src/internal/instrumentation/mcp/semantic-conventions.ts
206
+ var MCP_TOOL_NAME, MCP_TOOL_ARGUMENTS, MCP_TOOL_RESULT, MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL, MCP_COMPONENT_TOOL_SCHEMA, MCP_TOOL_SCHEMA_PARAMETERS, MCP_TOOL_SCHEMA_OUTPUT, MCP_TOOL_DESCRIPTION, SPAN_NAME_TOOL_REGISTER, MCP_METHOD_NAME, MCP_REQUEST_ID, MCP_SESSION_ID, MCP_PROTOCOL_VERSION, MCP_RESOURCE_URI, RPC_SYSTEM, RPC_SYSTEM_MCP, RPC_RESPONSE_STATUS_CODE, GEN_AI_TOOL_NAME, GEN_AI_PROMPT_NAME, GEN_AI_OPERATION_NAME, GEN_AI_OPERATION_EXECUTE_TOOL, NETWORK_TRANSPORT, ERROR_TYPE, ERROR_TYPE_TOOL, JSONRPC_REQUEST_ID, SPAN_NAME_TOOLS_CALL, MAX_ATTRIBUTE_LENGTH, TRUNCATION_SUFFIX, METHOD_TOOLS_CALL, METHOD_TOOLS_LIST, METHOD_RESOURCES_READ, METHOD_PROMPTS_GET, METHOD_INITIALIZE;
207
+ var init_semantic_conventions2 = __esm({
208
+ "src/internal/instrumentation/mcp/semantic-conventions.ts"() {
209
+ "use strict";
210
+ MCP_TOOL_NAME = "mcp.tool.name";
211
+ MCP_TOOL_ARGUMENTS = "mcp.tool.arguments";
212
+ MCP_TOOL_RESULT = "mcp.tool.result";
213
+ MCP_COMPONENT_TYPE = "mcp.component.type";
214
+ MCP_COMPONENT_TOOL = "tool";
215
+ MCP_COMPONENT_TOOL_SCHEMA = "tool_schema";
216
+ MCP_TOOL_SCHEMA_PARAMETERS = "mcp.tool.schema.parameters";
217
+ MCP_TOOL_SCHEMA_OUTPUT = "mcp.tool.schema.output";
218
+ MCP_TOOL_DESCRIPTION = "mcp.tool.description";
219
+ SPAN_NAME_TOOL_REGISTER = "mcp.tool.register";
220
+ MCP_METHOD_NAME = "mcp.method.name";
221
+ MCP_REQUEST_ID = "mcp.request.id";
222
+ MCP_SESSION_ID = "mcp.session.id";
223
+ MCP_PROTOCOL_VERSION = "mcp.protocol.version";
224
+ MCP_RESOURCE_URI = "mcp.resource.uri";
225
+ RPC_SYSTEM = "rpc.system";
226
+ RPC_SYSTEM_MCP = "mcp";
227
+ RPC_RESPONSE_STATUS_CODE = "rpc.response.status_code";
228
+ GEN_AI_TOOL_NAME = "gen_ai.tool.name";
229
+ GEN_AI_PROMPT_NAME = "gen_ai.prompt.name";
230
+ GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
231
+ GEN_AI_OPERATION_EXECUTE_TOOL = "execute_tool";
232
+ NETWORK_TRANSPORT = "network.transport";
233
+ ERROR_TYPE = "error.type";
234
+ ERROR_TYPE_TOOL = "tool_error";
235
+ JSONRPC_REQUEST_ID = "jsonrpc.request.id";
236
+ SPAN_NAME_TOOLS_CALL = "tools/call";
237
+ MAX_ATTRIBUTE_LENGTH = 32 * 1024;
238
+ TRUNCATION_SUFFIX = "\u2026(truncated)";
239
+ METHOD_TOOLS_CALL = "tools/call";
240
+ METHOD_TOOLS_LIST = "tools/list";
241
+ METHOD_RESOURCES_READ = "resources/read";
242
+ METHOD_PROMPTS_GET = "prompts/get";
243
+ METHOD_INITIALIZE = "initialize";
244
+ }
245
+ });
246
+
247
+ // src/internal/instrumentation/mcp/schemas.ts
248
+ function truncateSchemaAttr(value) {
249
+ if (value.length <= _MAX_SCHEMA_ATTR_BYTES) {
250
+ return value;
251
+ }
252
+ return `{"_truncated":true,"original_length":${value.length}}`;
253
+ }
254
+ function safeStringify(value) {
255
+ if (value === null || value === void 0) {
256
+ return "";
257
+ }
258
+ try {
259
+ return JSON.stringify(value);
260
+ } catch {
261
+ return "";
262
+ }
263
+ }
264
+ function emitSchemaSpansFromListResponse(result, transportSessionId, tracer) {
265
+ if (!transportSessionId) {
266
+ return;
267
+ }
268
+ const tools = extractTools(result);
269
+ if (tools === void 0) {
270
+ return;
271
+ }
272
+ for (const tool of tools) {
273
+ const name = typeof tool.name === "string" ? tool.name : void 0;
274
+ if (!name) {
275
+ continue;
276
+ }
277
+ const span = tracer.startSpan(`${SPAN_NAME_TOOL_REGISTER} ${name}`, {
278
+ kind: import_api3.SpanKind.INTERNAL
279
+ });
280
+ try {
281
+ stampSchemaAttributes(span, name, transportSessionId, tool);
282
+ span.setStatus({ code: import_api3.SpanStatusCode.OK });
283
+ } finally {
284
+ span.end();
285
+ }
286
+ }
287
+ }
288
+ function stampSchemaAttributes(span, toolName, transportSessionId, tool) {
289
+ if (!span.isRecording()) {
290
+ logger.warn(
291
+ `Brizz MCP: schema span is not recording; dropping attributes for ${toolName}`
292
+ );
293
+ return;
294
+ }
295
+ const description = typeof tool.description === "string" ? tool.description : "";
296
+ const parameters = truncateSchemaAttr(safeStringify(tool.inputSchema));
297
+ const outputSchema = tool.outputSchema !== void 0 && tool.outputSchema !== null ? truncateSchemaAttr(safeStringify(tool.outputSchema)) : "";
298
+ span.setAttribute(RPC_SYSTEM, RPC_SYSTEM_MCP);
299
+ span.setAttribute(MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL_SCHEMA);
300
+ span.setAttribute(MCP_SESSION_ID, transportSessionId);
301
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, transportSessionId);
302
+ span.setAttribute(MCP_TOOL_NAME, toolName);
303
+ span.setAttribute(MCP_TOOL_SCHEMA_PARAMETERS, parameters);
304
+ span.setAttribute(MCP_TOOL_SCHEMA_OUTPUT, outputSchema);
305
+ span.setAttribute(MCP_TOOL_DESCRIPTION, description);
306
+ }
307
+ function extractTools(result) {
308
+ if (!result || typeof result !== "object") {
309
+ return void 0;
310
+ }
311
+ const tools = result.tools;
312
+ if (!Array.isArray(tools)) {
313
+ return void 0;
314
+ }
315
+ return tools.filter(
316
+ (t) => t !== null && typeof t === "object"
317
+ );
318
+ }
319
+ var import_api3, _MAX_SCHEMA_ATTR_BYTES;
320
+ var init_schemas = __esm({
321
+ "src/internal/instrumentation/mcp/schemas.ts"() {
322
+ "use strict";
323
+ import_api3 = require("@opentelemetry/api");
324
+ init_logger();
325
+ init_semantic_conventions();
326
+ init_semantic_conventions2();
327
+ _MAX_SCHEMA_ATTR_BYTES = 4e3;
328
+ }
329
+ });
330
+
331
+ // src/internal/instrumentation/mcp/session.ts
332
+ function stampAndPropagateSession(span, sessionId, baseContext = import_api4.context.active()) {
333
+ if (!sessionId) {
334
+ return { context: baseContext, sessionId: null };
335
+ }
336
+ if (span.isRecording()) {
337
+ try {
338
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
339
+ } catch (error) {
340
+ logger.warn(
341
+ `Brizz MCP: failed to stamp session id on span: ${String(error)}`
342
+ );
343
+ }
344
+ }
345
+ try {
346
+ const prev = baseContext.getValue(PROPERTIES_CONTEXT_KEY);
347
+ const merged = prev ? { ...prev, [SESSION_ID]: sessionId } : { [SESSION_ID]: sessionId };
348
+ return {
349
+ context: baseContext.setValue(PROPERTIES_CONTEXT_KEY, merged),
350
+ sessionId
351
+ };
352
+ } catch (error) {
353
+ logger.warn(`Brizz MCP: failed to attach session context: ${String(error)}`);
354
+ return { context: baseContext, sessionId };
355
+ }
356
+ }
357
+ var import_api4;
358
+ var init_session = __esm({
359
+ "src/internal/instrumentation/mcp/session.ts"() {
360
+ "use strict";
361
+ import_api4 = require("@opentelemetry/api");
362
+ init_logger();
363
+ init_semantic_conventions();
364
+ }
365
+ });
366
+
367
+ // src/internal/instrumentation/mcp/patches/attributes.ts
368
+ function deriveSpanName(method, params) {
369
+ try {
370
+ if (method === METHOD_TOOLS_CALL) {
371
+ const name = typeof params?.["name"] === "string" ? params["name"] : "";
372
+ return name ? `${SPAN_NAME_TOOLS_CALL} ${name}` : SPAN_NAME_TOOLS_CALL;
373
+ }
374
+ if (method === METHOD_RESOURCES_READ) {
375
+ const uri = typeof params?.["uri"] === "string" ? params["uri"] : "";
376
+ return uri ? `${METHOD_RESOURCES_READ} ${uri}` : METHOD_RESOURCES_READ;
377
+ }
378
+ if (method === METHOD_PROMPTS_GET) {
379
+ const name = typeof params?.["name"] === "string" ? params["name"] : "";
380
+ return name ? `${METHOD_PROMPTS_GET} ${name}` : METHOD_PROMPTS_GET;
381
+ }
382
+ return method;
383
+ } catch {
384
+ return method || "mcp";
385
+ }
386
+ }
387
+ function applyBaseAttributes(span, request) {
388
+ span.setAttribute(RPC_SYSTEM, RPC_SYSTEM_MCP);
389
+ if (request.method) {
390
+ span.setAttribute(MCP_METHOD_NAME, request.method);
391
+ }
392
+ if (request.id !== void 0 && request.id !== null) {
393
+ const id = String(request.id);
394
+ span.setAttribute(MCP_REQUEST_ID, id);
395
+ span.setAttribute(JSONRPC_REQUEST_ID, id);
396
+ }
397
+ }
398
+ function applyClientRequestAttributes(span, request, transportName) {
399
+ applyBaseAttributes(span, request);
400
+ applyMethodSpecificRequestAttributes(span, request);
401
+ if (transportName) {
402
+ const transport = normalizeTransport(transportName);
403
+ if (transport) {
404
+ span.setAttribute(NETWORK_TRANSPORT, transport);
405
+ }
406
+ }
407
+ }
408
+ function applyServerRequestAttributes(span, request, protocol) {
409
+ applyBaseAttributes(span, request);
410
+ applyMethodSpecificRequestAttributes(span, request);
411
+ if (request.method === METHOD_TOOLS_CALL) {
412
+ const args = request.params?.["arguments"];
413
+ if (args !== void 0) {
414
+ span.setAttribute(MCP_TOOL_ARGUMENTS, serializeForAttribute(args));
415
+ }
416
+ }
417
+ const sessionId = protocol.sessionId ?? protocol._transport?.sessionId;
418
+ if (sessionId) {
419
+ span.setAttribute(MCP_SESSION_ID, String(sessionId));
420
+ }
421
+ }
422
+ function applyMethodSpecificRequestAttributes(span, request) {
423
+ const params = request.params ?? {};
424
+ switch (request.method) {
425
+ case METHOD_TOOLS_CALL: {
426
+ const name = typeof params["name"] === "string" ? params["name"] : "";
427
+ if (name) {
428
+ span.setAttribute(MCP_TOOL_NAME, name);
429
+ span.setAttribute(GEN_AI_TOOL_NAME, name);
430
+ }
431
+ span.setAttribute(MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL);
432
+ span.setAttribute(GEN_AI_OPERATION_NAME, GEN_AI_OPERATION_EXECUTE_TOOL);
433
+ break;
434
+ }
435
+ case METHOD_RESOURCES_READ: {
436
+ const uri = typeof params["uri"] === "string" ? params["uri"] : "";
437
+ if (uri) {
438
+ span.setAttribute(MCP_RESOURCE_URI, uri);
439
+ }
440
+ break;
441
+ }
442
+ case METHOD_PROMPTS_GET: {
443
+ const name = typeof params["name"] === "string" ? params["name"] : "";
444
+ if (name) {
445
+ span.setAttribute(GEN_AI_PROMPT_NAME, name);
446
+ }
447
+ break;
448
+ }
449
+ default:
450
+ break;
451
+ }
452
+ }
453
+ function applyResultAttributes(span, method, result) {
454
+ if (method === METHOD_INITIALIZE && result && typeof result === "object") {
455
+ const protocolVersion = result["protocolVersion"];
456
+ if (typeof protocolVersion === "string") {
457
+ span.setAttribute(MCP_PROTOCOL_VERSION, protocolVersion);
458
+ }
459
+ return;
460
+ }
461
+ if (method !== METHOD_TOOLS_CALL) {
462
+ return;
463
+ }
464
+ const obj = result && typeof result === "object" ? result : null;
465
+ const content = obj?.["content"] ?? result;
466
+ span.setAttribute(MCP_TOOL_RESULT, serializeForAttribute(content));
467
+ if (obj && obj["isError"] === true) {
468
+ span.setAttribute(ERROR_TYPE, ERROR_TYPE_TOOL);
469
+ const message = extractToolErrorMessage(obj);
470
+ span.setStatus({ code: import_api5.SpanStatusCode.ERROR, message });
471
+ }
472
+ }
473
+ function applyErrorAttributes(span, err) {
474
+ const error = err;
475
+ const code = error?.code;
476
+ if (typeof code === "number") {
477
+ span.setAttribute(RPC_RESPONSE_STATUS_CODE, code);
478
+ span.setAttribute(ERROR_TYPE, String(code));
479
+ } else if (error?.name === "AbortError") {
480
+ span.setAttribute(ERROR_TYPE, "cancelled");
481
+ } else if (error?.name === "TimeoutError") {
482
+ span.setAttribute(ERROR_TYPE, "timeout");
483
+ } else {
484
+ span.setAttribute(
485
+ ERROR_TYPE,
486
+ error?.constructor?.name || error?.name || "Error"
487
+ );
488
+ }
489
+ try {
490
+ span.recordException(error);
491
+ } catch {
492
+ }
493
+ span.setStatus({
494
+ code: import_api5.SpanStatusCode.ERROR,
495
+ message: typeof error?.message === "string" ? error.message : void 0
496
+ });
497
+ }
498
+ function serializeForAttribute(value) {
499
+ const raw = rawSerialize(value);
500
+ if (raw.length <= MAX_ATTRIBUTE_LENGTH) {
501
+ return raw;
502
+ }
503
+ return raw.slice(0, MAX_ATTRIBUTE_LENGTH - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX;
504
+ }
505
+ function rawSerialize(value) {
506
+ if (value === null || value === void 0) {
507
+ return "";
508
+ }
509
+ if (typeof value === "string") {
510
+ return value;
511
+ }
512
+ try {
513
+ return JSON.stringify(value);
514
+ } catch {
515
+ try {
516
+ if (value === null || value === void 0) {
517
+ return "";
518
+ }
519
+ const tag = Object.prototype.toString.call(value);
520
+ return typeof value.toString === "function" ? (
521
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
522
+ String(value)
523
+ ) : tag;
524
+ } catch {
525
+ return "";
526
+ }
527
+ }
528
+ }
529
+ function extractToolErrorMessage(result) {
530
+ const content = result["content"];
531
+ if (Array.isArray(content)) {
532
+ for (const item of content) {
533
+ if (item && typeof item === "object") {
534
+ const text = item["text"];
535
+ if (typeof text === "string") {
536
+ return text;
537
+ }
538
+ }
539
+ }
540
+ }
541
+ return void 0;
542
+ }
543
+ function normalizeTransport(ctorName) {
544
+ const name = ctorName.toLowerCase();
545
+ if (name.includes("stdio")) {
546
+ return "stdio";
547
+ }
548
+ if (name.includes("sse")) {
549
+ return "sse";
550
+ }
551
+ if (name.includes("streamablehttp") || name.includes("http")) {
552
+ return "http";
553
+ }
554
+ return null;
555
+ }
556
+ var import_api5;
557
+ var init_attributes = __esm({
558
+ "src/internal/instrumentation/mcp/patches/attributes.ts"() {
559
+ "use strict";
560
+ import_api5 = require("@opentelemetry/api");
561
+ init_semantic_conventions2();
562
+ }
563
+ });
564
+
565
+ // src/internal/instrumentation/mcp/patches/protocol.ts
566
+ function patchProtocolPrototype(prototype, tracer) {
567
+ if (!prototype || typeof prototype !== "object") {
568
+ return false;
569
+ }
570
+ const proto = prototype;
571
+ if (proto[PATCHED_FLAG]) {
572
+ logger.debug("Brizz MCP: Protocol.prototype already patched, skipping");
573
+ return false;
574
+ }
575
+ const originalRequest = proto["request"];
576
+ const originalOnRequest = proto["_onrequest"];
577
+ if (typeof originalRequest === "function") {
578
+ proto["request"] = wrapRequest(originalRequest, tracer);
579
+ } else {
580
+ logger.debug(
581
+ "Brizz MCP: Protocol.prototype.request missing \u2014 skipping CLIENT patch"
582
+ );
583
+ }
584
+ if (typeof originalOnRequest === "function") {
585
+ proto["_onrequest"] = wrapOnRequest(
586
+ originalOnRequest,
587
+ tracer
588
+ );
589
+ } else {
590
+ logger.debug(
591
+ "Brizz MCP: Protocol.prototype._onrequest missing \u2014 skipping SERVER patch"
592
+ );
593
+ }
594
+ proto[PATCHED_FLAG] = true;
595
+ return true;
596
+ }
597
+ function wrapRequest(original, tracer) {
598
+ return function wrappedRequest(...args) {
599
+ const request = args[0];
600
+ if (!request || typeof request !== "object" || !request.method) {
601
+ return original.apply(this, args);
602
+ }
603
+ const span = safeStartClientSpan(tracer, request, this);
604
+ if (!span) {
605
+ return original.apply(this, args);
606
+ }
607
+ return executeAroundSpan(span, request.method, () => {
608
+ const ctx = import_api6.trace.setSpan(import_api6.context.active(), span);
609
+ return import_api6.context.with(ctx, () => original.apply(this, args));
610
+ });
611
+ };
612
+ }
613
+ function wrapOnRequest(original, tracer) {
614
+ return function wrappedOnRequest(...args) {
615
+ const request = args[0];
616
+ if (!request || typeof request !== "object" || !request.method) {
617
+ return original.apply(this, args);
618
+ }
619
+ const handlers = this._requestHandlers;
620
+ if (!handlers || typeof handlers.get !== "function") {
621
+ return original.apply(this, args);
622
+ }
623
+ const method = request.method;
624
+ const handler = handlers.get(method) ?? this.fallbackRequestHandler;
625
+ if (!handler) {
626
+ return original.apply(this, args);
627
+ }
628
+ const started = safeStartServerSpan(tracer, request, this);
629
+ if (!started) {
630
+ return original.apply(this, args);
631
+ }
632
+ const { span, spanCtx } = started;
633
+ const transportSessionId = this.sessionId ?? this._transport?.sessionId;
634
+ const postResult = method === METHOD_TOOLS_LIST ? (result) => {
635
+ try {
636
+ emitSchemaSpansFromListResponse(result, transportSessionId, tracer);
637
+ } catch (error) {
638
+ logger.warn(
639
+ `Brizz MCP: failed to emit tools/list schema spans: ${String(error)}`
640
+ );
641
+ }
642
+ } : void 0;
643
+ const wrappedHandler = (req, extra) => import_api6.context.with(
644
+ spanCtx,
645
+ () => executeHandler(span, method, handler, req, extra, postResult)
646
+ );
647
+ const hadEntry = handlers.has(method);
648
+ const prev = handlers.get(method);
649
+ handlers.set(method, wrappedHandler);
650
+ const usedFallback = !hadEntry && this.fallbackRequestHandler === handler;
651
+ const fallbackPrev = usedFallback ? this.fallbackRequestHandler : void 0;
652
+ if (usedFallback) {
653
+ this.fallbackRequestHandler = wrappedHandler;
654
+ }
655
+ try {
656
+ return original.apply(this, args);
657
+ } finally {
658
+ if (hadEntry) {
659
+ handlers.set(method, prev);
660
+ } else {
661
+ handlers.delete(method);
662
+ }
663
+ if (usedFallback) {
664
+ this.fallbackRequestHandler = fallbackPrev;
665
+ }
666
+ }
667
+ };
668
+ }
669
+ function executeAroundSpan(span, method, run, postResult) {
670
+ let result;
671
+ try {
672
+ result = run();
673
+ } catch (error) {
674
+ safeApplyErrorAttributes(span, error);
675
+ safeEnd(span);
676
+ throw error;
677
+ }
678
+ if (!isThenable(result)) {
679
+ safeApplyResultAttributes(span, method, result);
680
+ if (postResult) {
681
+ postResult(result);
682
+ }
683
+ safeEnd(span);
684
+ return result;
685
+ }
686
+ return result.then(
687
+ (value) => {
688
+ safeApplyResultAttributes(span, method, value);
689
+ if (postResult) {
690
+ postResult(value);
691
+ }
692
+ safeEnd(span);
693
+ return value;
694
+ },
695
+ (error) => {
696
+ safeApplyErrorAttributes(span, error);
697
+ safeEnd(span);
698
+ throw error;
699
+ }
700
+ );
701
+ }
702
+ function executeHandler(span, method, handler, req, extra, postResult) {
703
+ return executeAroundSpan(span, method, () => handler(req, extra), postResult);
704
+ }
705
+ function safeStartClientSpan(tracer, request, protocol) {
706
+ try {
707
+ const spanName = deriveSpanName(request.method, request.params);
708
+ const span = tracer.startSpan(spanName, { kind: import_api6.SpanKind.CLIENT });
709
+ applyClientRequestAttributes(
710
+ span,
711
+ request,
712
+ protocol._transport?.constructor?.name
713
+ );
714
+ return span;
715
+ } catch (error) {
716
+ logger.debug(`Brizz MCP: failed to open CLIENT span: ${String(error)}`);
717
+ return null;
718
+ }
719
+ }
720
+ function safeStartServerSpan(tracer, request, protocol) {
721
+ try {
722
+ const parentCtx = extractParentContext(request);
723
+ const spanName = deriveSpanName(request.method, request.params);
724
+ const span = tracer.startSpan(
725
+ spanName,
726
+ { kind: import_api6.SpanKind.SERVER },
727
+ parentCtx
728
+ );
729
+ applyServerRequestAttributes(span, request, protocol);
730
+ const sessionId = protocol.sessionId ?? protocol._transport?.sessionId;
731
+ const { context: sessCtx } = stampAndPropagateSession(span, sessionId, parentCtx);
732
+ return { span, spanCtx: import_api6.trace.setSpan(sessCtx, span) };
733
+ } catch (error) {
734
+ logger.debug(`Brizz MCP: failed to open SERVER span: ${String(error)}`);
735
+ return null;
736
+ }
737
+ }
738
+ function extractParentContext(request) {
739
+ try {
740
+ const meta = request.params?._meta;
741
+ if (meta && typeof meta === "object") {
742
+ return import_api6.propagation.extract(import_api6.context.active(), meta);
743
+ }
744
+ } catch (error) {
745
+ logger.debug(
746
+ `Brizz MCP: failed to extract parent context from _meta: ${String(error)}`
747
+ );
748
+ }
749
+ return import_api6.context.active();
750
+ }
751
+ function isThenable(value) {
752
+ return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
753
+ }
754
+ function safeApplyResultAttributes(span, method, value) {
755
+ try {
756
+ applyResultAttributes(span, method, value);
757
+ } catch (error) {
758
+ logger.debug(
759
+ `Brizz MCP: failed to apply result attributes: ${String(error)}`
760
+ );
761
+ }
762
+ }
763
+ function safeApplyErrorAttributes(span, err) {
764
+ try {
765
+ applyErrorAttributes(span, err);
766
+ } catch (error) {
767
+ logger.debug(
768
+ `Brizz MCP: failed to apply error attributes: ${String(error)}`
769
+ );
770
+ }
771
+ }
772
+ function safeEnd(span) {
773
+ try {
774
+ span.end();
775
+ } catch (error) {
776
+ logger.debug(`Brizz MCP: failed to end span: ${String(error)}`);
777
+ }
778
+ }
779
+ var import_api6, PATCHED_FLAG;
780
+ var init_protocol = __esm({
781
+ "src/internal/instrumentation/mcp/patches/protocol.ts"() {
782
+ "use strict";
783
+ import_api6 = require("@opentelemetry/api");
784
+ init_logger();
785
+ init_schemas();
786
+ init_semantic_conventions2();
787
+ init_session();
788
+ init_attributes();
789
+ PATCHED_FLAG = /* @__PURE__ */ Symbol("brizz.mcp.protocol-patched");
790
+ }
791
+ });
792
+
793
+ // src/internal/version.ts
794
+ function getSDKVersion() {
795
+ return "0.1.25";
796
+ }
797
+ var init_version = __esm({
798
+ "src/internal/version.ts"() {
799
+ "use strict";
800
+ }
801
+ });
802
+
803
+ // src/internal/instrumentation/mcp/version.ts
804
+ var INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION;
805
+ var init_version2 = __esm({
806
+ "src/internal/instrumentation/mcp/version.ts"() {
807
+ "use strict";
808
+ init_version();
809
+ INSTRUMENTATION_NAME = "@brizz/sdk/mcp";
810
+ INSTRUMENTATION_VERSION = getSDKVersion();
811
+ }
812
+ });
813
+
814
+ // src/internal/instrumentation/mcp/instrumentation.ts
815
+ function isMCPInstrumentation(value) {
816
+ return !!value && typeof value === "object" && typeof value.instrumentationName === "string";
817
+ }
818
+ var import_openinference_instrumentation_mcp, import_api7, import_instrumentation, PROTOCOL_MODULE_NAME, PROTOCOL_SUPPORTED_VERSIONS, MCPInstrumentation;
819
+ var init_instrumentation = __esm({
820
+ "src/internal/instrumentation/mcp/instrumentation.ts"() {
821
+ "use strict";
822
+ import_openinference_instrumentation_mcp = require("@arizeai/openinference-instrumentation-mcp");
823
+ import_api7 = require("@opentelemetry/api");
824
+ import_instrumentation = require("@opentelemetry/instrumentation");
825
+ init_logger();
826
+ init_protocol();
827
+ init_version2();
828
+ PROTOCOL_MODULE_NAME = "@modelcontextprotocol/sdk/shared/protocol.js";
829
+ PROTOCOL_SUPPORTED_VERSIONS = [">=1.0.0 <2"];
830
+ MCPInstrumentation = class extends import_openinference_instrumentation_mcp.MCPInstrumentation {
831
+ /**
832
+ * Dedicated Brizz-named tracer for our SERVER + CLIENT spans.
833
+ *
834
+ * Why a separate tracer from the parent class's one: Arize's inherited
835
+ * transport patches don't emit spans (they only inject propagation
836
+ * headers), so using our own tracer here keeps Brizz spans attributed to
837
+ * `@brizz/sdk/mcp` in the dashboard. The parent's `tracer` is a
838
+ * `protected get` (no setter), so fighting it with assignment is the
839
+ * wrong tool.
840
+ */
841
+ brizzTracer;
842
+ constructor(_config) {
843
+ super({ instrumentationConfig: _config?.instrumentationConfig });
844
+ this.brizzTracer = import_api7.trace.getTracer(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION);
845
+ }
846
+ /**
847
+ * Extend `super.init()` with our protocol-layer module definition.
848
+ *
849
+ * Arize's `init()` returns definitions for the six transport modules
850
+ * (SSE client/server, stdio client/server, streamable-HTTP client/server)
851
+ * whose `send`/`start` methods get patched for W3C trace-context
852
+ * injection. We append one more: `@modelcontextprotocol/sdk/shared/protocol.js`
853
+ * where our patches open SERVER/CLIENT spans around the handler + outgoing
854
+ * request. If `super.init()` throws (unlikely but possible across Arize
855
+ * versions), we gracefully degrade to protocol-only instrumentation.
856
+ *
857
+ * The cast at the end satisfies the parent's strongly-typed generic
858
+ * without leaking the cast into call sites.
859
+ */
860
+ init() {
861
+ let base;
862
+ try {
863
+ base = super.init() ?? [];
864
+ } catch (error) {
865
+ logger.warn(
866
+ `Brizz MCP: base Arize init() failed \u2014 transport context propagation disabled: ${String(error)}`
867
+ );
868
+ base = [];
869
+ }
870
+ const baseArr = Array.isArray(base) ? base : [base];
871
+ const brizzDef = new import_instrumentation.InstrumentationNodeModuleDefinition(
872
+ PROTOCOL_MODULE_NAME,
873
+ PROTOCOL_SUPPORTED_VERSIONS,
874
+ (module2) => {
875
+ this.patchProtocolModule(module2);
876
+ return module2;
877
+ },
878
+ (module2) => {
879
+ this.unpatchProtocolModule(module2);
880
+ return module2;
881
+ }
882
+ );
883
+ return [...baseArr, brizzDef];
884
+ }
885
+ /**
886
+ * Manually instrument MCP modules for Next.js/Webpack where the
887
+ * auto-instrumentation module-load hook doesn't fire.
888
+ *
889
+ * Forwards the six transport module fields to the inherited Arize
890
+ * `manuallyInstrument(...)` (context propagation) and applies our
891
+ * protocol patch if `protocolModule` is provided (SERVER/CLIENT spans).
892
+ * Both legs are try/catch-guarded — a failure in one shouldn't prevent
893
+ * the other from taking effect.
894
+ */
895
+ manuallyInstrument(modules) {
896
+ const {
897
+ clientSSEModule,
898
+ serverSSEModule,
899
+ clientStdioModule,
900
+ serverStdioModule,
901
+ clientStreamableHTTPModule,
902
+ serverStreamableHTTPModule,
903
+ protocolModule
904
+ } = modules;
905
+ try {
906
+ super.manuallyInstrument({
907
+ clientSSEModule,
908
+ serverSSEModule,
909
+ clientStdioModule,
910
+ serverStdioModule,
911
+ clientStreamableHTTPModule,
912
+ serverStreamableHTTPModule
913
+ });
914
+ } catch (error) {
915
+ logger.warn(`Brizz MCP: Arize manuallyInstrument(...) failed: ${String(error)}`);
916
+ }
917
+ if (protocolModule) {
918
+ try {
919
+ this.patchProtocolModule(protocolModule);
920
+ } catch (error) {
921
+ logger.warn(
922
+ `Brizz MCP: failed to manually patch Protocol module: ${String(error)}`
923
+ );
924
+ }
925
+ }
926
+ }
927
+ /**
928
+ * Apply the SERVER + CLIENT patch to a loaded `protocol.js` module. Shared
929
+ * by both the automatic module-load callback in `init()` and the manual
930
+ * `manuallyInstrument(...)` path above so there's exactly one place that
931
+ * calls `patchProtocolPrototype`.
932
+ */
933
+ patchProtocolModule(module2) {
934
+ const proto = module2?.Protocol?.prototype;
935
+ if (!proto) {
936
+ logger.debug(
937
+ "Brizz MCP: module does not expose Protocol.prototype \u2014 skipping protocol patches"
938
+ );
939
+ return;
940
+ }
941
+ const ok = patchProtocolPrototype(proto, this.brizzTracer);
942
+ if (ok) {
943
+ logger.debug("Brizz MCP: patched Protocol.prototype for SERVER+CLIENT spans");
944
+ }
945
+ }
946
+ /**
947
+ * Unpatch is intentionally a no-op.
948
+ *
949
+ * `patchProtocolPrototype` wraps methods in place and sets a PATCHED_FLAG
950
+ * Symbol on the prototype to prevent double-patching. Restoring the
951
+ * originals would require us to hold references across module unloads,
952
+ * which isn't a pattern we need — instrumentation rarely gets torn down
953
+ * at runtime, and a process reload is the canonical way to detach.
954
+ */
955
+ unpatchProtocolModule(_module) {
956
+ logger.debug(
957
+ "Brizz MCP: unpatch is a no-op \u2014 reload the process to cleanly detach"
958
+ );
959
+ }
960
+ };
961
+ }
962
+ });
963
+
964
+ // src/internal/instrumentation/mcp/index.ts
965
+ var mcp_exports = {};
966
+ __export(mcp_exports, {
967
+ MCPInstrumentation: () => MCPInstrumentation,
968
+ isMCPInstrumentation: () => isMCPInstrumentation
969
+ });
970
+ var init_mcp = __esm({
971
+ "src/internal/instrumentation/mcp/index.ts"() {
972
+ "use strict";
973
+ init_instrumentation();
974
+ }
975
+ });
29
976
 
30
977
  // src/index.ts
31
978
  var src_exports = {};
@@ -50,6 +997,7 @@ __export(src_exports, {
50
997
  logger: () => logger,
51
998
  maskAttributes: () => maskAttributes,
52
999
  maskValue: () => maskValue,
1000
+ setCurrentSpanCustomProperties: () => setCurrentSpanCustomProperties,
53
1001
  setLogLevel: () => setLogLevel,
54
1002
  startSession: () => startSession,
55
1003
  startSessionTitle: () => startSessionTitle,
@@ -60,7 +1008,7 @@ module.exports = __toCommonJS(src_exports);
60
1008
 
61
1009
  // src/internal/instrumentation/auto-init.ts
62
1010
  var import_auto_instrumentations_node = require("@opentelemetry/auto-instrumentations-node");
63
- var import_instrumentation = require("@opentelemetry/instrumentation");
1011
+ var import_instrumentation3 = require("@opentelemetry/instrumentation");
64
1012
  var import_instrumentation_anthropic = require("@traceloop/instrumentation-anthropic");
65
1013
  var import_instrumentation_bedrock = require("@traceloop/instrumentation-bedrock");
66
1014
  var import_instrumentation_chromadb = require("@traceloop/instrumentation-chromadb");
@@ -71,152 +1019,7 @@ var import_instrumentation_pinecone = require("@traceloop/instrumentation-pineco
71
1019
  var import_instrumentation_qdrant = require("@traceloop/instrumentation-qdrant");
72
1020
  var import_instrumentation_together = require("@traceloop/instrumentation-together");
73
1021
  var import_instrumentation_vertexai = require("@traceloop/instrumentation-vertexai");
74
-
75
- // src/internal/logger.ts
76
- var import_api = require("@opentelemetry/api");
77
- var import_pino = __toESM(require("pino"), 1);
78
- var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
79
- LogLevel2[LogLevel2["NONE"] = 0] = "NONE";
80
- LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
81
- LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
82
- LogLevel2[LogLevel2["INFO"] = 3] = "INFO";
83
- LogLevel2[LogLevel2["DEBUG"] = 4] = "DEBUG";
84
- return LogLevel2;
85
- })(LogLevel || {});
86
- var DEFAULT_LOG_LEVEL = 2 /* WARN */;
87
- var PinoLogger = class {
88
- _level = DEFAULT_LOG_LEVEL;
89
- _pinoLogger = null;
90
- constructor() {
91
- const envLevel = this.getLogLevelFromEnv();
92
- this._level = envLevel;
93
- }
94
- /**
95
- * Lazy initialization of Pino logger to ensure it's created AFTER Jest spies
96
- * are set up during tests. This prevents the pino-pretty transport from
97
- * bypassing stdout/stderr spies.
98
- */
99
- ensurePinoLogger() {
100
- if (!this._pinoLogger) {
101
- this._pinoLogger = (0, import_pino.default)({
102
- name: "Brizz",
103
- level: this.logLevelToPino(this._level),
104
- // Disable transport in test environment to allow proper spy capture
105
- transport: this.isProduction() || this.isTest() ? void 0 : {
106
- target: "pino-pretty",
107
- options: {
108
- singleLine: true,
109
- colorize: true,
110
- translateTime: "HH:MM:ss",
111
- ignore: "pid,hostname",
112
- messageFormat: "[{name}] {msg}"
113
- }
114
- }
115
- });
116
- }
117
- return this._pinoLogger;
118
- }
119
- isProduction() {
120
- return process.env["NODE_ENV"] === "production";
121
- }
122
- isTest() {
123
- return process.env["NODE_ENV"] === "test";
124
- }
125
- getLogLevelFromEnv() {
126
- const envLevel = process.env["BRIZZ_LOG_LEVEL"];
127
- return envLevel ? parseLogLevel(envLevel) : DEFAULT_LOG_LEVEL;
128
- }
129
- logLevelToPino(level) {
130
- switch (level) {
131
- case 4 /* DEBUG */:
132
- return "debug";
133
- case 3 /* INFO */:
134
- return "info";
135
- case 2 /* WARN */:
136
- return "warn";
137
- case 1 /* ERROR */:
138
- return "error";
139
- default:
140
- return "silent";
141
- }
142
- }
143
- formatMeta(meta) {
144
- if (meta.length === 0) {
145
- return {};
146
- }
147
- if (meta.length === 1 && typeof meta[0] === "object" && meta[0] !== null) {
148
- return meta[0];
149
- }
150
- return { metadata: meta };
151
- }
152
- setLevel(level) {
153
- this._level = level;
154
- if (this._pinoLogger) {
155
- this._pinoLogger.level = this.logLevelToPino(level);
156
- }
157
- }
158
- getLevel() {
159
- return this._level;
160
- }
161
- debug = (msg, ...meta) => {
162
- if (this._level >= 4 /* DEBUG */) {
163
- this.ensurePinoLogger().debug(this.formatMeta(meta), msg);
164
- }
165
- };
166
- info = (msg, ...meta) => {
167
- if (this._level >= 3 /* INFO */) {
168
- this.ensurePinoLogger().info(this.formatMeta(meta), msg);
169
- }
170
- };
171
- warn = (msg, ...meta) => {
172
- if (this._level >= 2 /* WARN */) {
173
- this.ensurePinoLogger().warn(this.formatMeta(meta), msg);
174
- }
175
- };
176
- error = (msg, ...meta) => {
177
- if (this._level >= 1 /* ERROR */) {
178
- this.ensurePinoLogger().error(this.formatMeta(meta), msg);
179
- }
180
- };
181
- };
182
- function parseLogLevel(level) {
183
- if (!level) {
184
- return DEFAULT_LOG_LEVEL;
185
- }
186
- const normalizedLevel = level.toLowerCase().trim();
187
- switch (normalizedLevel) {
188
- case "debug":
189
- return 4 /* DEBUG */;
190
- case "info":
191
- return 3 /* INFO */;
192
- case "warn":
193
- case "warning":
194
- return 2 /* WARN */;
195
- case "error":
196
- return 1 /* ERROR */;
197
- case "none":
198
- case "off":
199
- case "silent":
200
- return 0 /* NONE */;
201
- default: {
202
- const numLevel = Number.parseInt(normalizedLevel, 10);
203
- if (!Number.isNaN(numLevel) && numLevel >= 0 && numLevel <= 4) {
204
- return numLevel;
205
- }
206
- return DEFAULT_LOG_LEVEL;
207
- }
208
- }
209
- }
210
- var logger = new PinoLogger();
211
- function setLogLevel(level) {
212
- const resolvedLevel = typeof level === "string" ? parseLogLevel(level) : level;
213
- logger.setLevel(resolvedLevel);
214
- }
215
- function getLogLevel() {
216
- return logger.getLevel();
217
- }
218
-
219
- // src/internal/instrumentation/auto-init.ts
1022
+ init_logger();
220
1023
  var autoInstrumentationsLoaded = false;
221
1024
  var exceptionLogger = (error) => {
222
1025
  logger.error(`Exception in instrumentation: ${String(error)}`);
@@ -231,7 +1034,7 @@ function loadNodeAutoInstrumentations() {
231
1034
  // Brizz backend parser with no payload to read.
232
1035
  "@opentelemetry/instrumentation-openai": { enabled: false }
233
1036
  });
234
- (0, import_instrumentation.registerInstrumentations)({ instrumentations: nodeInstrumentations });
1037
+ (0, import_instrumentation3.registerInstrumentations)({ instrumentations: nodeInstrumentations });
235
1038
  return nodeInstrumentations;
236
1039
  } catch (error) {
237
1040
  logger.error(`Failed to load Node.js auto-instrumentations: ${String(error)}`);
@@ -262,13 +1065,27 @@ function loadGenAIInstrumentations() {
262
1065
  }
263
1066
  }
264
1067
  try {
265
- (0, import_instrumentation.registerInstrumentations)({ instrumentations });
1068
+ (0, import_instrumentation3.registerInstrumentations)({ instrumentations });
266
1069
  logger.info(`Auto-registered ${instrumentations.length} GenAI instrumentations`);
267
1070
  } catch (error) {
268
1071
  logger.error(`Failed to register GenAI instrumentations: ${String(error)}`);
269
1072
  }
270
1073
  return instrumentations;
271
1074
  }
1075
+ function loadMCPInstrumentation() {
1076
+ void (async () => {
1077
+ try {
1078
+ const { MCPInstrumentation: MCPInstrumentation2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
1079
+ const mcp = new MCPInstrumentation2({ exceptionLogger });
1080
+ (0, import_instrumentation3.registerInstrumentations)({ instrumentations: [mcp] });
1081
+ logger.debug("Auto-loaded MCP instrumentation");
1082
+ } catch (error) {
1083
+ logger.debug(
1084
+ `MCP instrumentation not loaded (install @modelcontextprotocol/sdk and @arizeai/openinference-instrumentation-mcp if you want MCP support): ${String(error)}`
1085
+ );
1086
+ }
1087
+ })();
1088
+ }
272
1089
  function autoInitializeInstrumentations() {
273
1090
  if (autoInstrumentationsLoaded) {
274
1091
  return;
@@ -276,6 +1093,7 @@ function autoInitializeInstrumentations() {
276
1093
  try {
277
1094
  const nodeInstrumentations = loadNodeAutoInstrumentations();
278
1095
  const genAIInstrumentations = loadGenAIInstrumentations();
1096
+ loadMCPInstrumentation();
279
1097
  autoInstrumentationsLoaded = true;
280
1098
  logger.info(
281
1099
  `Auto-initialization complete: ${nodeInstrumentations.length} node + ${genAIInstrumentations.length} GenAI instrumentations`
@@ -291,7 +1109,40 @@ autoInitializeInstrumentations();
291
1109
  var import_resources3 = require("@opentelemetry/resources");
292
1110
  var import_sdk_node = require("@opentelemetry/sdk-node");
293
1111
 
1112
+ // src/internal/dsn.ts
1113
+ var PLACEHOLDER_SERVICE = "<service-name>";
1114
+ var SERVICE_NAME_HEADER = "X-Brizz-Service-Name";
1115
+ function parseDSN(dsn) {
1116
+ let parsed;
1117
+ try {
1118
+ parsed = new globalThis.URL(dsn);
1119
+ } catch {
1120
+ return null;
1121
+ }
1122
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || !parsed.username || !parsed.host) {
1123
+ return null;
1124
+ }
1125
+ const scheme = parsed.protocol === "https:" ? "https" : "http";
1126
+ let service;
1127
+ try {
1128
+ service = decodeURIComponent(parsed.pathname.replace(/^\//, ""));
1129
+ } catch {
1130
+ return null;
1131
+ }
1132
+ if (service === "" || service === PLACEHOLDER_SERVICE) {
1133
+ return null;
1134
+ }
1135
+ return {
1136
+ scheme,
1137
+ host: parsed.host,
1138
+ bearer: decodeURIComponent(parsed.username),
1139
+ service,
1140
+ baseUrl: `${scheme}://${parsed.host}`
1141
+ };
1142
+ }
1143
+
294
1144
  // src/internal/config.ts
1145
+ init_logger();
295
1146
  function resolveConfig(options) {
296
1147
  const envLogLevel = process.env["BRIZZ_LOG_LEVEL"] || options.logLevel?.toString() || DEFAULT_LOG_LEVEL.toString();
297
1148
  let resolvedLogLevel;
@@ -317,6 +1168,7 @@ function resolveConfig(options) {
317
1168
  appName: options.appName,
318
1169
  baseUrl: options.baseUrl,
319
1170
  hasApiKey: !!options.apiKey,
1171
+ dsnProvided: !!(process.env["BRIZZ_DSN"] || options.dsn),
320
1172
  disableBatch: options.disableBatch,
321
1173
  logLevel: resolvedLogLevel,
322
1174
  headersCount: Object.keys(options.headers || {}).length,
@@ -344,7 +1196,42 @@ function resolveConfig(options) {
344
1196
  logLevel: resolvedLogLevel,
345
1197
  masking: resolvedMasking
346
1198
  };
347
- if (resolvedConfig.apiKey) {
1199
+ const dsnInput = process.env["BRIZZ_DSN"] || options.dsn;
1200
+ let parsedDSN = null;
1201
+ if (dsnInput) {
1202
+ const kwargConflicts = [];
1203
+ if (options.apiKey !== void 0) {
1204
+ kwargConflicts.push("apiKey");
1205
+ }
1206
+ if (options.baseUrl !== void 0) {
1207
+ kwargConflicts.push("baseUrl");
1208
+ }
1209
+ if (options.appName !== void 0) {
1210
+ kwargConflicts.push("appName");
1211
+ }
1212
+ if (kwargConflicts.length > 0) {
1213
+ throw new Error(
1214
+ `dsn cannot be combined with kwargs ${kwargConflicts.join(", ")}. The DSN bundles bearer, gateway URL, and service name \u2014 choose one configuration style.`
1215
+ );
1216
+ }
1217
+ const envConflicts = ["BRIZZ_API_KEY", "BRIZZ_BASE_URL", "BRIZZ_APP_NAME"].filter(
1218
+ (name) => process.env[name] !== void 0
1219
+ );
1220
+ if (envConflicts.length > 0) {
1221
+ logger.warn(
1222
+ `Ignoring ${envConflicts.join(", ")} \u2014 dsn / BRIZZ_DSN takes precedence.`
1223
+ );
1224
+ }
1225
+ resolvedConfig.apiKey = void 0;
1226
+ resolvedConfig.baseUrl = "https://telemetry.brizz.dev";
1227
+ resolvedConfig.appName = "unknown-app";
1228
+ parsedDSN = parseDSN(dsnInput);
1229
+ if (parsedDSN) {
1230
+ resolvedConfig.appName = parsedDSN.service;
1231
+ resolvedConfig.baseUrl = parsedDSN.baseUrl;
1232
+ resolvedConfig.apiKey = parsedDSN.bearer;
1233
+ }
1234
+ } else if (resolvedConfig.apiKey) {
348
1235
  resolvedConfig.headers["Authorization"] = `Bearer ${resolvedConfig.apiKey}`;
349
1236
  }
350
1237
  if (process.env["BRIZZ_HEADERS"]) {
@@ -359,14 +1246,28 @@ function resolveConfig(options) {
359
1246
  throw new Error("Invalid JSON in BRIZZ_HEADERS environment variable", { cause: error });
360
1247
  }
361
1248
  }
1249
+ if (dsnInput) {
1250
+ const authHeaderKeys = /* @__PURE__ */ new Set(["authorization", SERVICE_NAME_HEADER.toLowerCase()]);
1251
+ resolvedConfig.headers = Object.fromEntries(
1252
+ Object.entries(resolvedConfig.headers).filter(
1253
+ ([key]) => !authHeaderKeys.has(key.toLowerCase())
1254
+ )
1255
+ );
1256
+ if (parsedDSN) {
1257
+ resolvedConfig.headers["Authorization"] = `Bearer ${parsedDSN.bearer}`;
1258
+ resolvedConfig.headers[SERVICE_NAME_HEADER] = parsedDSN.service;
1259
+ }
1260
+ }
362
1261
  logger.debug("Configuration resolved with environment variables", {
363
1262
  appName: resolvedConfig.appName,
364
1263
  baseUrl: resolvedConfig.baseUrl,
365
1264
  hasApiKey: !!resolvedConfig.apiKey,
1265
+ dsnProvided: !!dsnInput,
366
1266
  disableBatch: resolvedConfig.disableBatch,
367
1267
  envOverrides: {
368
1268
  hasEnvApiKey: !!process.env["BRIZZ_API_KEY"],
369
1269
  hasEnvBaseUrl: !!process.env["BRIZZ_BASE_URL"],
1270
+ hasEnvDsn: !!process.env["BRIZZ_DSN"],
370
1271
  hasEnvBatch: !!process.env["BRIZZ_DISABLE_BATCH"],
371
1272
  hasEnvHeaders: !!process.env["BRIZZ_HEADERS"]
372
1273
  }
@@ -390,6 +1291,8 @@ var import_instrumentation_pinecone2 = require("@traceloop/instrumentation-pinec
390
1291
  var import_instrumentation_qdrant2 = require("@traceloop/instrumentation-qdrant");
391
1292
  var import_instrumentation_together2 = require("@traceloop/instrumentation-together");
392
1293
  var import_instrumentation_vertexai2 = require("@traceloop/instrumentation-vertexai");
1294
+ init_logger();
1295
+ init_mcp();
393
1296
  var InstrumentationRegistry = class _InstrumentationRegistry {
394
1297
  static instance;
395
1298
  manualModules = null;
@@ -494,6 +1397,14 @@ var InstrumentationRegistry = class _InstrumentationRegistry {
494
1397
  }
495
1398
  })();
496
1399
  }
1400
+ if (this.manualModules?.mcp) {
1401
+ try {
1402
+ new MCPInstrumentation({ exceptionLogger: exceptionLogger2 }).manuallyInstrument(this.manualModules.mcp);
1403
+ logger.debug("Manual instrumentation enabled for MCP");
1404
+ } catch (error) {
1405
+ logger.error(`Failed to apply MCP instrumentation: ${String(error)}`);
1406
+ }
1407
+ }
497
1408
  }
498
1409
  };
499
1410
 
@@ -502,33 +1413,21 @@ var import_api_logs = require("@opentelemetry/api-logs");
502
1413
  var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
503
1414
  var import_resources = require("@opentelemetry/resources");
504
1415
  var import_sdk_logs2 = require("@opentelemetry/sdk-logs");
505
-
506
- // src/internal/version.ts
507
- function getSDKVersion() {
508
- return "0.1.21";
509
- }
1416
+ init_logger();
1417
+ init_version();
510
1418
 
511
1419
  // src/internal/log/processors/log-processor.ts
512
- var import_api3 = require("@opentelemetry/api");
1420
+ var import_api8 = require("@opentelemetry/api");
513
1421
  var import_sdk_logs = require("@opentelemetry/sdk-logs");
1422
+ init_logger();
514
1423
 
515
1424
  // src/internal/masking/patterns.ts
516
1425
  var DEFAULT_PII_PATTERNS = [
517
- // Email addresses
518
- {
519
- name: "email_addresses",
520
- pattern: String.raw`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`
521
- },
522
1426
  // Phone numbers (US format)
523
1427
  {
524
1428
  name: "us_phone_numbers",
525
1429
  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]|$)`
526
1430
  },
527
- // Social Security Numbers
528
- {
529
- name: "ssn",
530
- pattern: String.raw`\b(?!000|666|9\d{2})\d{3}[-\s]?(?!00)\d{2}[-\s]?(?!0000)\d{4}\b`
531
- },
532
1431
  // Credit card numbers
533
1432
  {
534
1433
  name: "credit_cards",
@@ -552,19 +1451,11 @@ var DEFAULT_PII_PATTERNS = [
552
1451
  name: "openai_keys",
553
1452
  pattern: String.raw`\bsk[-_][a-zA-Z0-9]{20,}\b`
554
1453
  },
555
- {
556
- name: "base64_secrets",
557
- pattern: String.raw`\b[A-Za-z0-9+/]{64,}={0,2}\b`
558
- },
559
1454
  // AWS Keys
560
1455
  {
561
1456
  name: "aws_access_keys",
562
1457
  pattern: String.raw`\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b`
563
1458
  },
564
- {
565
- name: "aws_secret_keys",
566
- 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`
567
- },
568
1459
  // GitHub tokens
569
1460
  {
570
1461
  name: "github_tokens",
@@ -595,11 +1486,6 @@ var DEFAULT_PII_PATTERNS = [
595
1486
  name: "ipv6_addresses",
596
1487
  pattern: String.raw`\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b`
597
1488
  },
598
- // Medical records
599
- {
600
- name: "medical_record_numbers",
601
- pattern: String.raw`\b(?:[Mm][Rr][Nn])[-\s]?\d{6,10}\b`
602
- },
603
1489
  // Bitcoin addresses
604
1490
  {
605
1491
  name: "bitcoin_addresses",
@@ -610,11 +1496,6 @@ var DEFAULT_PII_PATTERNS = [
610
1496
  name: "ethereum_addresses",
611
1497
  pattern: String.raw`\b0x[a-fA-F0-9]{40}(?![a-fA-F0-9])\b`
612
1498
  },
613
- // UUIDs
614
- {
615
- name: "uuids",
616
- 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`
617
- },
618
1499
  // Database connection strings
619
1500
  {
620
1501
  name: "database_connections",
@@ -633,90 +1514,6 @@ var DEFAULT_PII_PATTERNS = [
633
1514
  name: "certificates",
634
1515
  pattern: "-----BEGIN CERTIFICATE-----"
635
1516
  },
636
- // Date of birth patterns
637
- {
638
- name: "date_of_birth_us",
639
- pattern: String.raw`\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])[-/](?:19|20)\\d{2}\b`
640
- },
641
- {
642
- name: "date_of_birth_iso",
643
- pattern: String.raw`\b(?:19|20)\\d{2}[-/](?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])\b`
644
- },
645
- // US Identification Numbers
646
- {
647
- name: "us_passport_numbers",
648
- pattern: String.raw`\b[A-Z]?\\d{6,9}\b`
649
- },
650
- {
651
- name: "drivers_license",
652
- 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`
653
- },
654
- {
655
- name: "bank_account_numbers",
656
- pattern: String.raw`\b\\d{10,17}\b`
657
- },
658
- {
659
- name: "aba_routing_numbers",
660
- 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`
661
- },
662
- {
663
- name: "health_insurance_numbers",
664
- pattern: String.raw`\b\\d{10}[A-Z]\b`
665
- },
666
- {
667
- name: "employee_ids",
668
- pattern: String.raw`\b(?:[Ee][Mm][Pp]|[Ee][Mm][Pp][Ll][Oo][Yy][Ee][Ee]|[Ee])[-\s]?\\d{5,8}\b`
669
- },
670
- {
671
- name: "tax_ein",
672
- pattern: String.raw`\b\\d{2}-\\d{7}\b`
673
- },
674
- {
675
- name: "medicare_beneficiary_id",
676
- 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`
677
- },
678
- {
679
- name: "national_provider_id",
680
- pattern: String.raw`\b1\\d{9}\b`
681
- },
682
- {
683
- name: "dea_numbers",
684
- pattern: String.raw`\b[A-Z]{2}\\d{7}\b`
685
- },
686
- {
687
- name: "itin",
688
- pattern: String.raw`\b9\\d{2}(?:[ \\-]?)[7,8]\\d(?:[ \\-]?)\\d{4}\b`
689
- },
690
- // Vehicle and Location
691
- {
692
- name: "vin_numbers",
693
- pattern: String.raw`\b[A-HJ-NPR-Z0-9]{17}\b`
694
- },
695
- {
696
- name: "coordinates",
697
- pattern: String.raw`\b[-+]?(?:[0-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?),\\s*[-+]?(?:1[0-7]\\d(?:\\.\\d+)?|180(?:\\.0+)?|[0-9]?\\d(?:\\.\\d+)?)\b`
698
- },
699
- {
700
- name: "us_license_plates",
701
- 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`
702
- },
703
- {
704
- name: "us_zip_codes",
705
- pattern: String.raw`\b(\\d{5}-\\d{4}|\\d{5})\b`
706
- },
707
- {
708
- name: "us_street_addresses",
709
- 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`
710
- },
711
- // International Banking
712
- {
713
- name: "iban",
714
- pattern: String.raw`\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}([A-Z0-9]?){0,16}\b`
715
- },
716
- {
717
- name: "swift_bic",
718
- pattern: String.raw`\b[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?\b`
719
- },
720
1517
  // Additional API Keys and Tokens
721
1518
  {
722
1519
  name: "google_oauth",
@@ -779,73 +1576,6 @@ var DEFAULT_PII_PATTERNS = [
779
1576
  name: "putty_ssh_keys",
780
1577
  pattern: String.raw`PuTTY-User-Key-File-2: ssh-(?:rsa|dss)\s*Encryption: none(?:.|\s?)*?Private-MAC:`
781
1578
  },
782
- // International Phone Numbers
783
- {
784
- name: "france_phone_numbers",
785
- pattern: String.raw`\b([0O]?[1lI][1lI])?[3E][3E][0O]?[\\dOIlZEASB]{9}\b`
786
- },
787
- {
788
- name: "german_phone_numbers",
789
- pattern: String.raw`\b[\d\w]\d{2}[\d\w]{6}\d[\d\w]\b`
790
- },
791
- {
792
- name: "uk_phone_numbers",
793
- pattern: String.raw`\b([0O]?[1lI][1lI])?[4A][4A][\\dOIlZEASB]{10,11}\b`
794
- },
795
- // International IDs
796
- {
797
- name: "uk_drivers_license",
798
- pattern: String.raw`\b[A-Z]{5}\d{6}[A-Z]{2}\d{1}[A-Z]{2}\b`
799
- },
800
- {
801
- name: "uk_passport",
802
- pattern: String.raw`\b\\d{10}GB[RP]\\d{7}[UMF]{1}\\d{9}\b`
803
- },
804
- {
805
- name: "argentina_dni",
806
- pattern: String.raw`\b\\d{2}\\.\\d{3}\\.\\d{3}\b`
807
- },
808
- {
809
- name: "australia_tfn",
810
- pattern: String.raw`\b[Tt][Ff][Nn](:|:\\s|\\s|)(\\d{8,9})\b`
811
- },
812
- {
813
- name: "canada_passport",
814
- pattern: String.raw`\b[\\w]{2}[\\d]{6}\b`
815
- },
816
- {
817
- name: "croatia_vat",
818
- pattern: String.raw`\bHR\\d{11}\b`
819
- },
820
- {
821
- name: "czech_vat",
822
- pattern: String.raw`\bCZ\\d{8,10}\b`
823
- },
824
- {
825
- name: "denmark_personal_id",
826
- pattern: String.raw`\b(?:\\d{10}|\\d{6}[-\\s]\\d{4})\b`
827
- },
828
- {
829
- name: "france_national_id",
830
- pattern: String.raw`\b\\d{12}\b`
831
- },
832
- {
833
- name: "france_ssn",
834
- pattern: String.raw`\b(?:\\d{13}|\\d{13}\\s\\d{2})\b`
835
- },
836
- {
837
- name: "france_passport",
838
- pattern: String.raw`\b\\d{2}11\\d{5}\b`
839
- },
840
- {
841
- name: "california_drivers_license",
842
- pattern: String.raw`\b[A-Z]{1}\\d{7}\b`
843
- },
844
- // Medical and Healthcare
845
- {
846
- name: "hipaa_ndc",
847
- pattern: String.raw`\b\\d{4,5}-\\d{3,4}-\\d{1,2}\b`
848
- },
849
1579
  // Security and Network
850
1580
  {
851
1581
  name: "cve_numbers",
@@ -879,48 +1609,11 @@ var DEFAULT_PII_PATTERNS = [
879
1609
  {
880
1610
  name: "discover_cards",
881
1611
  pattern: String.raw`\b65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}\b`
882
- },
883
- {
884
- name: "enhanced_credit_cards",
885
- 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`
886
- },
887
- // Bank Routing Numbers (US specific)
888
- {
889
- name: "bbva_routing_ca",
890
- pattern: String.raw`\\b321170538\\b`
891
- },
892
- {
893
- name: "boa_routing_ca",
894
- pattern: String.raw`\\b(?:121|026)00(?:0|9)(?:358|593)\\b`
895
- },
896
- {
897
- name: "chase_routing_ca",
898
- pattern: String.raw`\\b322271627\\b`
899
- },
900
- {
901
- name: "citibank_routing_ca",
902
- pattern: String.raw`\\b32(?:11|22)71(?:18|72)4\\b`
903
- },
904
- {
905
- name: "usbank_routing_ca",
906
- pattern: String.raw`\\b12(?:1122676|2235821)\\b`
907
- },
908
- {
909
- name: "united_bank_routing_ca",
910
- pattern: String.raw`\\b122243350\\b`
911
- },
912
- {
913
- name: "wells_fargo_routing_ca",
914
- pattern: String.raw`\\b121042882\\b`
915
- },
916
- // Unrealistic alphanumeric identifiers
917
- {
918
- name: "generic_non_usual",
919
- pattern: String.raw`(?:^|\s)(?=[A-Za-z0-9_\)\*\=@]*[A-Za-z])(?=[A-Za-z0-9_\)\*\=@]*[0-9])([A-Za-z0-9_\)\*\=@]{5,})(?=\s|$)`
920
1612
  }
921
1613
  ];
922
1614
 
923
1615
  // src/internal/masking/utils.ts
1616
+ init_logger();
924
1617
  function isValidPatternName(name) {
925
1618
  return /^[a-zA-Z0-9_]+$/.test(name);
926
1619
  }
@@ -1136,23 +1829,8 @@ function maskAttributes(attributes, rules, outputOriginalValue = false) {
1136
1829
  return maskedAttributes;
1137
1830
  }
1138
1831
 
1139
- // src/internal/semantic-conventions.ts
1140
- var import_api2 = require("@opentelemetry/api");
1141
- var BRIZZ = "brizz";
1142
- var PROPERTIES = "properties";
1143
- var SESSION_ID = "session.id";
1144
- var PROPERTIES_CONTEXT_KEY = (0, import_api2.createContextKey)(PROPERTIES);
1145
- var SESSION_OBJECT_CONTEXT_KEY = (0, import_api2.createContextKey)("brizz.session.object");
1146
- var SESSION_INPUT = "brizz.session.input";
1147
- var SESSION_OUTPUT = "brizz.session.output";
1148
- var SESSION_INPUT_CONTEXT = "brizz.session.input.context";
1149
- var SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
1150
- var SESSION_SPAN_NAME = "brizz.start_session";
1151
- var SESSION_TITLE_SPAN_NAME = "brizz.session_title";
1152
- var SESSION_TITLE_GENERATION = "session.title_generation";
1153
- var SESSION_TITLE = "brizz.session.title";
1154
-
1155
1832
  // src/internal/log/processors/log-processor.ts
1833
+ init_semantic_conventions();
1156
1834
  var DEFAULT_LOG_MASKING_RULES = [
1157
1835
  {
1158
1836
  mode: "partial",
@@ -1171,7 +1849,7 @@ var BrizzSimpleLogRecordProcessor = class extends import_sdk_logs.SimpleLogRecor
1171
1849
  if (maskingConfig) {
1172
1850
  maskLog(logRecord, maskingConfig);
1173
1851
  }
1174
- const associationProperties = import_api3.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1852
+ const associationProperties = import_api8.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1175
1853
  if (associationProperties) {
1176
1854
  for (const [key, value] of Object.entries(associationProperties)) {
1177
1855
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1191,7 +1869,7 @@ var BrizzBatchLogRecordProcessor = class extends import_sdk_logs.BatchLogRecordP
1191
1869
  if (maskingConfig) {
1192
1870
  maskLog(logRecord, maskingConfig);
1193
1871
  }
1194
- const associationProperties = import_api3.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1872
+ const associationProperties = import_api8.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1195
1873
  if (associationProperties) {
1196
1874
  for (const [key, value] of Object.entries(associationProperties)) {
1197
1875
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1410,9 +2088,13 @@ function emitEvent(name, attributes, body, severityNumber = import_api_logs.Seve
1410
2088
  return LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
1411
2089
  }
1412
2090
 
2091
+ // src/internal/sdk.ts
2092
+ init_logger();
2093
+
1413
2094
  // src/internal/metric/metrics.ts
1414
2095
  var import_exporter_metrics_otlp_http = require("@opentelemetry/exporter-metrics-otlp-http");
1415
2096
  var import_sdk_metrics = require("@opentelemetry/sdk-metrics");
2097
+ init_logger();
1416
2098
  var MetricsModule = class _MetricsModule {
1417
2099
  static instance = null;
1418
2100
  metricsExporter = null;
@@ -1514,10 +2196,13 @@ function getMetricsReader() {
1514
2196
 
1515
2197
  // src/internal/trace/tracing.ts
1516
2198
  var import_exporter_trace_otlp_proto = require("@opentelemetry/exporter-trace-otlp-proto");
2199
+ init_logger();
1517
2200
 
1518
2201
  // src/internal/trace/exporters/span-exporter.ts
1519
2202
  var import_core = require("@opentelemetry/core");
1520
2203
  var import_resources2 = require("@opentelemetry/resources");
2204
+ init_logger();
2205
+ init_version();
1521
2206
  var BrizzSpanExporter = class {
1522
2207
  _delegate;
1523
2208
  _brizzResource;
@@ -1584,10 +2269,12 @@ var BrizzSpanExporter = class {
1584
2269
  };
1585
2270
 
1586
2271
  // src/internal/trace/processors/span-processor.ts
1587
- var import_api4 = require("@opentelemetry/api");
2272
+ var import_api9 = require("@opentelemetry/api");
1588
2273
  var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
2274
+ init_logger();
2275
+ init_semantic_conventions();
1589
2276
  function applyContextAttributes(span) {
1590
- const sessionProperties = import_api4.context.active().getValue(PROPERTIES_CONTEXT_KEY);
2277
+ const sessionProperties = import_api9.context.active().getValue(PROPERTIES_CONTEXT_KEY);
1591
2278
  if (sessionProperties) {
1592
2279
  for (const [key, value] of Object.entries(sessionProperties)) {
1593
2280
  span.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1597,12 +2284,6 @@ function applyContextAttributes(span) {
1597
2284
  var DEFAULT_MASKING_RULES = [
1598
2285
  {
1599
2286
  mode: "partial",
1600
- attributePattern: "gen_ai.prompt",
1601
- patterns: DEFAULT_PII_PATTERNS
1602
- },
1603
- {
1604
- mode: "partial",
1605
- attributePattern: "gen_ai.completion",
1606
2287
  patterns: DEFAULT_PII_PATTERNS
1607
2288
  }
1608
2289
  ];
@@ -1612,24 +2293,16 @@ var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanPro
1612
2293
  super(spanExporter);
1613
2294
  this.config = config;
1614
2295
  }
1615
- // Will work with the following code:
1616
- // const span = tracer.startSpan('sensitive-operation',{attributes:{
1617
- // 'user.password': 'secret123',
1618
- // 'user.email': 'user@example.com',
1619
- // }});
1620
- //
1621
- // Won't work because onStart is called before attributes are set:
1622
- // span.setAttributes({
1623
- // 'user.password': 'secret123',
1624
- // 'user.email': 'user@example.com'
1625
- // });
1626
2296
  onStart(span, parentContext) {
2297
+ applyContextAttributes(span);
2298
+ super.onStart(span, parentContext);
2299
+ }
2300
+ onEnd(span) {
1627
2301
  const maskingConfig = this.config.masking?.spanMasking;
1628
2302
  if (maskingConfig) {
1629
- maskSpan(span, maskingConfig);
2303
+ maskReadableSpan(span, maskingConfig);
1630
2304
  }
1631
- applyContextAttributes(span);
1632
- super.onStart(span, parentContext);
2305
+ super.onEnd(span);
1633
2306
  }
1634
2307
  };
1635
2308
  var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProcessor {
@@ -1639,39 +2312,39 @@ var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProce
1639
2312
  this.config = config;
1640
2313
  }
1641
2314
  onStart(span, parentContext) {
2315
+ applyContextAttributes(span);
2316
+ super.onStart(span, parentContext);
2317
+ }
2318
+ onEnd(span) {
1642
2319
  const maskingConfig = this.config.masking?.spanMasking;
1643
2320
  if (maskingConfig) {
1644
- maskSpan(span, maskingConfig);
2321
+ maskReadableSpan(span, maskingConfig);
1645
2322
  }
1646
- applyContextAttributes(span);
1647
- super.onStart(span, parentContext);
2323
+ super.onEnd(span);
1648
2324
  }
1649
2325
  };
1650
- function maskSpan(span, config) {
1651
- if (!span.attributes || Object.keys(span.attributes).length === 0) {
1652
- return span;
2326
+ function maskReadableSpan(span, config) {
2327
+ const attrs = span.attributes;
2328
+ if (!attrs || Object.keys(attrs).length === 0) {
2329
+ return;
1653
2330
  }
1654
- let rules = config.rules || [];
2331
+ let rules = config.rules ? [...config.rules] : [];
1655
2332
  if (!config.disableDefaultRules) {
1656
- rules = [...DEFAULT_MASKING_RULES, ...rules];
2333
+ rules = [...rules, ...DEFAULT_MASKING_RULES];
1657
2334
  }
1658
2335
  try {
1659
- const attributesRecord = {};
1660
- for (const [key, value] of Object.entries(span.attributes)) {
1661
- attributesRecord[key] = value;
1662
- }
1663
- const maskedAttributes = maskAttributes(attributesRecord, rules);
1664
- if (maskedAttributes && Object.keys(maskedAttributes).length > 0) {
1665
- const merged = { ...span.attributes };
1666
- for (const [key, value] of Object.entries(maskedAttributes)) {
1667
- merged[key] = value;
2336
+ const input = {};
2337
+ for (const [k, v] of Object.entries(attrs)) {
2338
+ input[k] = v;
2339
+ }
2340
+ const masked = maskAttributes(input, rules);
2341
+ for (const [k, v] of Object.entries(masked ?? {})) {
2342
+ if (attrs[k] !== v) {
2343
+ attrs[k] = v;
1668
2344
  }
1669
- span.setAttributes(merged);
1670
2345
  }
1671
- return span;
1672
2346
  } catch (error) {
1673
- logger.error("Error masking span:", error);
1674
- return span;
2347
+ logger.error("Error masking span", { err: error });
1675
2348
  }
1676
2349
  }
1677
2350
 
@@ -1787,13 +2460,26 @@ function getSpanProcessor() {
1787
2460
  }
1788
2461
 
1789
2462
  // src/internal/trace/session.ts
1790
- var import_api5 = require("@opentelemetry/api");
2463
+ var import_api10 = require("@opentelemetry/api");
2464
+ init_semantic_conventions();
2465
+ function setCurrentSpanCustomProperties(properties) {
2466
+ const current = import_api10.trace.getActiveSpan();
2467
+ if (!current || !current.isRecording()) {
2468
+ return;
2469
+ }
2470
+ for (const [key, value] of Object.entries(properties)) {
2471
+ try {
2472
+ current.setAttribute(`${BRIZZ}.${key}`, value);
2473
+ } catch {
2474
+ }
2475
+ }
2476
+ }
1791
2477
  function callWithProperties(properties, fn, thisArg, ...args) {
1792
- const base = import_api5.context.active();
2478
+ const base = import_api10.context.active();
1793
2479
  const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
1794
2480
  const merged = prev ? { ...prev, ...properties } : properties;
1795
2481
  const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
1796
- return import_api5.context.with(next, fn, thisArg, ...args);
2482
+ return import_api10.context.with(next, fn, thisArg, ...args);
1797
2483
  }
1798
2484
  function withProperties(properties, fn, thisArg) {
1799
2485
  return function wrapped(...args) {
@@ -1835,9 +2521,9 @@ var Session = class {
1835
2521
  * @param text - Text to append (null becomes a null/"hide marker")
1836
2522
  * @param context - Optional per-turn context bag to attach to this turn
1837
2523
  */
1838
- setInput(text, context4) {
2524
+ setInput(text, context6) {
1839
2525
  this.inputs.push(text);
1840
- this.inputContexts.push(context4 ?? {});
2526
+ this.inputContexts.push(context6 ?? {});
1841
2527
  this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
1842
2528
  this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
1843
2529
  }
@@ -1851,9 +2537,9 @@ var Session = class {
1851
2537
  * @param text - Text to append (null becomes a null/"hide marker")
1852
2538
  * @param context - Optional per-turn context bag to attach to this turn
1853
2539
  */
1854
- setOutput(text, context4) {
2540
+ setOutput(text, context6) {
1855
2541
  this.outputs.push(text);
1856
- this.outputContexts.push(context4 ?? {});
2542
+ this.outputContexts.push(context6 ?? {});
1857
2543
  this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
1858
2544
  this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
1859
2545
  }
@@ -1892,12 +2578,12 @@ var SessionTitle = class {
1892
2578
  }
1893
2579
  };
1894
2580
  function getActiveSession() {
1895
- return import_api5.context.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
2581
+ return import_api10.context.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
1896
2582
  }
1897
2583
  function startSession(sessionId, callback, extraProperties, options) {
1898
2584
  const isTitle = options?.mode === "title";
1899
2585
  const spanName = isTitle ? SESSION_TITLE_SPAN_NAME : SESSION_SPAN_NAME;
1900
- const tracer = import_api5.trace.getTracer("@brizz/sdk");
2586
+ const tracer = import_api10.trace.getTracer("@brizz/sdk");
1901
2587
  return tracer.startActiveSpan(spanName, (span) => {
1902
2588
  span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
1903
2589
  if (extraProperties) {
@@ -1916,8 +2602,8 @@ function startSession(sessionId, callback, extraProperties, options) {
1916
2602
  }
1917
2603
  }
1918
2604
  return callWithProperties(contextProperties, () => {
1919
- const sessionCtx = import_api5.context.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
1920
- return import_api5.context.with(sessionCtx, () => {
2605
+ const sessionCtx = import_api10.context.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
2606
+ return import_api10.context.with(sessionCtx, () => {
1921
2607
  try {
1922
2608
  const result = callback(session);
1923
2609
  if (result && typeof result.then === "function") {
@@ -1926,7 +2612,7 @@ function startSession(sessionId, callback, extraProperties, options) {
1926
2612
  return value;
1927
2613
  }).catch((error) => {
1928
2614
  span.recordException(error);
1929
- span.setStatus({ code: import_api5.SpanStatusCode.ERROR });
2615
+ span.setStatus({ code: import_api10.SpanStatusCode.ERROR });
1930
2616
  span.end();
1931
2617
  throw error;
1932
2618
  });
@@ -1935,7 +2621,7 @@ function startSession(sessionId, callback, extraProperties, options) {
1935
2621
  return result;
1936
2622
  } catch (error) {
1937
2623
  span.recordException(error);
1938
- span.setStatus({ code: import_api5.SpanStatusCode.ERROR });
2624
+ span.setStatus({ code: import_api10.SpanStatusCode.ERROR });
1939
2625
  span.end();
1940
2626
  throw error;
1941
2627
  }
@@ -1945,7 +2631,7 @@ function startSession(sessionId, callback, extraProperties, options) {
1945
2631
  }
1946
2632
  function startSessionTitle(callback, options) {
1947
2633
  const resolvedSessionId = options?.sessionId ?? getActiveSession()?.sessionId;
1948
- const tracer = import_api5.trace.getTracer("@brizz/sdk");
2634
+ const tracer = import_api10.trace.getTracer("@brizz/sdk");
1949
2635
  return tracer.startActiveSpan(SESSION_TITLE_SPAN_NAME, (span) => {
1950
2636
  if (resolvedSessionId) {
1951
2637
  span.setAttribute(`${BRIZZ}.${SESSION_ID}`, resolvedSessionId);
@@ -1964,7 +2650,7 @@ function startSessionTitle(callback, options) {
1964
2650
  return value;
1965
2651
  }).catch((error) => {
1966
2652
  span.recordException(error);
1967
- span.setStatus({ code: import_api5.SpanStatusCode.ERROR });
2653
+ span.setStatus({ code: import_api10.SpanStatusCode.ERROR });
1968
2654
  span.end();
1969
2655
  throw error;
1970
2656
  });
@@ -1973,7 +2659,7 @@ function startSessionTitle(callback, options) {
1973
2659
  return result;
1974
2660
  } catch (error) {
1975
2661
  span.recordException(error);
1976
- span.setStatus({ code: import_api5.SpanStatusCode.ERROR });
2662
+ span.setStatus({ code: import_api10.SpanStatusCode.ERROR });
1977
2663
  span.end();
1978
2664
  throw error;
1979
2665
  }
@@ -1982,6 +2668,7 @@ function startSessionTitle(callback, options) {
1982
2668
  }
1983
2669
 
1984
2670
  // src/internal/sdk.ts
2671
+ init_version();
1985
2672
  var _Brizz = class __Brizz {
1986
2673
  static instance = null;
1987
2674
  /** Flag indicating if SDK initialization has completed successfully */
@@ -2179,9 +2866,11 @@ var _Brizz = class __Brizz {
2179
2866
  var Brizz = new _Brizz();
2180
2867
 
2181
2868
  // src/index.ts
2869
+ init_logger();
2182
2870
  var import_api_logs2 = require("@opentelemetry/api-logs");
2183
2871
 
2184
2872
  // src/node/runtime.ts
2873
+ init_logger();
2185
2874
  function detectRuntime() {
2186
2875
  const [major, minor] = process.versions.node.split(".").map(Number);
2187
2876
  const noNodeJSGlobals = typeof __filename === "undefined" && typeof __dirname === "undefined";
@@ -2251,6 +2940,7 @@ var init_exports = {};
2251
2940
  logger,
2252
2941
  maskAttributes,
2253
2942
  maskValue,
2943
+ setCurrentSpanCustomProperties,
2254
2944
  setLogLevel,
2255
2945
  startSession,
2256
2946
  startSessionTitle,