@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.js CHANGED
@@ -1,131 +1,22 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
1
3
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
4
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
5
  }) : x)(function(x) {
4
6
  if (typeof require !== "undefined") return require.apply(this, arguments);
5
7
  throw Error('Dynamic require of "' + x + '" is not supported');
6
8
  });
7
-
8
- // src/internal/instrumentation/auto-init.ts
9
- import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
10
- import { registerInstrumentations } from "@opentelemetry/instrumentation";
11
- import { AnthropicInstrumentation } from "@traceloop/instrumentation-anthropic";
12
- import { BedrockInstrumentation } from "@traceloop/instrumentation-bedrock";
13
- import { ChromaDBInstrumentation } from "@traceloop/instrumentation-chromadb";
14
- import { CohereInstrumentation } from "@traceloop/instrumentation-cohere";
15
- import { LlamaIndexInstrumentation } from "@traceloop/instrumentation-llamaindex";
16
- import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai";
17
- import { PineconeInstrumentation } from "@traceloop/instrumentation-pinecone";
18
- import { QdrantInstrumentation } from "@traceloop/instrumentation-qdrant";
19
- import { TogetherInstrumentation } from "@traceloop/instrumentation-together";
20
- import { VertexAIInstrumentation } from "@traceloop/instrumentation-vertexai";
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
21
16
 
22
17
  // src/internal/logger.ts
23
18
  import { DiagLogLevel } from "@opentelemetry/api";
24
19
  import pino from "pino";
25
- var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
26
- LogLevel2[LogLevel2["NONE"] = 0] = "NONE";
27
- LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
28
- LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
29
- LogLevel2[LogLevel2["INFO"] = 3] = "INFO";
30
- LogLevel2[LogLevel2["DEBUG"] = 4] = "DEBUG";
31
- return LogLevel2;
32
- })(LogLevel || {});
33
- var DEFAULT_LOG_LEVEL = 2 /* WARN */;
34
- var PinoLogger = class {
35
- _level = DEFAULT_LOG_LEVEL;
36
- _pinoLogger = null;
37
- constructor() {
38
- const envLevel = this.getLogLevelFromEnv();
39
- this._level = envLevel;
40
- }
41
- /**
42
- * Lazy initialization of Pino logger to ensure it's created AFTER Jest spies
43
- * are set up during tests. This prevents the pino-pretty transport from
44
- * bypassing stdout/stderr spies.
45
- */
46
- ensurePinoLogger() {
47
- if (!this._pinoLogger) {
48
- this._pinoLogger = pino({
49
- name: "Brizz",
50
- level: this.logLevelToPino(this._level),
51
- // Disable transport in test environment to allow proper spy capture
52
- transport: this.isProduction() || this.isTest() ? void 0 : {
53
- target: "pino-pretty",
54
- options: {
55
- singleLine: true,
56
- colorize: true,
57
- translateTime: "HH:MM:ss",
58
- ignore: "pid,hostname",
59
- messageFormat: "[{name}] {msg}"
60
- }
61
- }
62
- });
63
- }
64
- return this._pinoLogger;
65
- }
66
- isProduction() {
67
- return process.env["NODE_ENV"] === "production";
68
- }
69
- isTest() {
70
- return process.env["NODE_ENV"] === "test";
71
- }
72
- getLogLevelFromEnv() {
73
- const envLevel = process.env["BRIZZ_LOG_LEVEL"];
74
- return envLevel ? parseLogLevel(envLevel) : DEFAULT_LOG_LEVEL;
75
- }
76
- logLevelToPino(level) {
77
- switch (level) {
78
- case 4 /* DEBUG */:
79
- return "debug";
80
- case 3 /* INFO */:
81
- return "info";
82
- case 2 /* WARN */:
83
- return "warn";
84
- case 1 /* ERROR */:
85
- return "error";
86
- default:
87
- return "silent";
88
- }
89
- }
90
- formatMeta(meta) {
91
- if (meta.length === 0) {
92
- return {};
93
- }
94
- if (meta.length === 1 && typeof meta[0] === "object" && meta[0] !== null) {
95
- return meta[0];
96
- }
97
- return { metadata: meta };
98
- }
99
- setLevel(level) {
100
- this._level = level;
101
- if (this._pinoLogger) {
102
- this._pinoLogger.level = this.logLevelToPino(level);
103
- }
104
- }
105
- getLevel() {
106
- return this._level;
107
- }
108
- debug = (msg, ...meta) => {
109
- if (this._level >= 4 /* DEBUG */) {
110
- this.ensurePinoLogger().debug(this.formatMeta(meta), msg);
111
- }
112
- };
113
- info = (msg, ...meta) => {
114
- if (this._level >= 3 /* INFO */) {
115
- this.ensurePinoLogger().info(this.formatMeta(meta), msg);
116
- }
117
- };
118
- warn = (msg, ...meta) => {
119
- if (this._level >= 2 /* WARN */) {
120
- this.ensurePinoLogger().warn(this.formatMeta(meta), msg);
121
- }
122
- };
123
- error = (msg, ...meta) => {
124
- if (this._level >= 1 /* ERROR */) {
125
- this.ensurePinoLogger().error(this.formatMeta(meta), msg);
126
- }
127
- };
128
- };
129
20
  function parseLogLevel(level) {
130
21
  if (!level) {
131
22
  return DEFAULT_LOG_LEVEL;
@@ -154,7 +45,6 @@ function parseLogLevel(level) {
154
45
  }
155
46
  }
156
47
  }
