@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/preload.js CHANGED
@@ -142,6 +142,38 @@ function setLogLevel(level) {
142
142
  import { resourceFromAttributes as resourceFromAttributes3 } from "@opentelemetry/resources";
143
143
  import { NodeSDK } from "@opentelemetry/sdk-node";
144
144
 
145
+ // src/internal/dsn.ts
146
+ var PLACEHOLDER_SERVICE = "<service-name>";
147
+ var SERVICE_NAME_HEADER = "X-Brizz-Service-Name";
148
+ function parseDSN(dsn) {
149
+ let parsed;
150
+ try {
151
+ parsed = new globalThis.URL(dsn);
152
+ } catch {
153
+ return null;
154
+ }
155
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || !parsed.username || !parsed.host) {
156
+ return null;
157
+ }
158
+ const scheme = parsed.protocol === "https:" ? "https" : "http";
159
+ let service;
160
+ try {
161
+ service = decodeURIComponent(parsed.pathname.replace(/^\//, ""));
162
+ } catch {
163
+ return null;
164
+ }
165
+ if (service === "" || service === PLACEHOLDER_SERVICE) {
166
+ return null;
167
+ }
168
+ return {
169
+ scheme,
170
+ host: parsed.host,
171
+ bearer: decodeURIComponent(parsed.username),
172
+ service,
173
+ baseUrl: `${scheme}://${parsed.host}`
174
+ };
175
+ }
176
+
145
177
  // src/internal/config.ts
146
178
  function resolveConfig(options) {
147
179
  const envLogLevel = process.env["BRIZZ_LOG_LEVEL"] || options.logLevel?.toString() || DEFAULT_LOG_LEVEL.toString();
@@ -168,6 +200,7 @@ function resolveConfig(options) {
168
200
  appName: options.appName,
169
201
  baseUrl: options.baseUrl,
170
202
  hasApiKey: !!options.apiKey,
203
+ dsnProvided: !!(process.env["BRIZZ_DSN"] || options.dsn),
171
204
  disableBatch: options.disableBatch,
172
205
  logLevel: resolvedLogLevel,
173
206
  headersCount: Object.keys(options.headers || {}).length,
@@ -195,7 +228,42 @@ function resolveConfig(options) {
195
228
  logLevel: resolvedLogLevel,
196
229
  masking: resolvedMasking
197
230
  };
198
- if (resolvedConfig.apiKey) {
231
+ const dsnInput = process.env["BRIZZ_DSN"] || options.dsn;
232
+ let parsedDSN = null;
233
+ if (dsnInput) {
234
+ const kwargConflicts = [];
235
+ if (options.apiKey !== void 0) {
236
+ kwargConflicts.push("apiKey");
237
+ }
238
+ if (options.baseUrl !== void 0) {
239
+ kwargConflicts.push("baseUrl");
240
+ }
241
+ if (options.appName !== void 0) {
242
+ kwargConflicts.push("appName");
243
+ }
244
+ if (kwargConflicts.length > 0) {
245
+ throw new Error(
246
+ `dsn cannot be combined with kwargs ${kwargConflicts.join(", ")}. The DSN bundles bearer, gateway URL, and service name \u2014 choose one configuration style.`
247
+ );
248
+ }
249
+ const envConflicts = ["BRIZZ_API_KEY", "BRIZZ_BASE_URL", "BRIZZ_APP_NAME"].filter(
250
+ (name) => process.env[name] !== void 0
251
+ );
252
+ if (envConflicts.length > 0) {
253
+ logger.warn(
254
+ `Ignoring ${envConflicts.join(", ")} \u2014 dsn / BRIZZ_DSN takes precedence.`
255
+ );
256
+ }
257
+ resolvedConfig.apiKey = void 0;
258
+ resolvedConfig.baseUrl = "https://telemetry.brizz.dev";
259
+ resolvedConfig.appName = "unknown-app";
260
+ parsedDSN = parseDSN(dsnInput);
261
+ if (parsedDSN) {
262
+ resolvedConfig.appName = parsedDSN.service;
263
+ resolvedConfig.baseUrl = parsedDSN.baseUrl;
264
+ resolvedConfig.apiKey = parsedDSN.bearer;
265
+ }
266
+ } else if (resolvedConfig.apiKey) {
199
267
  resolvedConfig.headers["Authorization"] = `Bearer ${resolvedConfig.apiKey}`;
200
268
  }
201
269
  if (process.env["BRIZZ_HEADERS"]) {
@@ -210,14 +278,28 @@ function resolveConfig(options) {
210
278
  throw new Error("Invalid JSON in BRIZZ_HEADERS environment variable", { cause: error });
211
279
  }
212
280
  }
281
+ if (dsnInput) {
282
+ const authHeaderKeys = /* @__PURE__ */ new Set(["authorization", SERVICE_NAME_HEADER.toLowerCase()]);
283
+ resolvedConfig.headers = Object.fromEntries(
284
+ Object.entries(resolvedConfig.headers).filter(
285
+ ([key]) => !authHeaderKeys.has(key.toLowerCase())
286
+ )
287
+ );
288
+ if (parsedDSN) {
289
+ resolvedConfig.headers["Authorization"] = `Bearer ${parsedDSN.bearer}`;
290
+ resolvedConfig.headers[SERVICE_NAME_HEADER] = parsedDSN.service;
291
+ }
292
+ }
213
293
  logger.debug("Configuration resolved with environment variables", {
214
294
  appName: resolvedConfig.appName,
215
295
  baseUrl: resolvedConfig.baseUrl,
216
296
  hasApiKey: !!resolvedConfig.apiKey,
297
+ dsnProvided: !!dsnInput,
217
298
  disableBatch: resolvedConfig.disableBatch,
218
299
  envOverrides: {
219
300
  hasEnvApiKey: !!process.env["BRIZZ_API_KEY"],
220
301
  hasEnvBaseUrl: !!process.env["BRIZZ_BASE_URL"],
302
+ hasEnvDsn: !!process.env["BRIZZ_DSN"],
221
303
  hasEnvBatch: !!process.env["BRIZZ_DISABLE_BATCH"],
222
304
  hasEnvHeaders: !!process.env["BRIZZ_HEADERS"]
223
305
  }
@@ -241,6 +323,716 @@ import { PineconeInstrumentation } from "@traceloop/instrumentation-pinecone";
241
323
  import { QdrantInstrumentation } from "@traceloop/instrumentation-qdrant";
242
324
  import { TogetherInstrumentation } from "@traceloop/instrumentation-together";
243
325
  import { VertexAIInstrumentation } from "@traceloop/instrumentation-vertexai";
326
+
327
+ // src/internal/instrumentation/mcp/instrumentation.ts
328
+ import { MCPInstrumentation as BaseMCPInstrumentation } from "@arizeai/openinference-instrumentation-mcp";
329
+ import { trace as trace2 } from "@opentelemetry/api";
330
+ import { InstrumentationNodeModuleDefinition } from "@opentelemetry/instrumentation";
331
+
332
+ // src/internal/instrumentation/mcp/patches/protocol.ts
333
+ import { context as context2, propagation, SpanKind as SpanKind2, trace } from "@opentelemetry/api";
334
+
335
+ // src/internal/instrumentation/mcp/schemas.ts
336
+ import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
337
+
338
+ // src/internal/semantic-conventions.ts
339
+ import { createContextKey } from "@opentelemetry/api";
340
+ var BRIZZ = "brizz";
341
+ var PROPERTIES = "properties";
342
+ var SESSION_ID = "session.id";
343
+ var PROPERTIES_CONTEXT_KEY = createContextKey(PROPERTIES);
344
+ var SESSION_OBJECT_CONTEXT_KEY = createContextKey("brizz.session.object");
345
+
346
+ // src/internal/instrumentation/mcp/semantic-conventions.ts
347
+ var MCP_TOOL_NAME = "mcp.tool.name";
348
+ var MCP_TOOL_ARGUMENTS = "mcp.tool.arguments";
349
+ var MCP_TOOL_RESULT = "mcp.tool.result";
350
+ var MCP_COMPONENT_TYPE = "mcp.component.type";
351
+ var MCP_COMPONENT_TOOL = "tool";
352
+ var MCP_COMPONENT_TOOL_SCHEMA = "tool_schema";
353
+ var MCP_TOOL_SCHEMA_PARAMETERS = "mcp.tool.schema.parameters";
354
+ var MCP_TOOL_SCHEMA_OUTPUT = "mcp.tool.schema.output";
355
+ var MCP_TOOL_DESCRIPTION = "mcp.tool.description";
356
+ var SPAN_NAME_TOOL_REGISTER = "mcp.tool.register";
357
+ var MCP_METHOD_NAME = "mcp.method.name";
358
+ var MCP_REQUEST_ID = "mcp.request.id";
359
+ var MCP_SESSION_ID = "mcp.session.id";
360
+ var MCP_PROTOCOL_VERSION = "mcp.protocol.version";
361
+ var MCP_RESOURCE_URI = "mcp.resource.uri";
362
+ var RPC_SYSTEM = "rpc.system";
363
+ var RPC_SYSTEM_MCP = "mcp";
364
+ var RPC_RESPONSE_STATUS_CODE = "rpc.response.status_code";
365
+ var GEN_AI_TOOL_NAME = "gen_ai.tool.name";
366
+ var GEN_AI_PROMPT_NAME = "gen_ai.prompt.name";
367
+ var GEN_AI_OPERATION_NAME = "gen_ai.operation.name";
368
+ var GEN_AI_OPERATION_EXECUTE_TOOL = "execute_tool";
369
+ var NETWORK_TRANSPORT = "network.transport";
370
+ var ERROR_TYPE = "error.type";
371
+ var ERROR_TYPE_TOOL = "tool_error";
372
+ var JSONRPC_REQUEST_ID = "jsonrpc.request.id";
373
+ var SPAN_NAME_TOOLS_CALL = "tools/call";
374
+ var MAX_ATTRIBUTE_LENGTH = 32 * 1024;
375
+ var TRUNCATION_SUFFIX = "\u2026(truncated)";
376
+ var METHOD_TOOLS_CALL = "tools/call";
377
+ var METHOD_TOOLS_LIST = "tools/list";
378
+ var METHOD_RESOURCES_READ = "resources/read";
379
+ var METHOD_PROMPTS_GET = "prompts/get";
380
+ var METHOD_INITIALIZE = "initialize";
381
+
382
+ // src/internal/instrumentation/mcp/schemas.ts
383
+ var _MAX_SCHEMA_ATTR_BYTES = 4e3;
384
+ function truncateSchemaAttr(value) {
385
+ if (value.length <= _MAX_SCHEMA_ATTR_BYTES) {
386
+ return value;
387
+ }
388
+ return `{"_truncated":true,"original_length":${value.length}}`;
389
+ }
390
+ function safeStringify(value) {
391
+ if (value === null || value === void 0) {
392
+ return "";
393
+ }
394
+ try {
395
+ return JSON.stringify(value);
396
+ } catch {
397
+ return "";
398
+ }
399
+ }
400
+ function emitSchemaSpansFromListResponse(result, transportSessionId, tracer) {
401
+ if (!transportSessionId) {
402
+ return;
403
+ }
404
+ const tools = extractTools(result);
405
+ if (tools === void 0) {
406
+ return;
407
+ }
408
+ for (const tool of tools) {
409
+ const name = typeof tool.name === "string" ? tool.name : void 0;
410
+ if (!name) {
411
+ continue;
412
+ }
413
+ const span = tracer.startSpan(`${SPAN_NAME_TOOL_REGISTER} ${name}`, {
414
+ kind: SpanKind.INTERNAL
415
+ });
416
+ try {
417
+ stampSchemaAttributes(span, name, transportSessionId, tool);
418
+ span.setStatus({ code: SpanStatusCode.OK });
419
+ } finally {
420
+ span.end();
421
+ }
422
+ }
423
+ }
424
+ function stampSchemaAttributes(span, toolName, transportSessionId, tool) {
425
+ if (!span.isRecording()) {
426
+ logger.warn(
427
+ `Brizz MCP: schema span is not recording; dropping attributes for ${toolName}`
428
+ );
429
+ return;
430
+ }
431
+ const description = typeof tool.description === "string" ? tool.description : "";
432
+ const parameters = truncateSchemaAttr(safeStringify(tool.inputSchema));
433
+ const outputSchema = tool.outputSchema !== void 0 && tool.outputSchema !== null ? truncateSchemaAttr(safeStringify(tool.outputSchema)) : "";
434
+ span.setAttribute(RPC_SYSTEM, RPC_SYSTEM_MCP);
435
+ span.setAttribute(MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL_SCHEMA);
436
+ span.setAttribute(MCP_SESSION_ID, transportSessionId);
437
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, transportSessionId);
438
+ span.setAttribute(MCP_TOOL_NAME, toolName);
439
+ span.setAttribute(MCP_TOOL_SCHEMA_PARAMETERS, parameters);
440
+ span.setAttribute(MCP_TOOL_SCHEMA_OUTPUT, outputSchema);
441
+ span.setAttribute(MCP_TOOL_DESCRIPTION, description);
442
+ }
443
+ function extractTools(result) {
444
+ if (!result || typeof result !== "object") {
445
+ return void 0;
446
+ }
447
+ const tools = result.tools;
448
+ if (!Array.isArray(tools)) {
449
+ return void 0;
450
+ }
451
+ return tools.filter(
452
+ (t) => t !== null && typeof t === "object"
453
+ );
454
+ }
455
+
456
+ // src/internal/instrumentation/mcp/session.ts
457
+ import { context } from "@opentelemetry/api";
458
+ function stampAndPropagateSession(span, sessionId, baseContext = context.active()) {
459
+ if (!sessionId) {
460
+ return { context: baseContext, sessionId: null };
461
+ }
462
+ if (span.isRecording()) {
463
+ try {
464
+ span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
465
+ } catch (error) {
466
+ logger.warn(
467
+ `Brizz MCP: failed to stamp session id on span: ${String(error)}`
468
+ );
469
+ }
470
+ }
471
+ try {
472
+ const prev = baseContext.getValue(PROPERTIES_CONTEXT_KEY);
473
+ const merged = prev ? { ...prev, [SESSION_ID]: sessionId } : { [SESSION_ID]: sessionId };
474
+ return {
475
+ context: baseContext.setValue(PROPERTIES_CONTEXT_KEY, merged),
476
+ sessionId
477
+ };
478
+ } catch (error) {
479
+ logger.warn(`Brizz MCP: failed to attach session context: ${String(error)}`);
480
+ return { context: baseContext, sessionId };
481
+ }
482
+ }
483
+
484
+ // src/internal/instrumentation/mcp/patches/attributes.ts
485
+ import { SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
486
+ function deriveSpanName(method, params) {
487
+ try {
488
+ if (method === METHOD_TOOLS_CALL) {
489
+ const name = typeof params?.["name"] === "string" ? params["name"] : "";
490
+ return name ? `${SPAN_NAME_TOOLS_CALL} ${name}` : SPAN_NAME_TOOLS_CALL;
491
+ }
492
+ if (method === METHOD_RESOURCES_READ) {
493
+ const uri = typeof params?.["uri"] === "string" ? params["uri"] : "";
494
+ return uri ? `${METHOD_RESOURCES_READ} ${uri}` : METHOD_RESOURCES_READ;
495
+ }
496
+ if (method === METHOD_PROMPTS_GET) {
497
+ const name = typeof params?.["name"] === "string" ? params["name"] : "";
498
+ return name ? `${METHOD_PROMPTS_GET} ${name}` : METHOD_PROMPTS_GET;
499
+ }
500
+ return method;
501
+ } catch {
502
+ return method || "mcp";
503
+ }
504
+ }
505
+ function applyBaseAttributes(span, request) {
506
+ span.setAttribute(RPC_SYSTEM, RPC_SYSTEM_MCP);
507
+ if (request.method) {
508
+ span.setAttribute(MCP_METHOD_NAME, request.method);
509
+ }
510
+ if (request.id !== void 0 && request.id !== null) {
511
+ const id = String(request.id);
512
+ span.setAttribute(MCP_REQUEST_ID, id);
513
+ span.setAttribute(JSONRPC_REQUEST_ID, id);
514
+ }
515
+ }
516
+ function applyClientRequestAttributes(span, request, transportName) {
517
+ applyBaseAttributes(span, request);
518
+ applyMethodSpecificRequestAttributes(span, request);
519
+ if (transportName) {
520
+ const transport = normalizeTransport(transportName);
521
+ if (transport) {
522
+ span.setAttribute(NETWORK_TRANSPORT, transport);
523
+ }
524
+ }
525
+ }
526
+ function applyServerRequestAttributes(span, request, protocol) {
527
+ applyBaseAttributes(span, request);
528
+ applyMethodSpecificRequestAttributes(span, request);
529
+ if (request.method === METHOD_TOOLS_CALL) {
530
+ const args = request.params?.["arguments"];
531
+ if (args !== void 0) {
532
+ span.setAttribute(MCP_TOOL_ARGUMENTS, serializeForAttribute(args));
533
+ }
534
+ }
535
+ const sessionId = protocol.sessionId ?? protocol._transport?.sessionId;
536
+ if (sessionId) {
537
+ span.setAttribute(MCP_SESSION_ID, String(sessionId));
538
+ }
539
+ }
540
+ function applyMethodSpecificRequestAttributes(span, request) {
541
+ const params = request.params ?? {};
542
+ switch (request.method) {
543
+ case METHOD_TOOLS_CALL: {
544
+ const name = typeof params["name"] === "string" ? params["name"] : "";
545
+ if (name) {
546
+ span.setAttribute(MCP_TOOL_NAME, name);
547
+ span.setAttribute(GEN_AI_TOOL_NAME, name);
548
+ }
549
+ span.setAttribute(MCP_COMPONENT_TYPE, MCP_COMPONENT_TOOL);
550
+ span.setAttribute(GEN_AI_OPERATION_NAME, GEN_AI_OPERATION_EXECUTE_TOOL);
551
+ break;
552
+ }
553
+ case METHOD_RESOURCES_READ: {
554
+ const uri = typeof params["uri"] === "string" ? params["uri"] : "";
555
+ if (uri) {
556
+ span.setAttribute(MCP_RESOURCE_URI, uri);
557
+ }
558
+ break;
559
+ }
560
+ case METHOD_PROMPTS_GET: {
561
+ const name = typeof params["name"] === "string" ? params["name"] : "";
562
+ if (name) {
563
+ span.setAttribute(GEN_AI_PROMPT_NAME, name);
564
+ }
565
+ break;
566
+ }
567
+ default:
568
+ break;
569
+ }
570
+ }
571
+ function applyResultAttributes(span, method, result) {
572
+ if (method === METHOD_INITIALIZE && result && typeof result === "object") {
573
+ const protocolVersion = result["protocolVersion"];
574
+ if (typeof protocolVersion === "string") {
575
+ span.setAttribute(MCP_PROTOCOL_VERSION, protocolVersion);
576
+ }
577
+ return;
578
+ }
579
+ if (method !== METHOD_TOOLS_CALL) {
580
+ return;
581
+ }
582
+ const obj = result && typeof result === "object" ? result : null;
583
+ const content = obj?.["content"] ?? result;
584
+ span.setAttribute(MCP_TOOL_RESULT, serializeForAttribute(content));
585
+ if (obj && obj["isError"] === true) {
586
+ span.setAttribute(ERROR_TYPE, ERROR_TYPE_TOOL);
587
+ const message = extractToolErrorMessage(obj);
588
+ span.setStatus({ code: SpanStatusCode2.ERROR, message });
589
+ }
590
+ }
591
+ function applyErrorAttributes(span, err) {
592
+ const error = err;
593
+ const code = error?.code;
594
+ if (typeof code === "number") {
595
+ span.setAttribute(RPC_RESPONSE_STATUS_CODE, code);
596
+ span.setAttribute(ERROR_TYPE, String(code));
597
+ } else if (error?.name === "AbortError") {
598
+ span.setAttribute(ERROR_TYPE, "cancelled");
599
+ } else if (error?.name === "TimeoutError") {
600
+ span.setAttribute(ERROR_TYPE, "timeout");
601
+ } else {
602
+ span.setAttribute(
603
+ ERROR_TYPE,
604
+ error?.constructor?.name || error?.name || "Error"
605
+ );
606
+ }
607
+ try {
608
+ span.recordException(error);
609
+ } catch {
610
+ }
611
+ span.setStatus({
612
+ code: SpanStatusCode2.ERROR,
613
+ message: typeof error?.message === "string" ? error.message : void 0
614
+ });
615
+ }
616
+ function serializeForAttribute(value) {
617
+ const raw = rawSerialize(value);
618
+ if (raw.length <= MAX_ATTRIBUTE_LENGTH) {
619
+ return raw;
620
+ }
621
+ return raw.slice(0, MAX_ATTRIBUTE_LENGTH - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX;
622
+ }
623
+ function rawSerialize(value) {
624
+ if (value === null || value === void 0) {
625
+ return "";
626
+ }
627
+ if (typeof value === "string") {
628
+ return value;
629
+ }
630
+ try {
631
+ return JSON.stringify(value);
632
+ } catch {
633
+ try {
634
+ if (value === null || value === void 0) {
635
+ return "";
636
+ }
637
+ const tag = Object.prototype.toString.call(value);
638
+ return typeof value.toString === "function" ? (
639
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
640
+ String(value)
641
+ ) : tag;
642
+ } catch {
643
+ return "";
644
+ }
645
+ }
646
+ }
647
+ function extractToolErrorMessage(result) {
648
+ const content = result["content"];
649
+ if (Array.isArray(content)) {
650
+ for (const item of content) {
651
+ if (item && typeof item === "object") {
652
+ const text = item["text"];
653
+ if (typeof text === "string") {
654
+ return text;
655
+ }
656
+ }
657
+ }
658
+ }
659
+ return void 0;
660
+ }
661
+ function normalizeTransport(ctorName) {
662
+ const name = ctorName.toLowerCase();
663
+ if (name.includes("stdio")) {
664
+ return "stdio";
665
+ }
666
+ if (name.includes("sse")) {
667
+ return "sse";
668
+ }
669
+ if (name.includes("streamablehttp") || name.includes("http")) {
670
+ return "http";
671
+ }
672
+ return null;
673
+ }
674
+
675
+ // src/internal/instrumentation/mcp/patches/protocol.ts
676
+ var PATCHED_FLAG = /* @__PURE__ */ Symbol("brizz.mcp.protocol-patched");
677
+ function patchProtocolPrototype(prototype, tracer) {
678
+ if (!prototype || typeof prototype !== "object") {
679
+ return false;
680
+ }
681
+ const proto = prototype;
682
+ if (proto[PATCHED_FLAG]) {
683
+ logger.debug("Brizz MCP: Protocol.prototype already patched, skipping");
684
+ return false;
685
+ }
686
+ const originalRequest = proto["request"];
687
+ const originalOnRequest = proto["_onrequest"];
688
+ if (typeof originalRequest === "function") {
689
+ proto["request"] = wrapRequest(originalRequest, tracer);
690
+ } else {
691
+ logger.debug(
692
+ "Brizz MCP: Protocol.prototype.request missing \u2014 skipping CLIENT patch"
693
+ );
694
+ }
695
+ if (typeof originalOnRequest === "function") {
696
+ proto["_onrequest"] = wrapOnRequest(
697
+ originalOnRequest,
698
+ tracer
699
+ );
700
+ } else {
701
+ logger.debug(
702
+ "Brizz MCP: Protocol.prototype._onrequest missing \u2014 skipping SERVER patch"
703
+ );
704
+ }
705
+ proto[PATCHED_FLAG] = true;
706
+ return true;
707
+ }
708
+ function wrapRequest(original, tracer) {
709
+ return function wrappedRequest(...args) {
710
+ const request = args[0];
711
+ if (!request || typeof request !== "object" || !request.method) {
712
+ return original.apply(this, args);
713
+ }
714
+ const span = safeStartClientSpan(tracer, request, this);
715
+ if (!span) {
716
+ return original.apply(this, args);
717
+ }
718
+ return executeAroundSpan(span, request.method, () => {
719
+ const ctx = trace.setSpan(context2.active(), span);
720
+ return context2.with(ctx, () => original.apply(this, args));
721
+ });
722
+ };
723
+ }
724
+ function wrapOnRequest(original, tracer) {
725
+ return function wrappedOnRequest(...args) {
726
+ const request = args[0];
727
+ if (!request || typeof request !== "object" || !request.method) {
728
+ return original.apply(this, args);
729
+ }
730
+ const handlers = this._requestHandlers;
731
+ if (!handlers || typeof handlers.get !== "function") {
732
+ return original.apply(this, args);
733
+ }
734
+ const method = request.method;
735
+ const handler = handlers.get(method) ?? this.fallbackRequestHandler;
736
+ if (!handler) {
737
+ return original.apply(this, args);
738
+ }
739
+ const started = safeStartServerSpan(tracer, request, this);
740
+ if (!started) {
741
+ return original.apply(this, args);
742
+ }
743
+ const { span, spanCtx } = started;
744
+ const transportSessionId = this.sessionId ?? this._transport?.sessionId;
745
+ const postResult = method === METHOD_TOOLS_LIST ? (result) => {
746
+ try {
747
+ emitSchemaSpansFromListResponse(result, transportSessionId, tracer);
748
+ } catch (error) {
749
+ logger.warn(
750
+ `Brizz MCP: failed to emit tools/list schema spans: ${String(error)}`
751
+ );
752
+ }
753
+ } : void 0;
754
+ const wrappedHandler = (req, extra) => context2.with(
755
+ spanCtx,
756
+ () => executeHandler(span, method, handler, req, extra, postResult)
757
+ );
758
+ const hadEntry = handlers.has(method);
759
+ const prev = handlers.get(method);
760
+ handlers.set(method, wrappedHandler);
761
+ const usedFallback = !hadEntry && this.fallbackRequestHandler === handler;
762
+ const fallbackPrev = usedFallback ? this.fallbackRequestHandler : void 0;
763
+ if (usedFallback) {
764
+ this.fallbackRequestHandler = wrappedHandler;
765
+ }
766
+ try {
767
+ return original.apply(this, args);
768
+ } finally {
769
+ if (hadEntry) {
770
+ handlers.set(method, prev);
771
+ } else {
772
+ handlers.delete(method);
773
+ }
774
+ if (usedFallback) {
775
+ this.fallbackRequestHandler = fallbackPrev;
776
+ }
777
+ }
778
+ };
779
+ }
780
+ function executeAroundSpan(span, method, run, postResult) {
781
+ let result;
782
+ try {
783
+ result = run();
784
+ } catch (error) {
785
+ safeApplyErrorAttributes(span, error);
786
+ safeEnd(span);
787
+ throw error;
788
+ }
789
+ if (!isThenable(result)) {
790
+ safeApplyResultAttributes(span, method, result);
791
+ if (postResult) {
792
+ postResult(result);
793
+ }
794
+ safeEnd(span);
795
+ return result;
796
+ }
797
+ return result.then(
798
+ (value) => {
799
+ safeApplyResultAttributes(span, method, value);
800
+ if (postResult) {
801
+ postResult(value);
802
+ }
803
+ safeEnd(span);
804
+ return value;
805
+ },
806
+ (error) => {
807
+ safeApplyErrorAttributes(span, error);
808
+ safeEnd(span);
809
+ throw error;
810
+ }
811
+ );
812
+ }
813
+ function executeHandler(span, method, handler, req, extra, postResult) {
814
+ return executeAroundSpan(span, method, () => handler(req, extra), postResult);
815
+ }
816
+ function safeStartClientSpan(tracer, request, protocol) {
817
+ try {
818
+ const spanName = deriveSpanName(request.method, request.params);
819
+ const span = tracer.startSpan(spanName, { kind: SpanKind2.CLIENT });
820
+ applyClientRequestAttributes(
821
+ span,
822
+ request,
823
+ protocol._transport?.constructor?.name
824
+ );
825
+ return span;
826
+ } catch (error) {
827
+ logger.debug(`Brizz MCP: failed to open CLIENT span: ${String(error)}`);
828
+ return null;
829
+ }
830
+ }
831
+ function safeStartServerSpan(tracer, request, protocol) {
832
+ try {
833
+ const parentCtx = extractParentContext(request);
834
+ const spanName = deriveSpanName(request.method, request.params);
835
+ const span = tracer.startSpan(
836
+ spanName,
837
+ { kind: SpanKind2.SERVER },
838
+ parentCtx
839
+ );
840
+ applyServerRequestAttributes(span, request, protocol);
841
+ const sessionId = protocol.sessionId ?? protocol._transport?.sessionId;
842
+ const { context: sessCtx } = stampAndPropagateSession(span, sessionId, parentCtx);
843
+ return { span, spanCtx: trace.setSpan(sessCtx, span) };
844
+ } catch (error) {
845
+ logger.debug(`Brizz MCP: failed to open SERVER span: ${String(error)}`);
846
+ return null;
847
+ }
848
+ }
849
+ function extractParentContext(request) {
850
+ try {
851
+ const meta = request.params?._meta;
852
+ if (meta && typeof meta === "object") {
853
+ return propagation.extract(context2.active(), meta);
854
+ }
855
+ } catch (error) {
856
+ logger.debug(
857
+ `Brizz MCP: failed to extract parent context from _meta: ${String(error)}`
858
+ );
859
+ }
860
+ return context2.active();
861
+ }
862
+ function isThenable(value) {
863
+ return !!value && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
864
+ }
865
+ function safeApplyResultAttributes(span, method, value) {
866
+ try {
867
+ applyResultAttributes(span, method, value);
868
+ } catch (error) {
869
+ logger.debug(
870
+ `Brizz MCP: failed to apply result attributes: ${String(error)}`
871
+ );
872
+ }
873
+ }
874
+ function safeApplyErrorAttributes(span, err) {
875
+ try {
876
+ applyErrorAttributes(span, err);
877
+ } catch (error) {
878
+ logger.debug(
879
+ `Brizz MCP: failed to apply error attributes: ${String(error)}`
880
+ );
881
+ }
882
+ }
883
+ function safeEnd(span) {
884
+ try {
885
+ span.end();
886
+ } catch (error) {
887
+ logger.debug(`Brizz MCP: failed to end span: ${String(error)}`);
888
+ }
889
+ }
890
+
891
+ // src/internal/version.ts
892
+ function getSDKVersion() {
893
+ return "0.1.25";
894
+ }
895
+
896
+ // src/internal/instrumentation/mcp/version.ts
897
+ var INSTRUMENTATION_NAME = "@brizz/sdk/mcp";
898
+ var INSTRUMENTATION_VERSION = getSDKVersion();
899
+
900
+ // src/internal/instrumentation/mcp/instrumentation.ts
901
+ var PROTOCOL_MODULE_NAME = "@modelcontextprotocol/sdk/shared/protocol.js";
902
+ var PROTOCOL_SUPPORTED_VERSIONS = [">=1.0.0 <2"];
903
+ var MCPInstrumentation = class extends BaseMCPInstrumentation {
904
+ /**
905
+ * Dedicated Brizz-named tracer for our SERVER + CLIENT spans.
906
+ *
907
+ * Why a separate tracer from the parent class's one: Arize's inherited
908
+ * transport patches don't emit spans (they only inject propagation
909
+ * headers), so using our own tracer here keeps Brizz spans attributed to
910
+ * `@brizz/sdk/mcp` in the dashboard. The parent's `tracer` is a
911
+ * `protected get` (no setter), so fighting it with assignment is the
912
+ * wrong tool.
913
+ */
914
+ brizzTracer;
915
+ constructor(_config) {
916
+ super({ instrumentationConfig: _config?.instrumentationConfig });
917
+ this.brizzTracer = trace2.getTracer(INSTRUMENTATION_NAME, INSTRUMENTATION_VERSION);
918
+ }
919
+ /**
920
+ * Extend `super.init()` with our protocol-layer module definition.
921
+ *
922
+ * Arize's `init()` returns definitions for the six transport modules
923
+ * (SSE client/server, stdio client/server, streamable-HTTP client/server)
924
+ * whose `send`/`start` methods get patched for W3C trace-context
925
+ * injection. We append one more: `@modelcontextprotocol/sdk/shared/protocol.js`
926
+ * where our patches open SERVER/CLIENT spans around the handler + outgoing
927
+ * request. If `super.init()` throws (unlikely but possible across Arize
928
+ * versions), we gracefully degrade to protocol-only instrumentation.
929
+ *
930
+ * The cast at the end satisfies the parent's strongly-typed generic
931
+ * without leaking the cast into call sites.
932
+ */
933
+ init() {
934
+ let base;
935
+ try {
936
+ base = super.init() ?? [];
937
+ } catch (error) {
938
+ logger.warn(
939
+ `Brizz MCP: base Arize init() failed \u2014 transport context propagation disabled: ${String(error)}`
940
+ );
941
+ base = [];
942
+ }
943
+ const baseArr = Array.isArray(base) ? base : [base];
944
+ const brizzDef = new InstrumentationNodeModuleDefinition(
945
+ PROTOCOL_MODULE_NAME,
946
+ PROTOCOL_SUPPORTED_VERSIONS,
947
+ (module3) => {
948
+ this.patchProtocolModule(module3);
949
+ return module3;
950
+ },
951
+ (module3) => {
952
+ this.unpatchProtocolModule(module3);
953
+ return module3;
954
+ }
955
+ );
956
+ return [...baseArr, brizzDef];
957
+ }
958
+ /**
959
+ * Manually instrument MCP modules for Next.js/Webpack where the
960
+ * auto-instrumentation module-load hook doesn't fire.
961
+ *
962
+ * Forwards the six transport module fields to the inherited Arize
963
+ * `manuallyInstrument(...)` (context propagation) and applies our
964
+ * protocol patch if `protocolModule` is provided (SERVER/CLIENT spans).
965
+ * Both legs are try/catch-guarded — a failure in one shouldn't prevent
966
+ * the other from taking effect.
967
+ */
968
+ manuallyInstrument(modules) {
969
+ const {
970
+ clientSSEModule,
971
+ serverSSEModule,
972
+ clientStdioModule,
973
+ serverStdioModule,
974
+ clientStreamableHTTPModule,
975
+ serverStreamableHTTPModule,
976
+ protocolModule
977
+ } = modules;
978
+ try {
979
+ super.manuallyInstrument({
980
+ clientSSEModule,
981
+ serverSSEModule,
982
+ clientStdioModule,
983
+ serverStdioModule,
984
+ clientStreamableHTTPModule,
985
+ serverStreamableHTTPModule
986
+ });
987
+ } catch (error) {
988
+ logger.warn(`Brizz MCP: Arize manuallyInstrument(...) failed: ${String(error)}`);
989
+ }
990
+ if (protocolModule) {
991
+ try {
992
+ this.patchProtocolModule(protocolModule);
993
+ } catch (error) {
994
+ logger.warn(
995
+ `Brizz MCP: failed to manually patch Protocol module: ${String(error)}`
996
+ );
997
+ }
998
+ }
999
+ }
1000
+ /**
1001
+ * Apply the SERVER + CLIENT patch to a loaded `protocol.js` module. Shared
1002
+ * by both the automatic module-load callback in `init()` and the manual
1003
+ * `manuallyInstrument(...)` path above so there's exactly one place that
1004
+ * calls `patchProtocolPrototype`.
1005
+ */
1006
+ patchProtocolModule(module3) {
1007
+ const proto = module3?.Protocol?.prototype;
1008
+ if (!proto) {
1009
+ logger.debug(
1010
+ "Brizz MCP: module does not expose Protocol.prototype \u2014 skipping protocol patches"
1011
+ );
1012
+ return;
1013
+ }
1014
+ const ok = patchProtocolPrototype(proto, this.brizzTracer);
1015
+ if (ok) {
1016
+ logger.debug("Brizz MCP: patched Protocol.prototype for SERVER+CLIENT spans");
1017
+ }
1018
+ }
1019
+ /**
1020
+ * Unpatch is intentionally a no-op.
1021
+ *
1022
+ * `patchProtocolPrototype` wraps methods in place and sets a PATCHED_FLAG
1023
+ * Symbol on the prototype to prevent double-patching. Restoring the
1024
+ * originals would require us to hold references across module unloads,
1025
+ * which isn't a pattern we need — instrumentation rarely gets torn down
1026
+ * at runtime, and a process reload is the canonical way to detach.
1027
+ */
1028
+ unpatchProtocolModule(_module) {
1029
+ logger.debug(
1030
+ "Brizz MCP: unpatch is a no-op \u2014 reload the process to cleanly detach"
1031
+ );
1032
+ }
1033
+ };
1034
+
1035
+ // src/internal/instrumentation/registry.ts
244
1036
  var InstrumentationRegistry = class _InstrumentationRegistry {
245
1037
  static instance;
246
1038
  manualModules = null;
@@ -345,6 +1137,14 @@ var InstrumentationRegistry = class _InstrumentationRegistry {
345
1137
  }
346
1138
  })();
347
1139
  }
1140
+ if (this.manualModules?.mcp) {
1141
+ try {
1142
+ new MCPInstrumentation({ exceptionLogger }).manuallyInstrument(this.manualModules.mcp);
1143
+ logger.debug("Manual instrumentation enabled for MCP");
1144
+ } catch (error) {
1145
+ logger.error(`Failed to apply MCP instrumentation: ${String(error)}`);
1146
+ }
1147
+ }
348
1148
  }
349
1149
  };
350
1150
 
@@ -356,32 +1156,17 @@ import {
356
1156
  LoggerProvider
357
1157
  } from "@opentelemetry/sdk-logs";
358
1158
 
359
- // src/internal/version.ts
360
- function getSDKVersion() {
361
- return "0.1.21";
362
- }
363
-
364
1159
  // src/internal/log/processors/log-processor.ts
365
- import { context } from "@opentelemetry/api";
1160
+ import { context as context3 } from "@opentelemetry/api";
366
1161
  import { BatchLogRecordProcessor, SimpleLogRecordProcessor } from "@opentelemetry/sdk-logs";
367
1162
 
368
1163
  // src/internal/masking/patterns.ts
369
1164
  var DEFAULT_PII_PATTERNS = [
370
- // Email addresses
371
- {
372
- name: "email_addresses",
373
- pattern: String.raw`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`
374
- },
375
1165
  // Phone numbers (US format)
376
1166
  {
377
1167
  name: "us_phone_numbers",
378
1168
  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]|$)`
379
1169
  },
380
- // Social Security Numbers
381
- {
382
- name: "ssn",
383
- pattern: String.raw`\b(?!000|666|9\d{2})\d{3}[-\s]?(?!00)\d{2}[-\s]?(?!0000)\d{4}\b`
384
- },
385
1170
  // Credit card numbers
386
1171
  {
387
1172
  name: "credit_cards",
@@ -405,19 +1190,11 @@ var DEFAULT_PII_PATTERNS = [
405
1190
  name: "openai_keys",
406
1191
  pattern: String.raw`\bsk[-_][a-zA-Z0-9]{20,}\b`
407
1192
  },
408
- {
409
- name: "base64_secrets",
410
- pattern: String.raw`\b[A-Za-z0-9+/]{64,}={0,2}\b`
411
- },
412
1193
  // AWS Keys
413
1194
  {
414
1195
  name: "aws_access_keys",
415
1196
  pattern: String.raw`\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b`
416
1197
  },
417
- {
418
- name: "aws_secret_keys",
419
- 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`
420
- },
421
1198
  // GitHub tokens
422
1199
  {
423
1200
  name: "github_tokens",
@@ -448,11 +1225,6 @@ var DEFAULT_PII_PATTERNS = [
448
1225
  name: "ipv6_addresses",
449
1226
  pattern: String.raw`\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b`
450
1227
  },
451
- // Medical records
452
- {
453
- name: "medical_record_numbers",
454
- pattern: String.raw`\b(?:[Mm][Rr][Nn])[-\s]?\d{6,10}\b`
455
- },
456
1228
  // Bitcoin addresses
457
1229
  {
458
1230
  name: "bitcoin_addresses",
@@ -463,11 +1235,6 @@ var DEFAULT_PII_PATTERNS = [
463
1235
  name: "ethereum_addresses",
464
1236
  pattern: String.raw`\b0x[a-fA-F0-9]{40}(?![a-fA-F0-9])\b`
465
1237
  },
466
- // UUIDs
467
- {
468
- name: "uuids",
469
- 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`
470
- },
471
1238
  // Database connection strings
472
1239
  {
473
1240
  name: "database_connections",
@@ -486,90 +1253,6 @@ var DEFAULT_PII_PATTERNS = [
486
1253
  name: "certificates",
487
1254
  pattern: "-----BEGIN CERTIFICATE-----"
488
1255
  },
489
- // Date of birth patterns
490
- {
491
- name: "date_of_birth_us",
492
- pattern: String.raw`\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])[-/](?:19|20)\\d{2}\b`
493
- },
494
- {
495
- name: "date_of_birth_iso",
496
- pattern: String.raw`\b(?:19|20)\\d{2}[-/](?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])\b`
497
- },
498
- // US Identification Numbers
499
- {
500
- name: "us_passport_numbers",
501
- pattern: String.raw`\b[A-Z]?\\d{6,9}\b`
502
- },
503
- {
504
- name: "drivers_license",
505
- 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`
506
- },
507
- {
508
- name: "bank_account_numbers",
509
- pattern: String.raw`\b\\d{10,17}\b`
510
- },
511
- {
512
- name: "aba_routing_numbers",
513
- 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`
514
- },
515
- {
516
- name: "health_insurance_numbers",
517
- pattern: String.raw`\b\\d{10}[A-Z]\b`
518
- },
519
- {
520
- name: "employee_ids",
521
- pattern: String.raw`\b(?:[Ee][Mm][Pp]|[Ee][Mm][Pp][Ll][Oo][Yy][Ee][Ee]|[Ee])[-\s]?\\d{5,8}\b`
522
- },
523
- {
524
- name: "tax_ein",
525
- pattern: String.raw`\b\\d{2}-\\d{7}\b`
526
- },
527
- {
528
- name: "medicare_beneficiary_id",
529
- 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`
530
- },
531
- {
532
- name: "national_provider_id",
533
- pattern: String.raw`\b1\\d{9}\b`
534
- },
535
- {
536
- name: "dea_numbers",
537
- pattern: String.raw`\b[A-Z]{2}\\d{7}\b`
538
- },
539
- {
540
- name: "itin",
541
- pattern: String.raw`\b9\\d{2}(?:[ \\-]?)[7,8]\\d(?:[ \\-]?)\\d{4}\b`
542
- },
543
- // Vehicle and Location
544
- {
545
- name: "vin_numbers",
546
- pattern: String.raw`\b[A-HJ-NPR-Z0-9]{17}\b`
547
- },
548
- {
549
- name: "coordinates",
550
- pattern: String.raw`\b[-+]?(?:[0-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?),\\s*[-+]?(?:1[0-7]\\d(?:\\.\\d+)?|180(?:\\.0+)?|[0-9]?\\d(?:\\.\\d+)?)\b`
551
- },
552
- {
553
- name: "us_license_plates",
554
- 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`
555
- },
556
- {
557
- name: "us_zip_codes",
558
- pattern: String.raw`\b(\\d{5}-\\d{4}|\\d{5})\b`
559
- },
560
- {
561
- name: "us_street_addresses",
562
- 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`
563
- },
564
- // International Banking
565
- {
566
- name: "iban",
567
- pattern: String.raw`\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}([A-Z0-9]?){0,16}\b`
568
- },
569
- {
570
- name: "swift_bic",
571
- pattern: String.raw`\b[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?\b`
572
- },
573
1256
  // Additional API Keys and Tokens
574
1257
  {
575
1258
  name: "google_oauth",
@@ -632,73 +1315,6 @@ var DEFAULT_PII_PATTERNS = [
632
1315
  name: "putty_ssh_keys",
633
1316
  pattern: String.raw`PuTTY-User-Key-File-2: ssh-(?:rsa|dss)\s*Encryption: none(?:.|\s?)*?Private-MAC:`
634
1317
  },
635
- // International Phone Numbers
636
- {
637
- name: "france_phone_numbers",
638
- pattern: String.raw`\b([0O]?[1lI][1lI])?[3E][3E][0O]?[\\dOIlZEASB]{9}\b`
639
- },
640
- {
641
- name: "german_phone_numbers",
642
- pattern: String.raw`\b[\d\w]\d{2}[\d\w]{6}\d[\d\w]\b`
643
- },
644
- {
645
- name: "uk_phone_numbers",
646
- pattern: String.raw`\b([0O]?[1lI][1lI])?[4A][4A][\\dOIlZEASB]{10,11}\b`
647
- },
648
- // International IDs
649
- {
650
- name: "uk_drivers_license",
651
- pattern: String.raw`\b[A-Z]{5}\d{6}[A-Z]{2}\d{1}[A-Z]{2}\b`
652
- },
653
- {
654
- name: "uk_passport",
655
- pattern: String.raw`\b\\d{10}GB[RP]\\d{7}[UMF]{1}\\d{9}\b`
656
- },
657
- {
658
- name: "argentina_dni",
659
- pattern: String.raw`\b\\d{2}\\.\\d{3}\\.\\d{3}\b`
660
- },
661
- {
662
- name: "australia_tfn",
663
- pattern: String.raw`\b[Tt][Ff][Nn](:|:\\s|\\s|)(\\d{8,9})\b`
664
- },
665
- {
666
- name: "canada_passport",
667
- pattern: String.raw`\b[\\w]{2}[\\d]{6}\b`
668
- },
669
- {
670
- name: "croatia_vat",
671
- pattern: String.raw`\bHR\\d{11}\b`
672
- },
673
- {
674
- name: "czech_vat",
675
- pattern: String.raw`\bCZ\\d{8,10}\b`
676
- },
677
- {
678
- name: "denmark_personal_id",
679
- pattern: String.raw`\b(?:\\d{10}|\\d{6}[-\\s]\\d{4})\b`
680
- },
681
- {
682
- name: "france_national_id",
683
- pattern: String.raw`\b\\d{12}\b`
684
- },
685
- {
686
- name: "france_ssn",
687
- pattern: String.raw`\b(?:\\d{13}|\\d{13}\\s\\d{2})\b`
688
- },
689
- {
690
- name: "france_passport",
691
- pattern: String.raw`\b\\d{2}11\\d{5}\b`
692
- },
693
- {
694
- name: "california_drivers_license",
695
- pattern: String.raw`\b[A-Z]{1}\\d{7}\b`
696
- },
697
- // Medical and Healthcare
698
- {
699
- name: "hipaa_ndc",
700
- pattern: String.raw`\b\\d{4,5}-\\d{3,4}-\\d{1,2}\b`
701
- },
702
1318
  // Security and Network
703
1319
  {
704
1320
  name: "cve_numbers",
@@ -732,44 +1348,6 @@ var DEFAULT_PII_PATTERNS = [
732
1348
  {
733
1349
  name: "discover_cards",
734
1350
  pattern: String.raw`\b65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}\b`
735
- },
736
- {
737
- name: "enhanced_credit_cards",
738
- 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`
739
- },
740
- // Bank Routing Numbers (US specific)
741
- {
742
- name: "bbva_routing_ca",
743
- pattern: String.raw`\\b321170538\\b`
744
- },
745
- {
746
- name: "boa_routing_ca",
747
- pattern: String.raw`\\b(?:121|026)00(?:0|9)(?:358|593)\\b`
748
- },
749
- {
750
- name: "chase_routing_ca",
751
- pattern: String.raw`\\b322271627\\b`
752
- },
753
- {
754
- name: "citibank_routing_ca",
755
- pattern: String.raw`\\b32(?:11|22)71(?:18|72)4\\b`
756
- },
757
- {
758
- name: "usbank_routing_ca",
759
- pattern: String.raw`\\b12(?:1122676|2235821)\\b`
760
- },
761
- {
762
- name: "united_bank_routing_ca",
763
- pattern: String.raw`\\b122243350\\b`
764
- },
765
- {
766
- name: "wells_fargo_routing_ca",
767
- pattern: String.raw`\\b121042882\\b`
768
- },
769
- // Unrealistic alphanumeric identifiers
770
- {
771
- name: "generic_non_usual",
772
- pattern: String.raw`(?:^|\s)(?=[A-Za-z0-9_\)\*\=@]*[A-Za-z])(?=[A-Za-z0-9_\)\*\=@]*[0-9])([A-Za-z0-9_\)\*\=@]{5,})(?=\s|$)`
773
1351
  }
774
1352
  ];
775
1353
 
@@ -989,13 +1567,6 @@ function maskAttributes(attributes, rules, outputOriginalValue = false) {
989
1567
  return maskedAttributes;
990
1568
  }
991
1569
 
992
- // src/internal/semantic-conventions.ts
993
- import { createContextKey } from "@opentelemetry/api";
994
- var BRIZZ = "brizz";
995
- var PROPERTIES = "properties";
996
- var PROPERTIES_CONTEXT_KEY = createContextKey(PROPERTIES);
997
- var SESSION_OBJECT_CONTEXT_KEY = createContextKey("brizz.session.object");
998
-
999
1570
  // src/internal/log/processors/log-processor.ts
1000
1571
  var DEFAULT_LOG_MASKING_RULES = [
1001
1572
  {
@@ -1015,7 +1586,7 @@ var BrizzSimpleLogRecordProcessor = class extends SimpleLogRecordProcessor {
1015
1586
  if (maskingConfig) {
1016
1587
  maskLog(logRecord, maskingConfig);
1017
1588
  }
1018
- const associationProperties = context.active().getValue(PROPERTIES_CONTEXT_KEY);
1589
+ const associationProperties = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
1019
1590
  if (associationProperties) {
1020
1591
  for (const [key, value] of Object.entries(associationProperties)) {
1021
1592
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1035,7 +1606,7 @@ var BrizzBatchLogRecordProcessor = class extends BatchLogRecordProcessor {
1035
1606
  if (maskingConfig) {
1036
1607
  maskLog(logRecord, maskingConfig);
1037
1608
  }
1038
- const associationProperties = context.active().getValue(PROPERTIES_CONTEXT_KEY);
1609
+ const associationProperties = context3.active().getValue(PROPERTIES_CONTEXT_KEY);
1039
1610
  if (associationProperties) {
1040
1611
  for (const [key, value] of Object.entries(associationProperties)) {
1041
1612
  logRecord.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1422,13 +1993,13 @@ var BrizzSpanExporter = class {
1422
1993
  };
1423
1994
 
1424
1995
  // src/internal/trace/processors/span-processor.ts
1425
- import { context as context2 } from "@opentelemetry/api";
1996
+ import { context as context4 } from "@opentelemetry/api";
1426
1997
  import {
1427
1998
  BatchSpanProcessor,
1428
1999
  SimpleSpanProcessor
1429
2000
  } from "@opentelemetry/sdk-trace-base";
1430
2001
  function applyContextAttributes(span) {
1431
- const sessionProperties = context2.active().getValue(PROPERTIES_CONTEXT_KEY);
2002
+ const sessionProperties = context4.active().getValue(PROPERTIES_CONTEXT_KEY);
1432
2003
  if (sessionProperties) {
1433
2004
  for (const [key, value] of Object.entries(sessionProperties)) {
1434
2005
  span.setAttribute(`${BRIZZ}.${key}`, value);
@@ -1438,12 +2009,6 @@ function applyContextAttributes(span) {
1438
2009
  var DEFAULT_MASKING_RULES = [
1439
2010
  {
1440
2011
  mode: "partial",
1441
- attributePattern: "gen_ai.prompt",
1442
- patterns: DEFAULT_PII_PATTERNS
1443
- },
1444
- {
1445
- mode: "partial",
1446
- attributePattern: "gen_ai.completion",
1447
2012
  patterns: DEFAULT_PII_PATTERNS
1448
2013
  }
1449
2014
  ];
@@ -1453,24 +2018,16 @@ var BrizzSimpleSpanProcessor = class extends SimpleSpanProcessor {
1453
2018
  super(spanExporter);
1454
2019
  this.config = config;
1455
2020
  }
1456
- // Will work with the following code:
1457
- // const span = tracer.startSpan('sensitive-operation',{attributes:{
1458
- // 'user.password': 'secret123',
1459
- // 'user.email': 'user@example.com',
1460
- // }});
1461
- //
1462
- // Won't work because onStart is called before attributes are set:
1463
- // span.setAttributes({
1464
- // 'user.password': 'secret123',
1465
- // 'user.email': 'user@example.com'
1466
- // });
1467
2021
  onStart(span, parentContext) {
2022
+ applyContextAttributes(span);
2023
+ super.onStart(span, parentContext);
2024
+ }
2025
+ onEnd(span) {
1468
2026
  const maskingConfig = this.config.masking?.spanMasking;
1469
2027
  if (maskingConfig) {
1470
- maskSpan(span, maskingConfig);
2028
+ maskReadableSpan(span, maskingConfig);
1471
2029
  }
1472
- applyContextAttributes(span);
1473
- super.onStart(span, parentContext);
2030
+ super.onEnd(span);
1474
2031
  }
1475
2032
  };
1476
2033
  var BrizzBatchSpanProcessor = class extends BatchSpanProcessor {
@@ -1480,39 +2037,39 @@ var BrizzBatchSpanProcessor = class extends BatchSpanProcessor {
1480
2037
  this.config = config;
1481
2038
  }
1482
2039
  onStart(span, parentContext) {
2040
+ applyContextAttributes(span);
2041
+ super.onStart(span, parentContext);
2042
+ }
2043
+ onEnd(span) {
1483
2044
  const maskingConfig = this.config.masking?.spanMasking;
1484
2045
  if (maskingConfig) {
1485
- maskSpan(span, maskingConfig);
2046
+ maskReadableSpan(span, maskingConfig);
1486
2047
  }
1487
- applyContextAttributes(span);
1488
- super.onStart(span, parentContext);
2048
+ super.onEnd(span);
1489
2049
  }
1490
2050
  };
1491
- function maskSpan(span, config) {
1492
- if (!span.attributes || Object.keys(span.attributes).length === 0) {
1493
- return span;
2051
+ function maskReadableSpan(span, config) {
2052
+ const attrs = span.attributes;
2053
+ if (!attrs || Object.keys(attrs).length === 0) {
2054
+ return;
1494
2055
  }
1495
- let rules = config.rules || [];
2056
+ let rules = config.rules ? [...config.rules] : [];
1496
2057
  if (!config.disableDefaultRules) {
1497
- rules = [...DEFAULT_MASKING_RULES, ...rules];
2058
+ rules = [...rules, ...DEFAULT_MASKING_RULES];
1498
2059
  }
1499
2060
  try {
1500
- const attributesRecord = {};
1501
- for (const [key, value] of Object.entries(span.attributes)) {
1502
- attributesRecord[key] = value;
1503
- }
1504
- const maskedAttributes = maskAttributes(attributesRecord, rules);
1505
- if (maskedAttributes && Object.keys(maskedAttributes).length > 0) {
1506
- const merged = { ...span.attributes };
1507
- for (const [key, value] of Object.entries(maskedAttributes)) {
1508
- merged[key] = value;
2061
+ const input = {};
2062
+ for (const [k, v] of Object.entries(attrs)) {
2063
+ input[k] = v;
2064
+ }
2065
+ const masked = maskAttributes(input, rules);
2066
+ for (const [k, v] of Object.entries(masked ?? {})) {
2067
+ if (attrs[k] !== v) {
2068
+ attrs[k] = v;
1509
2069
  }
1510
- span.setAttributes(merged);
1511
2070
  }
1512
- return span;
1513
2071
  } catch (error) {
1514
- logger.error("Error masking span:", error);
1515
- return span;
2072
+ logger.error("Error masking span", { err: error });
1516
2073
  }
1517
2074
  }
1518
2075
 
@@ -1625,7 +2182,7 @@ function getSpanProcessor() {
1625
2182
  }
1626
2183
 
1627
2184
  // src/internal/trace/session.ts
1628
- import { context as context3, trace, SpanStatusCode } from "@opentelemetry/api";
2185
+ import { context as context5, trace as trace3, SpanStatusCode as SpanStatusCode3 } from "@opentelemetry/api";
1629
2186
 
1630
2187
  // src/internal/sdk.ts
1631
2188
  var _Brizz = class __Brizz {
@@ -1957,15 +2514,18 @@ if (runtime.isESM && runtime.supportsLoaderAPI) {
1957
2514
  maybeRegisterESMLoader();
1958
2515
  }
1959
2516
  try {
1960
- Brizz.initialize({
1961
- apiKey: process.env["BRIZZ_API_KEY"],
1962
- baseUrl: process.env["BRIZZ_BASE_URL"],
1963
- appName: process.env["BRIZZ_APP_NAME"] || process.env["OTEL_SERVICE_NAME"],
1964
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1965
- logLevel: process.env["BRIZZ_LOG_LEVEL"] || DEFAULT_LOG_LEVEL.toString(),
1966
- // Enable auto-instrumentation by default in preload mode
1967
- disableNodeSdk: false
1968
- });
2517
+ const logLevel = process.env["BRIZZ_LOG_LEVEL"] || DEFAULT_LOG_LEVEL.toString();
2518
+ if (process.env["BRIZZ_DSN"]) {
2519
+ Brizz.initialize({ logLevel, disableNodeSdk: false });
2520
+ } else {
2521
+ Brizz.initialize({
2522
+ apiKey: process.env["BRIZZ_API_KEY"],
2523
+ baseUrl: process.env["BRIZZ_BASE_URL"],
2524
+ appName: process.env["BRIZZ_APP_NAME"] || process.env["OTEL_SERVICE_NAME"],
2525
+ logLevel,
2526
+ disableNodeSdk: false
2527
+ });
2528
+ }
1969
2529
  logger.info(`SDK auto-initialized for ${runtime.isESM ? "ESM" : "CJS"} runtime`);
1970
2530
  } catch (error) {
1971
2531
  logger.warn("Failed to auto-initialize SDK:", { error });