@brizz/sdk 0.1.22 → 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
  }
@@ -248,10 +330,10 @@ import { trace as trace2 } from "@opentelemetry/api";
248
330
  import { InstrumentationNodeModuleDefinition } from "@opentelemetry/instrumentation";
249
331
 
250
332
  // src/internal/instrumentation/mcp/patches/protocol.ts
251
- import { context as context2, propagation, SpanKind, trace } from "@opentelemetry/api";
333
+ import { context as context2, propagation, SpanKind as SpanKind2, trace } from "@opentelemetry/api";
252
334
 
253
- // src/internal/instrumentation/mcp/session.ts
254
- import { context } from "@opentelemetry/api";
335
+ // src/internal/instrumentation/mcp/schemas.ts
336
+ import { SpanKind, SpanStatusCode } from "@opentelemetry/api";
255
337
 
256
338
  // src/internal/semantic-conventions.ts
257
339
  import { createContextKey } from "@opentelemetry/api";
@@ -261,42 +343,17 @@ var SESSION_ID = "session.id";
261
343
  var PROPERTIES_CONTEXT_KEY = createContextKey(PROPERTIES);
262
344
  var SESSION_OBJECT_CONTEXT_KEY = createContextKey("brizz.session.object");
263
345
 
264
- // src/internal/instrumentation/mcp/session.ts
265
- function stampAndPropagateSession(span, sessionId, baseContext = context.active()) {
266
- if (!sessionId) {
267
- return { context: baseContext, sessionId: null };
268
- }
269
- if (span.isRecording()) {
270
- try {
271
- span.setAttribute(`${BRIZZ}.${SESSION_ID}`, sessionId);
272
- } catch (error) {
273
- logger.warn(
274
- `Brizz MCP: failed to stamp session id on span: ${String(error)}`
275
- );
276
- }
277
- }
278
- try {
279
- const prev = baseContext.getValue(PROPERTIES_CONTEXT_KEY);
280
- const merged = prev ? { ...prev, [SESSION_ID]: sessionId } : { [SESSION_ID]: sessionId };
281
- return {
282
- context: baseContext.setValue(PROPERTIES_CONTEXT_KEY, merged),
283
- sessionId
284
- };
285
- } catch (error) {
286
- logger.warn(`Brizz MCP: failed to attach session context: ${String(error)}`);
287
- return { context: baseContext, sessionId };
288
- }
289
- }
290
-
291
- // src/internal/instrumentation/mcp/patches/attributes.ts
292
- import { SpanStatusCode } from "@opentelemetry/api";
293
-
294
346
  // src/internal/instrumentation/mcp/semantic-conventions.ts
295
347
  var MCP_TOOL_NAME = "mcp.tool.name";
296
348
  var MCP_TOOL_ARGUMENTS = "mcp.tool.arguments";
297
349
  var MCP_TOOL_RESULT = "mcp.tool.result";
298
350
  var MCP_COMPONENT_TYPE = "mcp.component.type";
299
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";
300
357
  var MCP_METHOD_NAME = "mcp.method.name";
301
358
  var MCP_REQUEST_ID = "mcp.request.id";
302
359
  var MCP_SESSION_ID = "mcp.session.id";
@@ -317,11 +374,115 @@ var SPAN_NAME_TOOLS_CALL = "tools/call";
317
374
  var MAX_ATTRIBUTE_LENGTH = 32 * 1024;
318
375
  var TRUNCATION_SUFFIX = "\u2026(truncated)";
319
376
  var METHOD_TOOLS_CALL = "tools/call";
377
+ var METHOD_TOOLS_LIST = "tools/list";
320
378
  var METHOD_RESOURCES_READ = "resources/read";
321
379
  var METHOD_PROMPTS_GET = "prompts/get";
322
380
  var METHOD_INITIALIZE = "initialize";
323
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
+
324
484
  // src/internal/instrumentation/mcp/patches/attributes.ts