157
- var logger = new PinoLogger();
158
48
  function setLogLevel(level) {
159
49
  const resolvedLevel = typeof level === "string" ? parseLogLevel(level) : level;
160
50
  logger.setLevel(resolvedLevel);
@@ -162,8 +52,924 @@ function setLogLevel(level) {
162
52
  function getLogLevel() {
163
53
  return logger.getLevel();
164
54
  }
55
+ var LogLevel, DEFAULT_LOG_LEVEL, PinoLogger, logger;
56
+ var init_logger = __esm({
57
+ "src/internal/logger.ts"() {
58
+ "use strict";
59
+ LogLevel = /* @__PURE__ */ ((LogLevel2) => {
60
+ LogLevel2[LogLevel2["NONE"] = 0] = "NONE";
61
+ LogLevel2[LogLevel2["ERROR"] = 1] = "ERROR";
62
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
63
+ LogLevel2[LogLevel2["INFO"] = 3] = "INFO";
64
+ LogLevel2[LogLevel2["DEBUG"] = 4] = "DEBUG";
65
+ return LogLevel2;
66
+ })(LogLevel || {});
67
+ DEFAULT_LOG_LEVEL = 2 /* WARN */;
68
+ PinoLogger = class {
69
+ _level = DEFAULT_LOG_LEVEL;
70
+ _pinoLogger = null;
71
+ constructor() {
72
+ const envLevel = this.getLogLevelFromEnv();
73
+ this._level = envLevel;
74
+ }
75
+ /**
76
+ * Lazy initialization of Pino logger to ensure it's created AFTER Jest spies
77
+ * are set up during tests. This prevents the pino-pretty transport from
78
+ * bypassing stdout/stderr spies.
79
+ */
80
+ ensurePinoLogger() {
81
+ if (!this._pinoLogger) {
82
+ this._pinoLogger = pino({
83
+ name: "Brizz",
84
+ level: this.logLevelToPino(this._level),
85
+ // Disable transport in test environment to allow proper spy capture
86
+ transport: this.isProduction() || this.isTest() ? void 0 : {
87
+ target: "pino-pretty",
88
+ options: {
89
+ singleLine: true,
90
+ colorize: true,
91
+ translateTime: "HH:MM:ss",
92
+ ignore: "pid,hostname",
93
+ messageFormat: "[{name}] {msg}"
94
+ }
95
+ }
96
+ });
97
+ }
98
+ return this._pinoLogger;
99
+ }
100
+ isProduction() {
101
+ return process.env["NODE_ENV"] === "production";
102
+ }
103
+ isTest() {
104
+ return process.env["NODE_ENV"] === "test";
105
+ }
106
+ getLogLevelFromEnv() {
107
+ const envLevel = process.env["BRIZZ_LOG_LEVEL"];
108
+ return envLevel ? parseLogLevel(envLevel) : DEFAULT_LOG_LEVEL;
109
+ }
110
+ logLevelToPino(level) {
111
+ switch (level) {
112
+ case 4 /* DEBUG */:
113
+ return "debug";
114
+ case 3 /* INFO */:
115
+ return "info";
116
+ case 2 /* WARN */:
117
+ return "warn";
118
+ case 1 /* ERROR */:
119
+ return "error";
120
+ default:
121
+ return "silent";
122
+ }
123
+ }
124
+ formatMeta(meta) {
125
+ if (meta.length === 0) {
126
+ return {};
127
+ }
128
+ if (meta.length === 1 && typeof meta[0] === "object" && meta[0] !== null) {
129
+ return meta[0];
130
+ }
131
+ return { metadata: meta };
132
+ }
133
+ setLevel(level) {
134
+ this._level = level;
135
+ if (this._pinoLogger) {
136
+ this._pinoLogger.level = this.logLevelToPino(level);
137
+ }
138
+ }
139
+ getLevel() {
140
+ return this._level;
141
+ }
142
+ debug = (msg, ...meta) => {
143
+ if (this._level >= 4 /* DEBUG */) {
144
+ this.ensurePinoLogger().debug(this.formatMeta(meta), msg);
145
+ }
146
+ };
147
+ info = (msg, ...meta) => {
148
+ if (this._level >= 3 /* INFO */) {
149
+ this.ensurePinoLogger().info(this.formatMeta(meta), msg);
150
+ }
151
+ };
152
+ warn = (msg, ...meta) => {
153
+ if (this._level >= 2 /* WARN */) {
154
+ this.ensurePinoLogger().warn(this.formatMeta(meta), msg);
155
+ }
156
+ };
157
+ error = (msg, ...meta) => {
158
+ if (this._level >= 1 /* ERROR */) {
159
+ this.ensurePinoLogger().error(this.formatMeta(meta), msg);
160
+ }
161
+ };
162
+ };
163
+ logger = new PinoLogger();
164
+ }
165
+ });
166
+
167
+ // src/internal/semantic-conventions.ts
168
+ import { createContextKey } from "@opentelemetry/api";
169
+ var 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;
170
+ var init_semantic_conventions = __esm({
171
+ "src/internal/semantic-conventions.ts"() {
172
+ "use strict";
173
+ BRIZZ = "brizz";
174
+ PROPERTIES = "properties";
175
+ SESSION_ID = "session.id";
176
+ PROPERTIES_CONTEXT_KEY = createContextKey(PROPERTIES);
177
+ SESSION_OBJECT_CONTEXT_KEY = createContextKey("brizz.session.object");
178
+ SESSION_INPUT = "brizz.session.input";
179
+ SESSION_OUTPUT = "brizz.session.output";
180
+ SESSION_INPUT_CONTEXT = "brizz.session.input.context";
181
+ SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
182
+ SESSION_SPAN_NAME = "brizz.start_session";
183
+ SESSION_TITLE_SPAN_NAME = "brizz.session_title";
184
+ SESSION_TITLE_GENERATION = "session.title_generation";
185
+ SESSION_TITLE = "brizz.session.title";
186
+ }
187
+ });
188
+
189
+ // src/internal/instrumentation/mcp/semantic-conventions.ts
190
+ 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;
191
+ var init_semantic_conventions2 = __esm({
192
+ "src/internal/instrumentation/mcp/semantic-conventions.ts"() {
193
+ "use strict";
194
+ MCP_TOOL_NAME = "mcp.tool.name";
195
+ MCP_TOOL_ARGUMENTS = "mcp.tool.arguments";
196
+ MCP_TOOL_RESULT = "mcp.tool.result";
197
+ MCP_COMPONENT_TYPE = "mcp.component.type";
198
+ MCP_COMPONENT_TOOL = "tool";
199
+ MCP_COMPONENT_TOOL_SCHEMA = "tool_schema";
200
+ MCP_TOOL_SCHEMA_PARAMETERS = "mcp.tool.schema.parameters";
201
+ MCP_TOOL_SCHEMA_OUTPUT = "mcp.tool.schema.output";
202
+ MCP_TOOL_DESCRIPTION = "mcp.tool.description";
203
+ SPAN_NAME_TOOL_REGISTER = "mcp.tool.register";
204
+ MCP_METHOD_NAME = "mcp.method.name";
205
+ MCP_REQUEST_ID = "mcp.request.id";
206
+ MCP_SESSION_ID = "mcp.session.id";
207
+ MCP_PROTOCOL_VERSION = "mcp.protocol.version";
208
+ MCP_RESOURCE_URI = "mcp.resource.uri";
209
+ RPC_SYSTEM = "rpc.system";
210
+ RPC_SYSTEM_MCP = "mcp";
211
+ RPC_RESPONSE_STATUS_CODE = "rpc.response.status_code";
212
+ GEN_AI_TOOL_NAME = "gen_ai.tool.name";
213
+ GEN_AI_PROMPT_NAME = "gen_ai.prompt.name";
214
+ GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
215
+ GEN_AI_OPERATION_EXECUTE_TOOL = "execute_tool";
216
+ NETWORK_TRANSPORT = "network.transport";
217
+ ERROR_TYPE = "error.type";
218
+ ERROR_TYPE_TOOL = "tool_error";
219
+ JSONRPC_REQUEST_ID = "jsonrpc.request.id";
220
+ SPAN_NAME_TOOLS_CALL = "tools/call";
221
+ MAX_ATTRIBUTE_LENGTH = 32 * 1024;
222
+ TRUNCATION_SUFFIX = "\u2026(truncated)";
223
+ METHOD_TOOLS_CALL = "tools/call";
224
+ METHOD_TOOLS_LIST = "tools/list";
225
+ METHOD_RESOURCES_READ = "resources/read";
226
+ METHOD_PROMPTS_GET = "prompts/get";
227
+ METHOD_INITIALIZE = "initialize";
228
+ }
229
+ });
230
+
231
+ // src/internal/instrumentation/mcp/schemas.ts
232
+ import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
233
+ function truncateSchemaAttr(value) {
234
+ if (value.length <= _MAX_SCHEMA_ATTR_BYTES) {
235
+ return value;
236
+ }
237
+ return `{"_truncated":true,"original_length":${value.length}}`;
238
+ }
239
+ function safeStringify(value) {
240
+ if (value === null || value === void 0) {
241
+ return "";
242
+ }
243
+ try {
244
+ return JSON.stringify(value);
245
+ } catch {
246
+ return "";
247
+ }
248
+ }
249
+ function emitSchemaSpansFromListResponse(result, transportSessionId, tracer) {
250
+ if (!transportSessionId) {
251
+ return;
252
+ }
253
+ const tools = extractTools(result);
254
+ if (tools === void 0) {
255
+ return;
256
+ }
257
+ for (const tool of tools) {
258
+ const name = typeof tool.name === "string" ? tool.name : void 0;
259
+ if (!name) {
260
+ continue;
261
+ }
262
+ const span = tracer.startSpan(`${SPAN_NAME_TOOL_REGISTER} ${name}`, {
263
+ kind: SpanKind.INTERNAL
264
+ });
265
+ try {
266
+ stampSchemaAttributes(span, name, transportSessionId, tool);
267
+ span.setStatus({ code: SpanStatusCode.OK });
268
+ } finally {
269
+ span.end();
270
+ }
271
+ }
272
+ }
273
+ function stampSchemaAttributes(span, toolName, transportSessionId, tool) {
274
+ if (!span.isRecording()) {
275
+ logger.warn(
276
+ `Brizz MCP: schema span is not recording; dropping attributes for ${toolName}`
277
+ );
278
+ return;
279
+ }
280
+ const description = typeof tool.description === "string" ? tool.description : "";
281
+ const parameters = truncateSchemaAttr(safeStringify(tool.inputSchema));
282
+ const outputSchema = tool.outputSchema !== void 0 && tool.outputSchema !== null ? truncateSchemaAttr(safeStringify(tool.outputSchema)) : "";
283
+ span.setAttribute(RPC_SYSTEM, RPC_SYSTEM_MCP);
284
+ span.setAttribute(MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL_SCHEMA);
285
+ span.setAttribute(MCP_SESSION_ID, transportSessionId);
286
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, transportSessionId);
287
+ span.setAttribute(MCP_TOOL_NAME, toolName);
288
+ span.setAttribute(MCP_TOOL_SCHEMA_PARAMETERS, parameters);
289
+ span.setAttribute(MCP_TOOL_SCHEMA_OUTPUT, outputSchema);
290
+ span.setAttribute(MCP_TOOL_DESCRIPTION, description);
291
+ }
292
+ function extractTools(result) {
293
+ if (!result || typeof result !== "object") {
294
+ return void 0;
295
+ }
296
+ const tools = result.tools;
297
+ if (!Array.isArray(tools)) {
298
+ return void 0;
299
+ }
300
+ return tools.filter(
301
+ (t) => t !== null && typeof t === "object"
302
+ );
303
+ }
304
+ var _MAX_SCHEMA_ATTR_BYTES;
305
+ var init_schemas = __esm({
306
+ "src/internal/instrumentation/mcp/schemas.ts"() {
307
+ "use strict";
308
+ init_logger();
309
+ init_semantic_conventions();
310
+ init_semantic_conventions2();
311
+ _MAX_SCHEMA_ATTR_BYTES = 4e3;
312
+ }
313
+ });
314
+
315
+ // src/internal/instrumentation/mcp/session.ts
316
+ import { context } from "@opentelemetry/api";
317
+ function stampAndPropagateSession(span, sessionId, baseContext = context.active()) {
318
+ if (!sessionId) {
319
+ return { context: baseContext, sessionId: null };
320
+ }
321
+ if (span.isRecording()) {
322
+ try {
323
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
324
+ } catch (error) {
325
+ logger.warn(
326
+ `Brizz MCP: failed to stamp session id on span: ${String(error)}`
327
+ );
328
+ }
329
+ }
330
+ try {
331
+ const prev = baseContext.getValue(PROPERTIES_CONTEXT_KEY);
332
+ const merged = prev ? { ...prev, [SESSION_ID]: sessionId } : { [SESSION_ID]: sessionId };
333
+ return {
334
+ context: baseContext.setValue(PROPERTIES_CONTEXT_KEY, merged),
335
+ sessionId
336
+ };
337
+ } catch (error) {
338
+ logger.warn(`Brizz MCP: failed to attach session context: ${String(error)}`);
339
+ return { context: baseContext, sessionId };
340
+ }
341
+ }
342
+ var init_session = __esm({
343
+ "src/internal/instrumentation/mcp/session.ts"() {
344
+ "use strict";
345
+ init_logger();
346
+ init_semantic_conventions();
347
+ }
348
+ });
349
+
350
+ // src/internal/instrumentation/mcp/patches/attributes.ts
351
+ import { SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
352
+ function deriveSpanName(method, params) {
353
+ try {
354
+ if (method === METHOD_TOOLS_CALL) {
355
+ const name = typeof params?.["name"] === "string" ? params["name"] : "";
356
+ return name ? `${SPAN_NAME_TOOLS_CALL} ${name}` : SPAN_NAME_TOOLS_CALL;
357
+ }
358
+ if (method === METHOD_RESOURCES_READ) {
359
+ const uri = typeof params?.["uri"] === "string" ? params["uri"] : "";
360
+ return uri ? `${METHOD_RESOURCES_READ} ${uri}` : METHOD_RESOURCES_READ;
361
+ }
362
+ if (method === METHOD_PROMPTS_GET) {
363
+ const name = typeof params?.["name"] === "string" ? params["name"] : "";
364
+ return name ? `${METHOD_PROMPTS_GET} ${name}` : METHOD_PROMPTS_GET;
365
+ }
366
+ return method;
367
+ } catch {
368
+ return method || "mcp";
369
+ }
370
+ }
371
+ function applyBaseAttributes(span, request) {
372
+ span.setAttribute(RPC_SYSTEM, RPC_SYSTEM_MCP);
373
+ if (request.method) {
374
+ span.setAttribute(MCP_METHOD_NAME, request.method);
375
+ }
376
+ if (request.id !== void 0 && request.id !== null) {
377
+ const id = String(request.id);
378
+ span.setAttribute(MCP_REQUEST_ID, id);
379
+ span.setAttribute(JSONRPC_REQUEST_ID, id);
380
+ }
381
+ }
382
+ function applyClientRequestAttributes(span, request, transportName) {
383
+ applyBaseAttributes(span, request);
384
+ applyMethodSpecificRequestAttributes(span, request);
385
+ if (transportName) {
386
+ const transport = normalizeTransport(transportName);
387
+ if (transport) {
388
+ span.setAttribute(NETWORK_TRANSPORT, transport);
389
+ }
390
+ }
391
+ }
392
+ function applyServerRequestAttributes(span, request, protocol) {
393
+ applyBaseAttributes(span, request);
394
+ applyMethodSpecificRequestAttributes(span, request);
395
+ if (request.method === METHOD_TOOLS_CALL) {
396
+ const args = request.params?.["arguments"];
397
+ if (args !== void 0) {
398
+ span.setAttribute(MCP_TOOL_ARGUMENTS, serializeForAttribute(args));
399
+ }
400
+ }
401
+ const sessionId = protocol.sessionId ?? protocol._transport?.sessionId;
402
+ if (sessionId) {
403
+ span.setAttribute(MCP_SESSION_ID, String(sessionId));
404
+ }
405
+ }
406
+ function applyMethodSpecificRequestAttributes(span, request) {
407
+ const params = request.params ?? {};
408
+ switch (request.method) {
409
+ case METHOD_TOOLS_CALL: {
410
+ const name = typeof params["name"] === "string" ? params["name"] : "";
411
+ if (name) {
412
+ span.setAttribute(MCP_TOOL_NAME, name);
413
+ span.setAttribute(GEN_AI_TOOL_NAME, name);
414
+ }
415
+ span.setAttribute(MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL);
416
+ span.setAttribute(GEN_AI_OPERATION_NAME, GEN_AI_OPERATION_EXECUTE_TOOL);
417
+ break;
418
+ }
419
+ case METHOD_RESOURCES_READ: {
420
+ const uri = typeof params["uri"] === "string" ? params["uri"] : "";
421
+ if (uri) {
422
+ span.setAttribute(MCP_RESOURCE_URI, uri);
423
+ }
424
+ break;
425
+ }
426
+ case METHOD_PROMPTS_GET: {
427
+ const name = typeof params["name"] === "string" ? params["name"] : "";
428
+ if (name) {
429
+ span.setAttribute(GEN_AI_PROMPT_NAME, name);
430
+ }
431
+ break;
432
+ }
433
+ default:
434
+ break;
435
+ }
436
+ }
437
+ function applyResultAttributes(span, method, result) {
438
+ if (method === METHOD_INITIALIZE && result && typeof result === "object") {
439
+ const protocolVersion = result["protocolVersion"];
440
+ if (typeof protocolVersion === "string") {
441
+ span.setAttribute(MCP_PROTOCOL_VERSION, protocolVersion);
442
+ }
443
+ return;
444
+ }
445
+ if (method !== METHOD_TOOLS_CALL) {
446
+ return;
447
+ }
448
+ const obj = result && typeof result === "object" ? result : null;
449
+ const content = obj?.["content"] ?? result;
450
+ span.setAttribute(MCP_TOOL_RESULT, serializeForAttribute(content));
451
+ if (obj && obj["isError"] === true) {
452
+ span.setAttribute(ERROR_TYPE, ERROR_TYPE_TOOL);
453
+ const message = extractToolErrorMessage(obj);
454
+ span.setStatus({ code: SpanStatusCode2.ERROR, message });
455
+ }
456
+ }
457
+ function applyErrorAttributes(span, err) {
458
+ const error = err;
459
+ const code = error?.code;
460
+ if (typeof code === "number") {
461
+ span.setAttribute(RPC_RESPONSE_STATUS_CODE, code);
462
+ span.setAttribute(ERROR_TYPE, String(code));
463
+ } else if (error?.name === "AbortError") {
464
+ span.setAttribute(ERROR_TYPE, "cancelled");
465
+ } else if (error?.name === "TimeoutError") {
466
+ span.setAttribute(ERROR_TYPE, "timeout");
467
+ } else {
468
+ span.setAttribute(
469
+ ERROR_TYPE,
470
+ error?.constructor?.name || error?.name || "Error"
471
+ );
472
+ }
473
+ try {
474
+ span.recordException(error);
475
+ } catch {
476
+ }
477
+ span.setStatus({
478
+ code: SpanStatusCode2.ERROR,
479
+ message: typeof error?.message === "string" ? error.message : void 0
480
+ });
481
+ }
482
+ function serializeForAttribute(value) {
483
+ const raw = rawSerialize(value);
484
+ if (raw.length <= MAX_ATTRIBUTE_LENGTH) {
485
+ return raw;
486
+ }
487
+ return raw.slice(0, MAX_ATTRIBUTE_LENGTH - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX;
488
+ }
489
+ function rawSerialize(value) {
490
+ if (value === null || value === void 0) {
491
+ return "";
492
+ }
493
+ if (typeof value === "string") {
494
+ return value;
495
+ }
496
+ try {
497
+ return JSON.stringify(value);
498
+ } catch {
499
+ try {
500
+ if (value === null || value === void 0) {
501
+ return "";
502
+ }
503
+ const tag = Object.prototype.toString.call(value);
504
+ return typeof value.toString === "function" ? (
505
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
506
+ String(value)
507
+ ) : tag;
508
+ } catch {
509
+ return "";
510
+ }
511
+ }
512
+ }
513
+ function extractToolErrorMessage(result) {
514
+ const content = result["content"];
515
+ if (Array.isArray(content)) {
516
+ for (const item of content) {
517
+ if (item && typeof item === "object") {
518
+ const text = item["text"];
519
+ if (typeof text === "string") {
520
+ return text;
521
+ }
522
+ }
523
+ }
524
+ }
525
+ return void 0;
526
+ }
527
+ function normalizeTransport(ctorName) {
528
+ const name = ctorName.toLowerCase();
529
+ if (name.includes("stdio")) {
530
+ return "stdio";
531
+ }
532
+ if (name.includes("sse")) {
533
+ return "sse";
534
+ }
535
+ if (name.includes("streamablehttp") || name.includes("http")) {
536
+ return "http";
537
+ }
538
+ return null;
539
+ }
540
+ var init_attributes = __esm({
541
+ "src/internal/instrumentation/mcp/patches/attributes.ts"() {
542
+ "use strict";
543
+ init_semantic_conventions2();
544
+ }
545
+ });
546
+
547
+ // src/internal/instrumentation/mcp/patches/protocol.ts
548
+ import { context as context2, propagation, SpanKind as SpanKind2, trace } from "@opentelemetry/api";
549
+ function patchProtocolPrototype(prototype, tracer) {
550
+ if (!prototype || typeof prototype !== "object") {
551
+ return false;
552
+ }
553
+ const proto = prototype;
554
+ if (proto[PATCHED_FLAG]) {
555
+ logger.debug("Brizz MCP: Protocol.prototype already patched, skipping");
556
+ return false;
557
+ }
558
+ const originalRequest = proto["request"];
559
+ const originalOnRequest = proto["_onrequest"];
560
+ if (typeof originalRequest === "function") {
561
+ proto["request"] = wrapRequest(originalRequest, tracer);
562
+ } else {
563
+ logger.debug(
564
+ "Brizz MCP: Protocol.prototype.request missing \u2014 skipping CLIENT patch"
565
+ );
566
+ }
567
+ if (typeof originalOnRequest === "function") {
568
+ proto["_onrequest"] = wrapOnRequest(
569
+ originalOnRequest,
570
+ tracer
571
+ );
572
+ } else {
573
+ logger.debug(
574
+ "Brizz MCP: Protocol.prototype._onrequest missing \u2014 skipping SERVER patch"
575
+ );
576
+ }
577
+ proto[PATCHED_FLAG] = true;
578
+ return true;
579
+ }
580
+ function wrapRequest(original, tracer) {
581
+ return function wrappedRequest(...args) {
582
+ const request = args[0];
583
+ if (!request || typeof request !== "object" || !request.method) {
584
+ return original.apply(this, args);
585
+ }
586
+ const span = safeStartClientSpan(tracer, request, this);
587
+ if (!span) {
588
+ return original.apply(this, args);
589
+ }
590
+ return executeAroundSpan(span, request.method, () => {
591
+ const ctx = trace.setSpan(context2.active(), span);
592
+ return context2.with(ctx, () => original.apply(this, args));
593
+ });
594
+ };
595
+ }
596
+ function wrapOnRequest(original, tracer) {
597
+ return function wrappedOnRequest(...args) {
598
+ const request = args[0];
599
+ if (!request || typeof request !== "object" || !request.method) {
600
+ return original.apply(this, args);
601
+ }
602
+ const handlers = this._requestHandlers;
603
+ if (!handlers || typeof handlers.get !== "function") {
604
+ return original.apply(this, args);
605
+ }
606
+ const method = request.method;
607
+ const handler = handlers.get(method) ?? this.fallbackRequestHandler;
608
+ if (!handler) {
609
+ return original.apply(this, args);
610
+ }
611
+ const started = safeStartServerSpan(tracer, request, this);
612
+ if (!started) {
613
+ return original.apply(this, args);
614
+ }
615
+ const { span, spanCtx } = started;
616
+ const transportSessionId = this.sessionId ?? this._transport?.sessionId;
617
+ const postResult = method === METHOD_TOOLS_LIST ? (result) => {
618
+ try {
619
+ emitSchemaSpansFromListResponse(result, transportSessionId, tracer);
620
+ } catch (error) {
621
+ logger.warn(
622
+ `Brizz MCP: failed to emit tools/list schema spans: ${String(error)}`
623
+ );
624
+ }
625
+ } : void 0;
626
+ const wrappedHandler = (req, extra) => context2.with(
627
+ spanCtx,
628
+ () => executeHandler(span, method, handler, req, extra, postResult)
629
+ );
630
+ const hadEntry = handlers.has(method);
631
+ const prev = handlers.get(method);
632
+ handlers.set(method, wrappedHandler);
633
+ const usedFallback = !hadEntry && this.fallbackRequestHandler === handler;
634
+ const fallbackPrev = usedFallback ? this.fallbackRequestHandler : void 0;
635
+ if (usedFallback) {
636
+ this.fallbackRequestHandler = wrappedHandler;
637
+ }
638
+ try {
639
+ return original.apply(this, args);
640
+ } finally {
641
+ if (hadEntry) {
642
+ handlers.set(method, prev);
643
+ } else {
644
+ handlers.delete(method);
645
+ }
646
+ if (usedFallback) {
647
+ this.fallbackRequestHandler = fallbackPrev;
648
+ }
649
+ }
650
+ };
651
+ }
652
+ function executeAroundSpan(span, method, run, postResult) {
653
+ let result;
654
+ try {
655
+ result = run();
656
+ } catch (error) {
657
+ safeApplyErrorAttributes(span, error);
658
+ safeEnd(span);
659
+ throw error;
660
+ }
661
+ if (!isThenable(result)) {
662
+ safeApplyResultAttributes(span, method, result);
663
+ if (postResult) {
664
+ postResult(result);
665
+ }
666
+ safeEnd(span);
667
+ return result;
668
+ }
669
+ return result.then(
670
+ (value) => {
671
+ safeApplyResultAttributes(span, method, value);
672
+ if (postResult) {
673
+ postResult(value);
674
+ }
675
+ safeEnd(span);
676
+ return value;
677
+ },
678
+ (error) => {
679
+ safeApplyErrorAttributes(span, error);
680
+ safeEnd(span);
681
+ throw error;
682
+ }
683
+ );
684
+ }
685
+ function executeHandler(span, method, handler, req, extra, postResult) {
686
+ return executeAroundSpan(span, method, () => handler(req, extra), postResult);
687
+ }
688
+ function safeStartClientSpan(tracer, request, protocol) {
689
+ try {
690
+ const spanName = deriveSpanName(request.method, request.params);
691
+ const span = tracer.startSpan(spanName, { kind: SpanKind2.CLIENT });
692
+ applyClientRequestAttributes(
693
+ span,
694
+ request,
695
+ protocol._transport?.constructor?.name
696
+ );
697
+ return span;
698
+ } catch (error) {
699
+ logger.debug(`Brizz MCP: failed to open CLIENT span: ${String(error)}`);
700
+ return null;
701
+ }
702
+ }
703
+ function safeStartServerSpan(tracer, request, protocol) {
704
+ try {
705
+ const parentCtx = extractParentContext(request);
706
+ const spanName = deriveSpanName(request.method, request.params);
707
+ const span = tracer.startSpan(
708
+ spanName,
709
+ { kind: SpanKind2.SERVER },
710
+ parentCtx
711
+ );
712
+ applyServerRequestAttributes(span, request, protocol);
713
+ const sessionId = protocol.sessionId ?? protocol._transport?.sessionId;
714
+ const { context: sessCtx } = stampAndPropagateSession(span, sessionId, parentCtx);
715
+ return { span, spanCtx: trace.setSpan(sessCtx, span) };
716
+ } catch (error) {
717
+ logger.debug(`Brizz MCP: failed to open SERVER span: ${String(error)}`);
718
+ return null;
719
+ }
720
+ }
721
+ function extractParentContext(request) {
722
+ try {
723
+ const meta = request.params?._meta;
724
+ if (meta && typeof meta === "object") {
725
+ return propagation.extract(context2.active(), meta);
726
+ }
727
+ } catch (error) {
728
+ logger.debug(
729
+ `Brizz MCP: failed to extract parent context from _meta: ${String(error)}`
730
+ );
731
+ }
732
+ return context2.active();
733
+ }
734
+ function isThenable(value) {
735
+ return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
736
+ }
737
+ function safeApplyResultAttributes(span, method, value) {
738
+ try {
739
+ applyResultAttributes(span, method, value);
740
+ } catch (error) {
741
+ logger.debug(
742
+ `Brizz MCP: failed to apply result attributes: ${String(error)}`
743
+ );
744
+ }
745
+ }
746
+ function safeApplyErrorAttributes(span, err) {
747
+ try {
748
+ applyErrorAttributes(span, err);
749
+ } catch (error) {
750
+ logger.debug(
751
+ `Brizz MCP: failed to apply error attributes: ${String(error)}`
752
+ );
753
+ }
754
+ }
755
+ function safeEnd(span) {
756
+ try {
757
+ span.end();
758
+ } catch (error) {
759
+ logger.debug(`Brizz MCP: failed to end span: ${String(error)}`);
760
+ }
761
+ }
762
+ var PATCHED_FLAG;
763
+ var init_protocol = __esm({
764
+ "src/internal/instrumentation/mcp/patches/protocol.ts"() {
765
+ "use strict";
766
+ init_logger();
767
+ init_schemas();
768
+ init_semantic_conventions2();
769
+ init_session();
770
+ init_attributes();
771
+ PATCHED_FLAG = /* @__PURE__ */ Symbol("brizz.mcp.protocol-patched");
772
+ }
773
+ });
774
+
775
+ // src/internal/version.ts
776
+ function getSDKVersion() {
777
+ return "0.1.25";
778
+ }
779
+ var init_version = __esm({
780
+ "src/internal/version.ts"() {
781
+ "use strict";
782
+ }
783
+ });
784
+
785
+ // src/internal/instrumentation/mcp/version.ts
786
+ var INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION;
787
+ var init_version2 = __esm({
788
+ "src/internal/instrumentation/mcp/version.ts"() {
789
+ "use strict";
790
+ init_version();
791
+ INSTRUMENTATION_NAME = "@brizz/sdk/mcp";
792
+ INSTRUMENTATION_VERSION = getSDKVersion();
793
+ }
794
+ });
795
+
796
+ // src/internal/instrumentation/mcp/instrumentation.ts
797
+ import { MCPInstrumentation as BaseMCPInstrumentation } from "@arizeai/openinference-instrumentation-mcp";
798
+ import { trace as trace2 } from "@opentelemetry/api";
799
+ import { InstrumentationNodeModuleDefinition } from "@opentelemetry/instrumentation";
800
+ function isMCPInstrumentation(value) {
801
+ return !!value && typeof value === "object" && typeof value.instrumentationName === "string";
802
+ }
803
+ var PROTOCOL_MODULE_NAME, PROTOCOL_SUPPORTED_VERSIONS, MCPInstrumentation;
804
+ var init_instrumentation = __esm({
805
+ "src/internal/instrumentation/mcp/instrumentation.ts"() {
806
+ "use strict";
807
+ init_logger();
808
+ init_protocol();
809
+ init_version2();
810
+ PROTOCOL_MODULE_NAME = "@modelcontextprotocol/sdk/shared/protocol.js";
811
+ PROTOCOL_SUPPORTED_VERSIONS = [">=1.0.0 <2"];
812
+ MCPInstrumentation = class extends BaseMCPInstrumentation {
813
+ /**
814
+ * Dedicated Brizz-named tracer for our SERVER + CLIENT spans.
815
+ *
816
+ * Why a separate tracer from the parent class's one: Arize's inherited
817
+ * transport patches don't emit spans (they only inject propagation
818
+ * headers), so using our own tracer here keeps Brizz spans attributed to
819
+ * `@brizz/sdk/mcp` in the dashboard. The parent's `tracer` is a
820
+ * `protected get` (no setter), so fighting it with assignment is the
821
+ * wrong tool.
822
+ */
823
+ brizzTracer;
824
+ constructor(_config) {
825
+ super({ instrumentationConfig: _config?.instrumentationConfig });
826
+ this.brizzTracer = trace2.getTracer(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION);
827
+ }
828
+ /**
829
+ * Extend `super.init()` with our protocol-layer module definition.
830
+ *
831
+ * Arize's `init()` returns definitions for the six transport modules
832
+ * (SSE client/server, stdio client/server, streamable-HTTP client/server)
833
+ * whose `send`/`start` methods get patched for W3C trace-context
834
+ * injection. We append one more: `@modelcontextprotocol/sdk/shared/protocol.js`
835
+ * where our patches open SERVER/CLIENT spans around the handler + outgoing
836
+ * request. If `super.init()` throws (unlikely but possible across Arize
837
+ * versions), we gracefully degrade to protocol-only instrumentation.
838
+ *
839
+ * The cast at the end satisfies the parent's strongly-typed generic
840
+ * without leaking the cast into call sites.
841
+ */
842
+ init() {
843
+ let base;
844
+ try {
845
+ base = super.init() ?? [];
846
+ } catch (error) {
847
+ logger.warn(
848
+ `Brizz MCP: base Arize init() failed \u2014 transport context propagation disabled: ${String(error)}`
849
+ );
850
+ base = [];
851
+ }
852
+ const baseArr = Array.isArray(base) ? base : [base];
853
+ const brizzDef = new InstrumentationNodeModuleDefinition(
854
+ PROTOCOL_MODULE_NAME,
855
+ PROTOCOL_SUPPORTED_VERSIONS,
856
+ (module2) => {
857
+ this.patchProtocolModule(module2);
858
+ return module2;
859
+ },
860
+ (module2) => {
861
+ this.unpatchProtocolModule(module2);
862
+ return module2;
863
+ }
864
+ );
865
+ return [...baseArr, brizzDef];
866
+ }
867
+ /**
868
+ * Manually instrument MCP modules for Next.js/Webpack where the
869
+ * auto-instrumentation module-load hook doesn't fire.
870
+ *
871
+ * Forwards the six transport module fields to the inherited Arize
872
+ * `manuallyInstrument(...)` (context propagation) and applies our
873
+ * protocol patch if `protocolModule` is provided (SERVER/CLIENT spans).
874
+ * Both legs are try/catch-guarded — a failure in one shouldn't prevent
875
+ * the other from taking effect.
876
+ */
877
+ manuallyInstrument(modules) {
878
+ const {
879
+ clientSSEModule,
880
+ serverSSEModule,
881
+ clientStdioModule,
882
+ serverStdioModule,
883
+ clientStreamableHTTPModule,
884
+ serverStreamableHTTPModule,
885
+ protocolModule
886
+ } = modules;
887
+ try {
888
+ super.manuallyInstrument({
889
+ clientSSEModule,
890
+ serverSSEModule,
891
+ clientStdioModule,
892
+ serverStdioModule,
893
+ clientStreamableHTTPModule,
894
+ serverStreamableHTTPModule
895
+ });
896
+ } catch (error) {
897
+ logger.warn(`Brizz MCP: Arize manuallyInstrument(...) failed: ${String(error)}`);
898
+ }
899
+ if (protocolModule) {
900
+ try {
901
+ this.patchProtocolModule(protocolModule);
902
+ } catch (error) {
903
+ logger.warn(
904
+ `Brizz MCP: failed to manually patch Protocol module: ${String(error)}`
905
+ );
906
+ }
907
+ }
908
+ }
909
+ /**
910
+ * Apply the SERVER + CLIENT patch to a loaded `protocol.js` module. Shared
911
+ * by both the automatic module-load callback in `init()` and the manual
912
+ * `manuallyInstrument(...)` path above so there's exactly one place that
913
+ * calls `patchProtocolPrototype`.
914
+ */
915
+ patchProtocolModule(module2) {
916
+ const proto = module2?.Protocol?.prototype;
917
+ if (!proto) {
918
+ logger.debug(
919
+ "Brizz MCP: module does not expose Protocol.prototype \u2014 skipping protocol patches"
920
+ );
921
+ return;
922
+ }
923
+ const ok = patchProtocolPrototype(proto, this.brizzTracer);
924
+ if (ok) {
925
+ logger.debug("Brizz MCP: patched Protocol.prototype for SERVER+CLIENT spans");
926
+ }
927
+ }
928
+ /**
929
+ * Unpatch is intentionally a no-op.
930
+ *
931
+ * `patchProtocolPrototype` wraps methods in place and sets a PATCHED_FLAG
932
+ * Symbol on the prototype to prevent double-patching. Restoring the
933
+ * originals would require us to hold references across module unloads,
934
+ * which isn't a pattern we need — instrumentation rarely gets torn down
935
+ * at runtime, and a process reload is the canonical way to detach.
936
+ */
937
+ unpatchProtocolModule(_module) {
938
+ logger.debug(
939
+ "Brizz MCP: unpatch is a no-op \u2014 reload the process to cleanly detach"
940
+ );
941
+ }
942
+ };
943
+ }
944
+ });
945
+
946
+ // src/internal/instrumentation/mcp/index.ts
947
+ var mcp_exports = {};
948
+ __export(mcp_exports, {
949
+ MCPInstrumentation: () => MCPInstrumentation,
950
+ isMCPInstrumentation: () => isMCPInstrumentation
951
+ });
952
+ var init_mcp = __esm({
953
+ "src/internal/instrumentation/mcp/index.ts"() {
954
+ "use strict";
955
+ init_instrumentation();
956
+ }
957
+ });
165
958
 
166
959
  // src/internal/instrumentation/auto-init.ts
960
+ init_logger();
961
+ import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
962
+ import { registerInstrumentations } from "@opentelemetry/instrumentation";
963
+ import { AnthropicInstrumentation } from "@traceloop/instrumentation-anthropic";
964
+ import { BedrockInstrumentation } from "@traceloop/instrumentation-bedrock";
965
+ import { ChromaDBInstrumentation } from "@traceloop/instrumentation-chromadb";
966
+ import { CohereInstrumentation } from "@traceloop/instrumentation-cohere";
967
+ import { LlamaIndexInstrumentation } from "@traceloop/instrumentation-llamaindex";
968
+ import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai";
969
+ import { PineconeInstrumentation } from "@traceloop/instrumentation-pinecone";
970
+ import { QdrantInstrumentation } from "@traceloop/instrumentation-qdrant";
971
+ import { TogetherInstrumentation } from "@traceloop/instrumentation-together";
972
+ import { VertexAIInstrumentation } from "@traceloop/instrumentation-vertexai";
167
973
  var autoInstrumentationsLoaded = false;
168
974
  var exceptionLogger = (error) => {
169
975
  logger.error(`Exception in instrumentation: ${String(error)}`);
@@ -216,6 +1022,20 @@ function loadGenAIInstrumentations() {
216
1022
  }
217
1023
  return instrumentations;
218
1024
  }
1025
+ function loadMCPInstrumentation() {
1026
+ void (async () => {
1027
+ try {
1028
+ const { MCPInstrumentation: MCPInstrumentation2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
1029
+ const mcp = new MCPInstrumentation2({ exceptionLogger });
1030
+ registerInstrumentations({ instrumentations: [mcp] });
1031
+ logger.debug("Auto-loaded MCP instrumentation");
1032
+ } catch (error) {
1033
+ logger.debug(
1034
+ `MCP instrumentation not loaded (install @modelcontextprotocol/sdk and @arizeai/openinference-instrumentation-mcp if you want MCP support): ${String(error)}`
1035
+ );
1036
+ }
1037
+ })();
1038
+ }
219
1039
  function autoInitializeInstrumentations() {
220
1040
  if (autoInstrumentationsLoaded) {
221
1041
  return;
@@ -223,6 +1043,7 @@ function autoInitializeInstrumentations() {
223
1043
  try {
224
1044
  const nodeInstrumentations = loadNodeAutoInstrumentations();
225
1045
  const genAIInstrumentations = loadGenAIInstrumentations();
1046
+ loadMCPInstrumentation();
226
1047
  autoInstrumentationsLoaded = true;
227
1048
  logger.info(
228
1049
  `Auto-initialization complete: ${nodeInstrumentations.length} node + ${genAIInstrumentations.length} GenAI instrumentations`
@@ -238,7 +1059,40 @@ autoInitializeInstrumentations();
238
1059
  import { resourceFromAttributes as resourceFromAttributes3 } from "@opentelemetry/resources";
239
1060
  import { NodeSDK } from "@opentelemetry/sdk-node";
240
1061
 
1062
+ // src/internal/dsn.ts
1063
+ var PLACEHOLDER_SERVICE = "<service-name>";
1064
+ var SERVICE_NAME_HEADER = "X-Brizz-Service-Name";
1065
+ function parseDSN(dsn) {
1066
+ let parsed;
1067
+ try {
1068
+ parsed = new globalThis.URL(dsn);
1069
+ } catch {
1070
+ return null;
1071
+ }
1072
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || !parsed.username || !parsed.host) {
1073
+ return null;
1074
+ }
1075
+ const scheme = parsed.protocol === "https:" ? "https" : "http";
1076
+ let service;
1077
+ try {
1078
+ service = decodeURIComponent(parsed.pathname.replace(/^\//, ""));
1079
+ } catch {
1080
+ return null;
1081
+ }
1082
+ if (service === "" || service === PLACEHOLDER_SERVICE) {
1083
+ return null;
1084
+ }
1085
+ return {
1086
+ scheme,
1087
+ host: parsed.host,
1088
+ bearer: decodeURIComponent(parsed.username),
1089
+ service,
1090
+ baseUrl: `${scheme}://${parsed.host}`
1091
+ };
1092
+ }
1093
+
241
1094
  // src/internal/config.ts
1095
+ init_logger();
242
1096
  function resolveConfig(options) {
243
1097
  const envLogLevel = process.env["BRIZZ_LOG_LEVEL"] || options.logLevel?.toString() || DEFAULT_LOG_LEVEL.toString();
244
1098
  let resolvedLogLevel;
@@ -264,6 +1118,7 @@ function resolveConfig(options) {
264
1118
  appName: options.appName,
265
1119
  baseUrl: options.baseUrl,
266
1120
  hasApiKey: !!options.apiKey,
1121
+ dsnProvided: !!(process.env["BRIZZ_DSN"] || options.dsn),
267
1122
  disableBatch: options.disableBatch,
268
1123
  logLevel: resolvedLogLevel,
269
1124
  headersCount: Object.keys(options.headers || {}).length,
@@ -291,7 +1146,42 @@ function resolveConfig(options) {
291
1146
  logLevel: resolvedLogLevel,
292
1147
  masking: resolvedMasking
293
1148
  };
294
- if (resolvedConfig.apiKey) {
1149
+ const dsnInput = process.env["BRIZZ_DSN"] || options.dsn;
1150
+ let parsedDSN = null;
1151
+ if (dsnInput) {
1152
+ const kwargConflicts = [];
1153
+ if (options.apiKey !== void 0) {
1154
+ kwargConflicts.push("apiKey");
1155
+ }
1156
+ if (options.baseUrl !== void 0) {
1157
+ kwargConflicts.push("baseUrl");
1158
+ }
1159
+ if (options.appName !== void 0) {
1160
+ kwargConflicts.push("appName");
1161
+ }
1162
+ if (kwargConflicts.length > 0) {
1163
+ throw new Error(
1164
+ `dsn cannot be combined with kwargs ${kwargConflicts.join(", ")}. The DSN bundles bearer, gateway URL, and service name \u2014 choose one configuration style.`
1165
+ );
1166
+ }
1167
+ const envConflicts = ["BRIZZ_API_KEY", "BRIZZ_BASE_URL", "BRIZZ_APP_NAME"].filter(
1168
+ (name) => process.env[name] !== void 0
1169
+ );
1170
+ if (envConflicts.length > 0) {
1171
+ logger.warn(
1172
+ `Ignoring ${envConflicts.join(", ")} \u2014 dsn / BRIZZ_DSN takes precedence.`
1173
+ );
1174
+ }
1175
+ resolvedConfig.apiKey = void 0;
1176
+ resolvedConfig.baseUrl = "https://telemetry.brizz.dev";
1177
+ resolvedConfig.appName = "unknown-app";
1178
+ parsedDSN = parseDSN(dsnInput);
1179
+ if (parsedDSN) {
1180
+ resolvedConfig.appName = parsedDSN.service;
1181
+ resolvedConfig.baseUrl = parsedDSN.baseUrl;
1182
+ resolvedConfig.apiKey = parsedDSN.bearer;
1183
+ }
1184
+ } else if (resolvedConfig.apiKey) {
295
1185
  resolvedConfig.headers["Authorization"] = `Bearer ${resolvedConfig.apiKey}`;
296
1186
  }
297
1187
  if (process.env["BRIZZ_HEADERS"]) {
@@ -306,14 +1196,28 @@ function resolveConfig(options) {
306
1196
  throw new Error("Invalid JSON in BRIZZ_HEADERS environment variable", { cause: error });
307
1197
  }
308
1198
  }
1199
+ if (dsnInput) {
1200
+ const authHeaderKeys = /* @__PURE__ */ new Set(["authorization", SERVICE_NAME_HEADER.toLowerCase()]);
1201
+ resolvedConfig.headers = Object.fromEntries(
1202
+ Object.entries(resolvedConfig.headers).filter(
1203
+ ([key]) => !authHeaderKeys.has(key.toLowerCase())
1204
+ )
1205
+ );
1206
+ if (parsedDSN) {
1207
+ resolvedConfig.headers["Authorization"] = `Bearer ${parsedDSN.bearer}`;
1208
+ resolvedConfig.headers[SERVICE_NAME_HEADER] = parsedDSN.service;
1209
+ }
1210
+ }
309
1211
  logger.debug("Configuration resolved with environment variables", {
310
1212
  appName: resolvedConfig.appName,
311
1213
  baseUrl: resolvedConfig.baseUrl,
312
1214
  hasApiKey: !!resolvedConfig.apiKey,
1215
+ dsnProvided: !!dsnInput,
313
1216
  disableBatch: resolvedConfig.disableBatch,
314
1217
  envOverrides: {
315
1218
  hasEnvApiKey: !!process.env["BRIZZ_API_KEY"],
316
1219
  hasEnvBaseUrl: !!process.env["BRIZZ_BASE_URL"],
1220
+ hasEnvDsn: !!process.env["BRIZZ_DSN"],
317
1221
  hasEnvBatch: !!process.env["BRIZZ_DISABLE_BATCH"],
318
1222
  hasEnvHeaders: !!process.env["BRIZZ_HEADERS"]
319
1223
  }
@@ -327,6 +1231,8 @@ var BRIZZ_SDK_LANGUAGE = "brizz.sdk.language";
327
1231
  var SDK_LANGUAGE = "typescript";
328
1232
 
329
1233
  // src/internal/instrumentation/registry.ts
1234
+ init_logger();
1235
+ init_mcp();
330
1236
  import { AnthropicInstrumentation as AnthropicInstrumentation2 } from "@traceloop/instrumentation-anthropic";
331
1237
  import { BedrockInstrumentation as BedrockInstrumentation2 } from "@traceloop/instrumentation-bedrock";
332
1238
  import { ChromaDBInstrumentation as ChromaDBInstrumentation2 } from "@traceloop/instrumentation-chromadb";
@@ -441,6 +1347,14 @@ var InstrumentationRegistry = class _InstrumentationRegistry {
441
1347
  }
442
1348
  })();
443
1349
  }
1350
+ if (this.manualModules?.mcp) {
1351
+ try {
1352
+ new MCPInstrumentation({ exceptionLogger: exceptionLogger2 }).manuallyInstrument(this.manualModules.mcp);
1353
+ logger.debug("Manual instrumentation enabled for MCP");
1354
+ } catch (error) {
1355
+ logger.error(`Failed to apply MCP instrumentation: ${String(error)}`);
1356
+ }
1357
+ }
444
1358
  }
445
1359
  };
446
1360
 
@@ -451,33 +1365,21 @@ import { resourceFromAttributes } from "@opentelemetry/resources";
451
1365
  import {
452
1366
  LoggerProvider
453
1367
  } from "@opentelemetry/sdk-logs";
454
-
455
- // src/internal/version.ts
456
- function getSDKVersion() {
457
- return "0.1.21";
458
- }
1368
+ init_logger();
1369
+ init_version();
459
1370
 
460
1371
  // src/internal/log/processors/log-processor.ts
461
- import { context } from "@opentelemetry/api";
1372
+ init_logger();
1373
+ import { context as context3 } from "@opentelemetry/api";
462
1374
  import { BatchLogRecordProcessor, SimpleLogRecordProcessor } from "@opentelemetry/sdk-logs";
463
1375
 
464
1376
  // src/internal/masking/patterns.ts
465
1377
  var DEFAULT_PII_PATTERNS = [
466
- // Email addresses
467
- {
468
- name: "email_addresses",
469
- pattern: String.raw`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`
470
- },
471
1378
  // Phone numbers (US format)
472
1379
  {
473
1380
  name: "us_phone_numbers",
474
1381
  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]|$)`
475
1382
  },
476
- // Social Security Numbers
477
- {
478
- name: "ssn",
479
- pattern: String.raw`\b(?!000|666|9\d{2})\d{3}[-\s]?(?!00)\d{2}[-\s]?(?!0000)\d{4}\b`
480
- },
481
1383
  // Credit card numbers
482
1384
  {
483
1385
  name: "credit_cards",
@@ -501,19 +1403,11 @@ var DEFAULT_PII_PATTERNS = [
501
1403
  name: "openai_keys",
502
1404
  pattern: String.raw`\bsk[-_][a-zA-Z0-9]{20,}\b`
503
1405
  },
504
- {
505
- name: "base64_secrets",
506
- pattern: String.raw`\b[A-Za-z0-9+/]{64,}={0,2}\b`
507
- },
508
1406
  // AWS Keys
509
1407
  {
510
1408
  name: "aws_access_keys",
511
1409
  pattern: String.raw`\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b`
512
1410
  },
513
- {
514
- name: "aws_secret_keys",
515
- 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`
516
- },
517
1411
  // GitHub tokens
518
1412
  {
519
1413
  name: "github_tokens",
@@ -544,11 +1438,6 @@ var DEFAULT_PII_PATTERNS = [
544
1438
  name: "ipv6_addresses",
545
1439
  pattern: String.raw`\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b`
546
1440
  },
547
- // Medical records
548
- {
549
- name: "medical_record_numbers",
550
- pattern: String.raw`\b(?:[Mm][Rr][Nn])[-\s]?\d{6,10}\b`
551
- },
552
1441
  // Bitcoin addresses
553
1442
  {
554
1443
  name: "bitcoin_addresses",
@@ -559,11 +1448,6 @@ var DEFAULT_PII_PATTERNS = [
559
1448
  name: "ethereum_addresses",
560
1449
  pattern: String.raw`\b0x[a-fA-F0-9]{40}(?![a-fA-F0-9])\b`
561
1450
  },
562
- // UUIDs
563
- {
564
- name: "uuids",
565
- 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`
566
- },
567
1451
  // Database connection strings
568
1452
  {
569
1453
  name: "database_connections",
@@ -582,90 +1466,6 @@ var DEFAULT_PII_PATTERNS = [
582
1466
  name: "certificates",
583
1467
  pattern: "-----BEGIN CERTIFICATE-----"
584
1468
  },
585
- // Date of birth patterns
586
- {
587
- name: "date_of_birth_us",
588
- pattern: String.raw`\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])[-/](?:19|20)\\d{2}\b`
589
- },
590
- {
591
- name: "date_of_birth_iso",
592
- pattern: String.raw`\b(?:19|20)\\d{2}[-/](?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])\b`
593
- },
594
- // US Identification Numbers
595
- {
596
- name: "us_passport_numbers",
597
- pattern: String.raw`\b[A-Z]?\\d{6,9}\b`
598
- },
599
- {
600
- name: "drivers_license",
601
- 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`
602
- },
603
- {
604
- name: "bank_account_numbers",
605
- pattern: String.raw`\b\\d{10,17}\b`
606
- },
607
- {
608
- name: "aba_routing_numbers",
609
- 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`
610
- },
611
- {
612
- name: "health_insurance_numbers",
613
- pattern: String.raw`\b\\d{10}[A-Z]\b`
614
- },
615
- {
616
- name: "employee_ids",
617
- pattern: String.raw`\b(?:[Ee][Mm][Pp]|[Ee][Mm][Pp][Ll][Oo][Yy][Ee][Ee]|[Ee])[-\s]?\\d{5,8}\b`
618
- },
619
- {
620
- name: "tax_ein",
621
- pattern: String.raw`\b\\d{2}-\\d{7}\b`
622
- },
623
- {
624
- name: "medicare_beneficiary_id",
625
- 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`
626
- },
627
- {
628
- name: "national_provider_id",
629
- pattern: String.raw`\b1\\d{9}\b`
630
- },
631
- {
632
- name: "dea_numbers",
633
- pattern: String.raw`\b[A-Z]{2}\\d{7}\b`
634
- },
635
- {
636
- name: "itin",
637
- pattern: String.raw`\b9\\d{2}(?:[ \\-]?)[7,8]\\d(?:[ \\-]?)\\d{4}\b`
638
- },
639
- // Vehicle and Location
640
- {
641
- name: "vin_numbers",
642
- pattern: String.raw`\b[A-HJ-NPR-Z0-9]{17}\b`
643
- },
644
- {
645
- name: "coordinates",
646
- pattern: String.raw`\b[-+]?(?:[0-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?),\\s*[-+]?(?:1[0-7]\\d(?:\\.\\d+)?|180(?:\\.0+)?|[0-9]?\\d(?:\\.\\d+)?)\b`
647
- },
648
- {
649
- name: "us_license_plates",
650
- 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`
651
- },
652
- {
653
- name: "us_zip_codes",
654
- pattern: String.raw`\b(\\d{5}-\\d{4}|\\d{5})\b`
655
- },
656
- {
657
- name: "us_street_addresses",
658
- 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`
659
- },
660
- // International Banking
661
- {
662
- name: "iban",
663
- pattern: String.raw`\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}([A-Z0-9]?){0,16}\b`
664
- },
665
- {
666
- name: "swift_bic",
667
- pattern: String.raw`\b[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?\b`
668
- },
669
1469
  // Additional API Keys and Tokens
670
1470
  {
671
1471
  name: "google_oauth",
@@ -728,73 +1528,6 @@ var DEFAULT_PII_PATTERNS = [
728
1528
  name: "putty_ssh_keys",
729
1529
  pattern: String.raw`PuTTY-User-Key-File-2: ssh-(?:rsa|dss)\s*Encryption: none(?:.|\s?)*?Private-MAC:`
730
1530
  },
731
- // International Phone Numbers
732
- {
733
- name: "france_phone_numbers",
734
- pattern: String.raw`\b([0O]?[1lI][1lI])?[3E][3E][0O]?[\\dOIlZEASB]{9}\b`
735
- },
736
- {
737
- name: "german_phone_numbers",
738
- pattern: String.raw`\b[\d\w]\d{2}[\d\w]{6}\d[\d\w]\b`
739
- },
740
- {
741
- name: "uk_phone_numbers",
742
- pattern: String.raw`\b([0O]?[1lI][1lI])?[4A][4A][\\dOIlZEASB]{10,11}\b`
743
- },
744
- // International IDs
745
- {
746
- name: "uk_drivers_license",
747
- pattern: String.raw`\b[A-Z]{5}\d{6}[A-Z]{2}\d{1}[A-Z]{2}\b`
748
- },
749
- {
750
- name: "uk_passport",
751
- pattern: String.raw`\b\\d{10}GB[RP]\\d{7}[UMF]{1}\\d{9}\b`
752
- },
753
- {
754
- name: "argentina_dni",
755
- pattern: String.raw`\b\\d{2}\\.\\d{3}\\.\\d{3}\b`
756
- },
757
- {
758
- name: "australia_tfn",
759
- pattern: String.raw`\b[Tt][Ff][Nn](:|:\\s|\\s|)(\\d{8,9})\b`
760
- },
761
- {
762
- name: "canada_passport",
763
- pattern: String.raw`\b[\\w]{2}[\\d]{6}\b`
764
- },
765
- {
766
- name: "croatia_vat",
767
- pattern: String.raw`\bHR\\d{11}\b`
768
- },
769
- {
770
- name: "czech_vat",
771
- pattern: String.raw`\bCZ\\d{8,10}\b`
772
- },
773
- {
774
- name: "denmark_personal_id",
775
- pattern: String.raw`\b(?:\\d{10}|\\d{6}[-\\s]\\d{4})\b`
776
- },
777
- {
778
- name: "france_national_id",
779
- pattern: String.raw`\b\\d{12}\b`
780
- },
781
- {
782
- name: "france_ssn",
783
- pattern: String.raw`\b(?:\\d{13}|\\d{13}\\s\\d{2})\b`
784
- },
785
- {
786
- name: "france_passport",
787
- pattern: String.raw`\b\\d{2}11\\d{5}\b`
788
- },
789
- {
790
- name: "california_drivers_license",
791
- pattern: String.raw`\b[A-Z]{1}\\d{7}\b`
792
- },
793
- // Medical and Healthcare
794
- {
795
- name: "hipaa_ndc",
796
- pattern: String.raw`\b\\d{4,5}-\\d{3,4}-\\d{1,2}\b`
797
- },
798
1531
  // Security and Network
799
1532
  {
800
1533
  name: "cve_numbers",
@@ -828,48 +1561,11 @@ var DEFAULT_PII_PATTERNS = [
828
1561
  {
829
1562
  name: "discover_cards",
830
1563
  pattern: String.raw`\b65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}\b`
831
- },
832
- {
833
- name: "enhanced_credit_cards",
834
- 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`
835
- },
836
- // Bank Routing Numbers (US specific)
837
- {
838
- name: "bbva_routing_ca",
839
- pattern: String.raw`\\b321170538\\b`
840
- },
841
- {
842
- name: "boa_routing_ca",
843
- pattern: String.raw`\\b(?:121|026)00(?:0|9)(?:358|593)\\b`
844
- },
845
- {
846
- name: "chase_routing_ca",
847
- pattern: String.raw`\\b322271627\\b`
848
- },
849
- {
850
- name: "citibank_routing_ca",
851
- pattern: String.raw`\\b32(?:11|22)71(?:18|72)4\\b`
852
- },
853
- {
854
- name: "usbank_routing_ca",
855
- pattern: String.raw`\\b12(?:1122676|2235821)\\b`
856
- },
857
- {
858
- name: "united_bank_routing_ca",
859
- pattern: String.raw`\\b122243350\\b`
860
- },
861
- {
862
- name: "wells_fargo_routing_ca",
863
- pattern: String.raw`\\b121042882\\b`
864
- },
865
- // Unrealistic alphanumeric identifiers
866
- {
867
- name: "generic_non_usual",
868
- pattern: String.raw`(?:^|\s)(?=[A-Za-z0-9_\)\*\=@]*[A-Za-z])(?=[A-Za-z0-9_\)\*\=@]*[0-9])([A-Za-z0-9_\)\*\=@]{5,})(?=\s|$)`
869
1564
  }
870
1565
  ];
871
1566
 
872
1567
  // src/internal/masking/utils.ts
1568
+ init_logger();
873
1569
  function isValidPatternName(name) {
874
1570
  return /^[a-zA-Z0-9_]+$/.test(name);
875
1571
  }
@@ -1085,23 +1781,8 @@ function maskAttributes(attributes, rules, outputOriginalValue = false) {
1085
1781
  return maskedAttributes;
1086
1782
  }
1087
1783
 
1088
- // src/internal/semantic-conventions.ts
1089
- import { createContextKey } from "@opentelemetry/api";
1090
- var BRIZZ = "brizz";
1091
- var PROPERTIES = "properties";
1092
- var SESSION_ID = "session.id";
1093
- var PROPERTIES_CONTEXT_KEY = createContextKey(PROPERTIES);
1094
- var SESSION_OBJECT_CONTEXT_KEY = createContextKey("brizz.session.object");
1095
- var SESSION_INPUT = "brizz.session.input";
1096
- var SESSION_OUTPUT = "brizz.session.output";
1097
- var SESSION_INPUT_CONTEXT = "brizz.session.input.context";
1098
- var SESSION_OUTPUT_CONTEXT = "brizz.session.output.context";
1099
- var SESSION_SPAN_NAME = "brizz.start_session";
1100
- var SESSION_TITLE_SPAN_NAME = "brizz.session_title";
1101
- var SESSION_TITLE_GENERATION = "session.title_generation";
1102
- var SESSION_TITLE = "brizz.session.title";
1103
-
1104
1784
  // src/internal/log/processors/log-processor.ts
1785
+ init_semantic_conventions();
1105
1786
  var DEFAULT_LOG_MASKING_RULES = [
1106
1787
  {
1107
1788
  mode: "partial",
@@ -1120,7 +1801,7 @@ var BrizzSimpleLogRecordProcessor = class extends SimpleLogRecordProcessor {
1120
1801
  if (maskingConfig) {
1121
1802
  maskLog(logRecord, maskingConfig);
1122
1803
  }
1123
- const associationProperties = context.active().getValue(PROPERTIES_CONTEXT_KEY);
1804
+ const associationProperties = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
1124
1805
  if (associationProperties) {
1125
1806
  for (const [key, value] of Object.entries(associationProperties)) {
1126
1807
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1140,7 +1821,7 @@ var BrizzBatchLogRecordProcessor = class extends BatchLogRecordProcessor {
1140
1821
  if (maskingConfig) {
1141
1822
  maskLog(logRecord, maskingConfig);
1142
1823
  }
1143
- const associationProperties = context.active().getValue(PROPERTIES_CONTEXT_KEY);
1824
+ const associationProperties = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
1144
1825
  if (associationProperties) {
1145
1826
  for (const [key, value] of Object.entries(associationProperties)) {
1146
1827
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1359,7 +2040,11 @@ function emitEvent(name, attributes, body, severityNumber = SeverityNumber.INFO)
1359
2040
  return LoggingModule.getInstance().emitEvent(name, attributes, body, severityNumber);
1360
2041
  }
1361
2042
 
2043
+ // src/internal/sdk.ts
2044
+ init_logger();
2045
+
1362
2046
  // src/internal/metric/metrics.ts
2047
+ init_logger();
1363
2048
  import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
1364
2049
  import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
1365
2050
  var MetricsModule = class _MetricsModule {
@@ -1462,11 +2147,14 @@ function getMetricsReader() {
1462
2147
  }
1463
2148
 
1464
2149
  // src/internal/trace/tracing.ts
2150
+ init_logger();
1465
2151
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
1466
2152
 
1467
2153
  // src/internal/trace/exporters/span-exporter.ts
1468
2154
  import { ExportResultCode } from "@opentelemetry/core";
1469
2155
  import { resourceFromAttributes as resourceFromAttributes2 } from "@opentelemetry/resources";
2156
+ init_logger();
2157
+ init_version();
1470
2158
  var BrizzSpanExporter = class {
1471
2159
  _delegate;
1472
2160
  _brizzResource;
@@ -1533,13 +2221,15 @@ var BrizzSpanExporter = class {
1533
2221
  };
1534
2222
 
1535
2223
  // src/internal/trace/processors/span-processor.ts
1536
- import { context as context2 } from "@opentelemetry/api";
2224
+ init_logger();
2225
+ import { context as context4 } from "@opentelemetry/api";
1537
2226
  import {
1538
2227
  BatchSpanProcessor,
1539
2228
  SimpleSpanProcessor
1540
2229
  } from "@opentelemetry/sdk-trace-base";
2230
+ init_semantic_conventions();
1541
2231
  function applyContextAttributes(span) {
1542
- const sessionProperties = context2.active().getValue(PROPERTIES_CONTEXT_KEY);
2232
+ const sessionProperties = context4.active().getValue(PROPERTIES_CONTEXT_KEY);
1543
2233
  if (sessionProperties) {
1544
2234
  for (const [key, value] of Object.entries(sessionProperties)) {
1545
2235
  span.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1549,12 +2239,6 @@ function applyContextAttributes(span) {
1549
2239
  var DEFAULT_MASKING_RULES = [
1550
2240
  {
1551
2241
  mode: "partial",
1552
- attributePattern: "gen_ai.prompt",
1553
- patterns: DEFAULT_PII_PATTERNS
1554
- },
1555
- {
1556
- mode: "partial",
1557
- attributePattern: "gen_ai.completion",
1558
2242
  patterns: DEFAULT_PII_PATTERNS
1559
2243
  }
1560
2244
  ];
@@ -1564,24 +2248,16 @@ var BrizzSimpleSpanProcessor = class extends SimpleSpanProcessor {
1564
2248
  super(spanExporter);
1565
2249
  this.config = config;
1566
2250
  }
1567
- // Will work with the following code:
1568
- // const span = tracer.startSpan('sensitive-operation',{attributes:{
1569
- // 'user.password': 'secret123',
1570
- // 'user.email': 'user@example.com',
1571
- // }});
1572
- //
1573
- // Won't work because onStart is called before attributes are set:
1574
- // span.setAttributes({
1575
- // 'user.password': 'secret123',
1576
- // 'user.email': 'user@example.com'
1577
- // });
1578
2251
  onStart(span, parentContext) {
2252
+ applyContextAttributes(span);
2253
+ super.onStart(span, parentContext);
2254
+ }
2255
+ onEnd(span) {
1579
2256
  const maskingConfig = this.config.masking?.spanMasking;
1580
2257
  if (maskingConfig) {
1581
- maskSpan(span, maskingConfig);
2258
+ maskReadableSpan(span, maskingConfig);
1582
2259
  }
1583
- applyContextAttributes(span);
1584
- super.onStart(span, parentContext);
2260
+ super.onEnd(span);
1585
2261
  }
1586
2262
  };
1587
2263
  var BrizzBatchSpanProcessor = class extends BatchSpanProcessor {
@@ -1591,39 +2267,39 @@ var BrizzBatchSpanProcessor = class extends BatchSpanProcessor {
1591
2267
  this.config = config;
1592
2268
  }
1593
2269
  onStart(span, parentContext) {
2270
+ applyContextAttributes(span);
2271
+ super.onStart(span, parentContext);
2272
+ }
2273
+ onEnd(span) {
1594
2274
  const maskingConfig = this.config.masking?.spanMasking;
1595
2275
  if (maskingConfig) {
1596
- maskSpan(span, maskingConfig);
2276
+ maskReadableSpan(span, maskingConfig);
1597
2277
  }
1598
- applyContextAttributes(span);
1599
- super.onStart(span, parentContext);
2278
+ super.onEnd(span);
1600
2279
  }
1601
2280
  };
1602
- function maskSpan(span, config) {
1603
- if (!span.attributes || Object.keys(span.attributes).length === 0) {
1604
- return span;
2281
+ function maskReadableSpan(span, config) {
2282
+ const attrs = span.attributes;
2283
+ if (!attrs || Object.keys(attrs).length === 0) {
2284
+ return;
1605
2285
  }
1606
- let rules = config.rules || [];
2286
+ let rules = config.rules ? [...config.rules] : [];
1607
2287
  if (!config.disableDefaultRules) {
1608
- rules = [...DEFAULT_MASKING_RULES, ...rules];
2288
+ rules = [...rules, ...DEFAULT_MASKING_RULES];
1609
2289
  }
1610
2290
  try {
1611
- const attributesRecord = {};
1612
- for (const [key, value] of Object.entries(span.attributes)) {
1613
- attributesRecord[key] = value;
1614
- }
1615
- const maskedAttributes = maskAttributes(attributesRecord, rules);
1616
- if (maskedAttributes && Object.keys(maskedAttributes).length > 0) {
1617
- const merged = { ...span.attributes };
1618
- for (const [key, value] of Object.entries(maskedAttributes)) {
1619
- merged[key] = value;
2291
+ const input = {};
2292
+ for (const [k, v] of Object.entries(attrs)) {
2293
+ input[k] = v;
2294
+ }
2295
+ const masked = maskAttributes(input, rules);
2296
+ for (const [k, v] of Object.entries(masked ?? {})) {
2297
+ if (attrs[k] !== v) {
2298
+ attrs[k] = v;
1620
2299
  }
1621
- span.setAttributes(merged);
1622
2300
  }
1623
- return span;
1624
2301
  } catch (error) {
1625
- logger.error("Error masking span:", error);
1626
- return span;
2302
+ logger.error("Error masking span", { err: error });
1627
2303
  }
1628
2304
  }
1629
2305
 
@@ -1739,13 +2415,26 @@ function getSpanProcessor() {
1739
2415
  }
1740
2416
 
1741
2417
  // src/internal/trace/session.ts
1742
- import { context as context3, trace, SpanStatusCode } from "@opentelemetry/api";
2418
+ init_semantic_conventions();
2419
+ import { context as context5, trace as trace3, SpanStatusCode as SpanStatusCode3 } from "@opentelemetry/api";
2420
+ function setCurrentSpanCustomProperties(properties) {
2421
+ const current = trace3.getActiveSpan();
2422
+ if (!current || !current.isRecording()) {
2423
+ return;
2424
+ }
2425
+ for (const [key, value] of Object.entries(properties)) {
2426
+ try {
2427
+ current.setAttribute(`${BRIZZ}.${key}`, value);
2428
+ } catch {
2429
+ }
2430
+ }
2431
+ }
1743
2432
  function callWithProperties(properties, fn, thisArg, ...args) {
1744
- const base = context3.active();
2433
+ const base = context5.active();
1745
2434
  const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
1746
2435
  const merged = prev ? { ...prev, ...properties } : properties;
1747
2436
  const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
1748
- return context3.with(next, fn, thisArg, ...args);
2437
+ return context5.with(next, fn, thisArg, ...args);
1749
2438
  }
1750
2439
  function withProperties(properties, fn, thisArg) {
1751
2440
  return function wrapped(...args) {
@@ -1787,9 +2476,9 @@ var Session = class {
1787
2476
  * @param text - Text to append (null becomes a null/"hide marker")
1788
2477
  * @param context - Optional per-turn context bag to attach to this turn
1789
2478
  */
1790
- setInput(text, context4) {
2479
+ setInput(text, context6) {
1791
2480
  this.inputs.push(text);
1792
- this.inputContexts.push(context4 ?? {});
2481
+ this.inputContexts.push(context6 ?? {});
1793
2482
  this.span.setAttribute(SESSION_INPUT, JSON.stringify(this.inputs));
1794
2483
  this.span.setAttribute(SESSION_INPUT_CONTEXT, JSON.stringify(this.inputContexts));
1795
2484
  }
@@ -1803,9 +2492,9 @@ var Session = class {
1803
2492
  * @param text - Text to append (null becomes a null/"hide marker")
1804
2493
  * @param context - Optional per-turn context bag to attach to this turn
1805
2494
  */
1806
- setOutput(text, context4) {
2495
+ setOutput(text, context6) {
1807
2496
  this.outputs.push(text);
1808
- this.outputContexts.push(context4 ?? {});
2497
+ this.outputContexts.push(context6 ?? {});
1809
2498
  this.span.setAttribute(SESSION_OUTPUT, JSON.stringify(this.outputs));
1810
2499
  this.span.setAttribute(SESSION_OUTPUT_CONTEXT, JSON.stringify(this.outputContexts));
1811
2500
  }
@@ -1844,12 +2533,12 @@ var SessionTitle = class {
1844
2533
  }
1845
2534
  };
1846
2535
  function getActiveSession() {
1847
- return context3.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
2536
+ return context5.active().getValue(SESSION_OBJECT_CONTEXT_KEY);
1848
2537
  }
1849
2538
  function startSession(sessionId, callback, extraProperties, options) {
1850
2539
  const isTitle = options?.mode === "title";
1851
2540
  const spanName = isTitle ? SESSION_TITLE_SPAN_NAME : SESSION_SPAN_NAME;
1852
- const tracer = trace.getTracer("@brizz/sdk");
2541
+ const tracer = trace3.getTracer("@brizz/sdk");
1853
2542
  return tracer.startActiveSpan(spanName, (span) => {
1854
2543
  span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
1855
2544
  if (extraProperties) {
@@ -1868,8 +2557,8 @@ function startSession(sessionId, callback, extraProperties, options) {
1868
2557
  }
1869
2558
  }
1870
2559
  return callWithProperties(contextProperties, () => {
1871
- const sessionCtx = context3.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
1872
- return context3.with(sessionCtx, () => {
2560
+ const sessionCtx = context5.active().setValue(SESSION_OBJECT_CONTEXT_KEY, session);
2561
+ return context5.with(sessionCtx, () => {
1873
2562
  try {
1874
2563
  const result = callback(session);
1875
2564
  if (result && typeof result.then === "function") {
@@ -1878,7 +2567,7 @@ function startSession(sessionId, callback, extraProperties, options) {
1878
2567
  return value;
1879
2568
  }).catch((error) => {
1880
2569
  span.recordException(error);
1881
- span.setStatus({ code: SpanStatusCode.ERROR });
2570
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1882
2571
  span.end();
1883
2572
  throw error;
1884
2573
  });
@@ -1887,7 +2576,7 @@ function startSession(sessionId, callback, extraProperties, options) {
1887
2576
  return result;
1888
2577
  } catch (error) {
1889
2578
  span.recordException(error);
1890
- span.setStatus({ code: SpanStatusCode.ERROR });
2579
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1891
2580
  span.end();
1892
2581
  throw error;
1893
2582
  }
@@ -1897,7 +2586,7 @@ function startSession(sessionId, callback, extraProperties, options) {
1897
2586
  }
1898
2587
  function startSessionTitle(callback, options) {
1899
2588
  const resolvedSessionId = options?.sessionId ?? getActiveSession()?.sessionId;
1900
- const tracer = trace.getTracer("@brizz/sdk");
2589
+ const tracer = trace3.getTracer("@brizz/sdk");
1901
2590
  return tracer.startActiveSpan(SESSION_TITLE_SPAN_NAME, (span) => {
1902
2591
  if (resolvedSessionId) {
1903
2592
  span.setAttribute(`${BRIZZ}.${SESSION_ID}`, resolvedSessionId);
@@ -1916,7 +2605,7 @@ function startSessionTitle(callback, options) {
1916
2605
  return value;
1917
2606
  }).catch((error) => {
1918
2607
  span.recordException(error);
1919
- span.setStatus({ code: SpanStatusCode.ERROR });
2608
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1920
2609
  span.end();
1921
2610
  throw error;
1922
2611
  });
@@ -1925,7 +2614,7 @@ function startSessionTitle(callback, options) {
1925
2614
  return result;
1926
2615
  } catch (error) {
1927
2616
  span.recordException(error);
1928
- span.setStatus({ code: SpanStatusCode.ERROR });
2617
+ span.setStatus({ code: SpanStatusCode3.ERROR });
1929
2618
  span.end();
1930
2619
  throw error;
1931
2620
  }
@@ -1934,6 +2623,7 @@ function startSessionTitle(callback, options) {
1934
2623
  }
1935
2624
 
1936
2625
  // src/internal/sdk.ts
2626
+ init_version();
1937
2627
  var _Brizz = class __Brizz {
1938
2628
  static instance = null;
1939
2629
  /** Flag indicating if SDK initialization has completed successfully */
@@ -2131,9 +2821,11 @@ var _Brizz = class __Brizz {
2131
2821
  var Brizz = new _Brizz();
2132
2822
 
2133
2823
  // src/index.ts
2824
+ init_logger();
2134
2825
  import { SeverityNumber as SeverityNumber2 } from "@opentelemetry/api-logs";
2135
2826
 
2136
2827
  // src/node/runtime.ts
2828
+ init_logger();
2137
2829
  function detectRuntime() {
2138
2830
  const [major, minor] = process.versions.node.split(".").map(Number);
2139
2831
  const noNodeJSGlobals = typeof __filename === "undefined" && typeof __dirname === "undefined";
@@ -2202,6 +2894,7 @@ export {
2202
2894
  logger,
2203
2895
  maskAttributes,
2204
2896
  maskValue,
2897
+ setCurrentSpanCustomProperties,
2205
2898
  setLogLevel,
2206
2899
  startSession,
2207
2900
  startSessionTitle,