485
+ import { SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
325
486
  function deriveSpanName(method, params) {
326
487
  try {
327
488
  if (method === METHOD_TOOLS_CALL) {
@@ -424,7 +585,7 @@ function applyResultAttributes(span, method, result) {
424
585
  if (obj && obj["isError"] === true) {
425
586
  span.setAttribute(ERROR_TYPE, ERROR_TYPE_TOOL);
426
587
  const message = extractToolErrorMessage(obj);
427
- span.setStatus({ code: SpanStatusCode.ERROR, message });
588
+ span.setStatus({ code: SpanStatusCode2.ERROR, message });
428
589
  }
429
590
  }
430
591
  function applyErrorAttributes(span, err) {
@@ -448,7 +609,7 @@ function applyErrorAttributes(span, err) {
448
609
  } catch {
449
610
  }
450
611
  span.setStatus({
451
- code: SpanStatusCode.ERROR,
612
+ code: SpanStatusCode2.ERROR,
452
613
  message: typeof error?.message === "string" ? error.message : void 0
453
614
  });
454
615
  }
@@ -580,7 +741,20 @@ function wrapOnRequest(original, tracer) {
580
741
  return original.apply(this, args);
581
742
  }
582
743
  const { span, spanCtx } = started;
583
- const wrappedHandler = (req, extra) => context2.with(spanCtx, () => executeHandler(span, method, handler, req, extra));
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
+ );
584
758
  const hadEntry = handlers.has(method);
585
759
  const prev = handlers.get(method);
586
760
  handlers.set(method, wrappedHandler);
@@ -603,7 +777,7 @@ function wrapOnRequest(original, tracer) {
603
777
  }
604
778
  };
605
779
  }
606
- function executeAroundSpan(span, method, run) {
780
+ function executeAroundSpan(span, method, run, postResult) {
607
781
  let result;
608
782
  try {
609
783
  result = run();
@@ -614,12 +788,18 @@ function executeAroundSpan(span, method, run) {
614
788
  }
615
789
  if (!isThenable(result)) {
616
790
  safeApplyResultAttributes(span, method, result);
791
+ if (postResult) {
792
+ postResult(result);
793
+ }
617
794
  safeEnd(span);
618
795
  return result;
619
796
  }
620
797
  return result.then(
621
798
  (value) => {
622
799
  safeApplyResultAttributes(span, method, value);
800
+ if (postResult) {
801
+ postResult(value);
802
+ }
623
803
  safeEnd(span);
624
804
  return value;
625
805
  },
@@ -630,13 +810,13 @@ function executeAroundSpan(span, method, run) {
630
810
  }
631
811
  );
632
812
  }
633
- function executeHandler(span, method, handler, req, extra) {
634
- return executeAroundSpan(span, method, () => handler(req, extra));
813
+ function executeHandler(span, method, handler, req, extra, postResult) {
814
+ return executeAroundSpan(span, method, () => handler(req, extra), postResult);
635
815
  }
636
816
  function safeStartClientSpan(tracer, request, protocol) {
637
817
  try {
638
818
  const spanName = deriveSpanName(request.method, request.params);
639
- const span = tracer.startSpan(spanName, { kind: SpanKind.CLIENT });
819
+ const span = tracer.startSpan(spanName, { kind: SpanKind2.CLIENT });
640
820
  applyClientRequestAttributes(
641
821
  span,
642
822
  request,
@@ -654,7 +834,7 @@ function safeStartServerSpan(tracer, request, protocol) {
654
834
  const spanName = deriveSpanName(request.method, request.params);
655
835
  const span = tracer.startSpan(
656
836
  spanName,
657
- { kind: SpanKind.SERVER },
837
+ { kind: SpanKind2.SERVER },
658
838
  parentCtx
659
839
  );
660
840
  applyServerRequestAttributes(span, request, protocol);
@@ -710,7 +890,7 @@ function safeEnd(span) {
710
890
 
711
891
  // src/internal/version.ts
712
892
  function getSDKVersion() {
713
- return "0.1.22";
893
+ return "0.1.25";
714
894
  }
715
895
 
716
896
  // src/internal/instrumentation/mcp/version.ts
@@ -982,21 +1162,11 @@ import { BatchLogRecordProcessor, SimpleLogRecordProcessor } from "@opentelemetr
982
1162
 
983
1163
  // src/internal/masking/patterns.ts
984
1164
  var DEFAULT_PII_PATTERNS = [
985
- // Email addresses
986
- {
987
- name: "email_addresses",
988
- pattern: String.raw`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`
989
- },
990
1165
  // Phone numbers (US format)
991
1166
  {
992
1167
  name: "us_phone_numbers",
993
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]|$)`
994
1169
  },
995
- // Social Security Numbers
996
- {
997
- name: "ssn",
998
- pattern: String.raw`\b(?!000|666|9\d{2})\d{3}[-\s]?(?!00)\d{2}[-\s]?(?!0000)\d{4}\b`
999
- },
1000
1170
  // Credit card numbers
1001
1171
  {
1002
1172
  name: "credit_cards",
@@ -1020,19 +1190,11 @@ var DEFAULT_PII_PATTERNS = [
1020
1190
  name: "openai_keys",
1021
1191
  pattern: String.raw`\bsk[-_][a-zA-Z0-9]{20,}\b`
1022
1192
  },
1023
- {
1024
- name: "base64_secrets",
1025
- pattern: String.raw`\b[A-Za-z0-9+/]{64,}={0,2}\b`
1026
- },
1027
1193
  // AWS Keys
1028
1194
  {
1029
1195
  name: "aws_access_keys",
1030
1196
  pattern: String.raw`\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b`
1031
1197
  },
1032
- {
1033
- name: "aws_secret_keys",
1034
- 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`
1035
- },
1036
1198
  // GitHub tokens
1037
1199
  {
1038
1200
  name: "github_tokens",
@@ -1063,11 +1225,6 @@ var DEFAULT_PII_PATTERNS = [
1063
1225
  name: "ipv6_addresses",
1064
1226
  pattern: String.raw`\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b`
1065
1227
  },
1066
- // Medical records
1067
- {
1068
- name: "medical_record_numbers",
1069
- pattern: String.raw`\b(?:[Mm][Rr][Nn])[-\s]?\d{6,10}\b`
1070
- },
1071
1228
  // Bitcoin addresses
1072
1229
  {
1073
1230
  name: "bitcoin_addresses",
@@ -1078,11 +1235,6 @@ var DEFAULT_PII_PATTERNS = [
1078
1235
  name: "ethereum_addresses",
1079
1236
  pattern: String.raw`\b0x[a-fA-F0-9]{40}(?![a-fA-F0-9])\b`
1080
1237
  },
1081
- // UUIDs
1082
- {
1083
- name: "uuids",
1084
- 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`
1085
- },
1086
1238
  // Database connection strings
1087
1239
  {
1088
1240
  name: "database_connections",
@@ -1101,90 +1253,6 @@ var DEFAULT_PII_PATTERNS = [
1101
1253
  name: "certificates",
1102
1254
  pattern: "-----BEGIN CERTIFICATE-----"
1103
1255
  },
1104
- // Date of birth patterns
1105
- {
1106
- name: "date_of_birth_us",
1107
- pattern: String.raw`\b(?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])[-/](?:19|20)\\d{2}\b`
1108
- },
1109
- {
1110
- name: "date_of_birth_iso",
1111
- pattern: String.raw`\b(?:19|20)\\d{2}[-/](?:0[1-9]|1[0-2])[-/](?:0[1-9]|[12]\\d|3[01])\b`
1112
- },
1113
- // US Identification Numbers
1114
- {
1115
- name: "us_passport_numbers",
1116
- pattern: String.raw`\b[A-Z]?\\d{6,9}\b`
1117
- },
1118
- {
1119
- name: "drivers_license",
1120
- 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`
1121
- },
1122
- {
1123
- name: "bank_account_numbers",
1124
- pattern: String.raw`\b\\d{10,17}\b`
1125
- },
1126
- {
1127
- name: "aba_routing_numbers",
1128
- 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`
1129
- },
1130
- {
1131
- name: "health_insurance_numbers",
1132
- pattern: String.raw`\b\\d{10}[A-Z]\b`
1133
- },
1134
- {
1135
- name: "employee_ids",
1136
- pattern: String.raw`\b(?:[Ee][Mm][Pp]|[Ee][Mm][Pp][Ll][Oo][Yy][Ee][Ee]|[Ee])[-\s]?\\d{5,8}\b`
1137
- },
1138
- {
1139
- name: "tax_ein",
1140
- pattern: String.raw`\b\\d{2}-\\d{7}\b`
1141
- },
1142
- {
1143
- name: "medicare_beneficiary_id",
1144
- 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`
1145
- },
1146
- {
1147
- name: "national_provider_id",
1148
- pattern: String.raw`\b1\\d{9}\b`
1149
- },
1150
- {
1151
- name: "dea_numbers",
1152
- pattern: String.raw`\b[A-Z]{2}\\d{7}\b`
1153
- },
1154
- {
1155
- name: "itin",
1156
- pattern: String.raw`\b9\\d{2}(?:[ \\-]?)[7,8]\\d(?:[ \\-]?)\\d{4}\b`
1157
- },
1158
- // Vehicle and Location
1159
- {
1160
- name: "vin_numbers",
1161
- pattern: String.raw`\b[A-HJ-NPR-Z0-9]{17}\b`
1162
- },
1163
- {
1164
- name: "coordinates",
1165
- pattern: String.raw`\b[-+]?(?:[0-8]?\\d(?:\\.\\d+)?|90(?:\\.0+)?),\\s*[-+]?(?:1[0-7]\\d(?:\\.\\d+)?|180(?:\\.0+)?|[0-9]?\\d(?:\\.\\d+)?)\b`
1166
- },
1167
- {
1168
- name: "us_license_plates",
1169
- 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`
1170
- },
1171
- {
1172
- name: "us_zip_codes",
1173
- pattern: String.raw`\b(\\d{5}-\\d{4}|\\d{5})\b`
1174
- },
1175
- {
1176
- name: "us_street_addresses",
1177
- 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`
1178
- },
1179
- // International Banking
1180
- {
1181
- name: "iban",
1182
- pattern: String.raw`\b[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}([A-Z0-9]?){0,16}\b`
1183
- },
1184
- {
1185
- name: "swift_bic",
1186
- pattern: String.raw`\b[A-Z]{4}[A-Z]{2}[A-Z0-9]{2}([A-Z0-9]{3})?\b`
1187
- },
1188
1256
  // Additional API Keys and Tokens
1189
1257
  {
1190
1258
  name: "google_oauth",
@@ -1247,73 +1315,6 @@ var DEFAULT_PII_PATTERNS = [
1247
1315
  name: "putty_ssh_keys",
1248
1316
  pattern: String.raw`PuTTY-User-Key-File-2: ssh-(?:rsa|dss)\s*Encryption: none(?:.|\s?)*?Private-MAC:`
1249
1317
  },
1250
- // International Phone Numbers
1251
- {
1252
- name: "france_phone_numbers",
1253
- pattern: String.raw`\b([0O]?[1lI][1lI])?[3E][3E][0O]?[\\dOIlZEASB]{9}\b`
1254
- },
1255
- {
1256
- name: "german_phone_numbers",
1257
- pattern: String.raw`\b[\d\w]\d{2}[\d\w]{6}\d[\d\w]\b`
1258
- },
1259
- {
1260
- name: "uk_phone_numbers",
1261
- pattern: String.raw`\b([0O]?[1lI][1lI])?[4A][4A][\\dOIlZEASB]{10,11}\b`
1262
- },
1263
- // International IDs
1264
- {
1265
- name: "uk_drivers_license",
1266
- pattern: String.raw`\b[A-Z]{5}\d{6}[A-Z]{2}\d{1}[A-Z]{2}\b`
1267
- },
1268
- {
1269
- name: "uk_passport",
1270
- pattern: String.raw`\b\\d{10}GB[RP]\\d{7}[UMF]{1}\\d{9}\b`
1271
- },
1272
- {
1273
- name: "argentina_dni",
1274
- pattern: String.raw`\b\\d{2}\\.\\d{3}\\.\\d{3}\b`
1275
- },
1276
- {
1277
- name: "australia_tfn",
1278
- pattern: String.raw`\b[Tt][Ff][Nn](:|:\\s|\\s|)(\\d{8,9})\b`
1279
- },
1280
- {
1281
- name: "canada_passport",
1282
- pattern: String.raw`\b[\\w]{2}[\\d]{6}\b`
1283
- },
1284
- {
1285
- name: "croatia_vat",
1286
- pattern: String.raw`\bHR\\d{11}\b`
1287
- },
1288
- {
1289
- name: "czech_vat",
1290
- pattern: String.raw`\bCZ\\d{8,10}\b`
1291
- },
1292
- {
1293
- name: "denmark_personal_id",
1294
- pattern: String.raw`\b(?:\\d{10}|\\d{6}[-\\s]\\d{4})\b`
1295
- },
1296
- {
1297
- name: "france_national_id",
1298
- pattern: String.raw`\b\\d{12}\b`
1299
- },
1300
- {
1301
- name: "france_ssn",
1302
- pattern: String.raw`\b(?:\\d{13}|\\d{13}\\s\\d{2})\b`
1303
- },
1304
- {
1305
- name: "france_passport",
1306
- pattern: String.raw`\b\\d{2}11\\d{5}\b`
1307
- },
1308
- {
1309
- name: "california_drivers_license",
1310
- pattern: String.raw`\b[A-Z]{1}\\d{7}\b`
1311
- },
1312
- // Medical and Healthcare
1313
- {
1314
- name: "hipaa_ndc",
1315
- pattern: String.raw`\b\\d{4,5}-\\d{3,4}-\\d{1,2}\b`
1316
- },
1317
1318
  // Security and Network
1318
1319
  {
1319
1320
  name: "cve_numbers",
@@ -1347,44 +1348,6 @@ var DEFAULT_PII_PATTERNS = [
1347
1348
  {
1348
1349
  name: "discover_cards",
1349
1350
  pattern: String.raw`\b65[4-9][0-9]{13}|64[4-9][0-9]{13}|6011[0-9]{12}\b`
1350
- },
1351
- {
1352
- name: "enhanced_credit_cards",
1353
- 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`
1354
- },
1355
- // Bank Routing Numbers (US specific)
1356
- {
1357
- name: "bbva_routing_ca",
1358
- pattern: String.raw`\\b321170538\\b`
1359
- },
1360
- {
1361
- name: "boa_routing_ca",
1362
- pattern: String.raw`\\b(?:121|026)00(?:0|9)(?:358|593)\\b`
1363
- },
1364
- {
1365
- name: "chase_routing_ca",
1366
- pattern: String.raw`\\b322271627\\b`
1367
- },
1368
- {
1369
- name: "citibank_routing_ca",
1370
- pattern: String.raw`\\b32(?:11|22)71(?:18|72)4\\b`
1371
- },
1372
- {
1373
- name: "usbank_routing_ca",
1374
- pattern: String.raw`\\b12(?:1122676|2235821)\\b`
1375
- },
1376
- {
1377
- name: "united_bank_routing_ca",
1378
- pattern: String.raw`\\b122243350\\b`
1379
- },
1380
- {
1381
- name: "wells_fargo_routing_ca",
1382
- pattern: String.raw`\\b121042882\\b`
1383
- },
1384
- // Unrealistic alphanumeric identifiers
1385
- {
1386
- name: "generic_non_usual",
1387
- pattern: String.raw`(?:^|\s)(?=[A-Za-z0-9_\)\*\=@]*[A-Za-z])(?=[A-Za-z0-9_\)\*\=@]*[0-9])([A-Za-z0-9_\)\*\=@]{5,})(?=\s|$)`
1388
1351
  }
1389
1352
  ];
1390
1353
 
@@ -2046,12 +2009,6 @@ function applyContextAttributes(span) {
2046
2009
  var DEFAULT_MASKING_RULES = [
2047
2010
  {
2048
2011
  mode: "partial",
2049
- attributePattern: "gen_ai.prompt",
2050
- patterns: DEFAULT_PII_PATTERNS
2051
- },
2052
- {
2053
- mode: "partial",
2054
- attributePattern: "gen_ai.completion",
2055
2012
  patterns: DEFAULT_PII_PATTERNS
2056
2013
  }
2057
2014
  ];
@@ -2061,24 +2018,16 @@ var BrizzSimpleSpanProcessor = class extends SimpleSpanProcessor {
2061
2018
  super(spanExporter);
2062
2019
  this.config = config;
2063
2020
  }
2064
- // Will work with the following code:
2065
- // const span = tracer.startSpan('sensitive-operation',{attributes:{
2066
- // 'user.password': 'secret123',
2067
- // 'user.email': 'user@example.com',
2068
- // }});
2069
- //
2070
- // Won't work because onStart is called before attributes are set:
2071
- // span.setAttributes({
2072
- // 'user.password': 'secret123',
2073
- // 'user.email': 'user@example.com'
2074
- // });
2075
2021
  onStart(span, parentContext) {
2022
+ applyContextAttributes(span);
2023
+ super.onStart(span, parentContext);
2024
+ }
2025
+ onEnd(span) {
2076
2026
  const maskingConfig = this.config.masking?.spanMasking;
2077
2027
  if (maskingConfig) {
2078
- maskSpan(span, maskingConfig);
2028
+ maskReadableSpan(span, maskingConfig);
2079
2029
  }
2080
- applyContextAttributes(span);
2081
- super.onStart(span, parentContext);
2030
+ super.onEnd(span);
2082
2031
  }
2083
2032
  };
2084
2033
  var BrizzBatchSpanProcessor = class extends BatchSpanProcessor {
@@ -2088,39 +2037,39 @@ var BrizzBatchSpanProcessor = class extends BatchSpanProcessor {
2088
2037
  this.config = config;
2089
2038
  }
2090
2039
  onStart(span, parentContext) {
2040
+ applyContextAttributes(span);
2041
+ super.onStart(span, parentContext);
2042
+ }
2043
+ onEnd(span) {
2091
2044
  const maskingConfig = this.config.masking?.spanMasking;
2092
2045
  if (maskingConfig) {
2093
- maskSpan(span, maskingConfig);
2046
+ maskReadableSpan(span, maskingConfig);
2094
2047
  }
2095
- applyContextAttributes(span);
2096
- super.onStart(span, parentContext);
2048
+ super.onEnd(span);
2097
2049
  }
2098
2050
  };
2099
- function maskSpan(span, config) {
2100
- if (!span.attributes || Object.keys(span.attributes).length === 0) {
2101
- return span;
2051
+ function maskReadableSpan(span, config) {
2052
+ const attrs = span.attributes;
2053
+ if (!attrs || Object.keys(attrs).length === 0) {
2054
+ return;
2102
2055
  }
2103
- let rules = config.rules || [];
2056
+ let rules = config.rules ? [...config.rules] : [];
2104
2057
  if (!config.disableDefaultRules) {
2105
- rules = [...DEFAULT_MASKING_RULES, ...rules];
2058
+ rules = [...rules, ...DEFAULT_MASKING_RULES];
2106
2059
  }
2107
2060
  try {
2108
- const attributesRecord = {};
2109
- for (const [key, value] of Object.entries(span.attributes)) {
2110
- attributesRecord[key] = value;
2111
- }
2112
- const maskedAttributes = maskAttributes(attributesRecord, rules);
2113
- if (maskedAttributes && Object.keys(maskedAttributes).length > 0) {
2114
- const merged = { ...span.attributes };
2115
- for (const [key, value] of Object.entries(maskedAttributes)) {
2116
- 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;
2117
2069
  }
2118
- span.setAttributes(merged);
2119
2070
  }
2120
- return span;
2121
2071
  } catch (error) {
2122
- logger.error("Error masking span:", error);
2123
- return span;
2072
+ logger.error("Error masking span", { err: error });
2124
2073
  }
2125
2074
  }
2126
2075
 
@@ -2233,7 +2182,7 @@ function getSpanProcessor() {
2233
2182
  }
2234
2183
 
2235
2184
  // src/internal/trace/session.ts
2236
- import { context as context5, trace as trace3, SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
2185
+ import { context as context5, trace as trace3, SpanStatusCode as SpanStatusCode3 } from "@opentelemetry/api";
2237
2186
 
2238
2187
  // src/internal/sdk.ts
2239
2188
  var _Brizz = class __Brizz {
@@ -2565,15 +2514,18 @@ if (runtime.isESM && runtime.supportsLoaderAPI) {
2565
2514
  maybeRegisterESMLoader();
2566
2515
  }
2567
2516
  try {
2568
- Brizz.initialize({
2569
- apiKey: process.env["BRIZZ_API_KEY"],
2570
- baseUrl: process.env["BRIZZ_BASE_URL"],
2571
- appName: process.env["BRIZZ_APP_NAME"] || process.env["OTEL_SERVICE_NAME"],
2572
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2573
- logLevel: process.env["BRIZZ_LOG_LEVEL"] || DEFAULT_LOG_LEVEL.toString(),
2574
- // Enable auto-instrumentation by default in preload mode
2575
- disableNodeSdk: false
2576
- });
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
+ }
2577
2529
  logger.info(`SDK auto-initialized for ${runtime.isESM ? "ESM" : "CJS"} runtime`);
2578
2530
  } catch (error) {
2579
2531
  logger.warn("Failed to auto-initialize SDK:", { error });