@brizz/sdk 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -292,6 +292,21 @@ import { callWithSessionId } from '@brizz/sdk';
292
292
  await callWithSessionId('session-123', processUserWorkflow, null, 'user-456');
293
293
  ```
294
294
 
295
+ ### Custom Properties
296
+
297
+ Add custom properties to telemetry context:
298
+
299
+ ```typescript
300
+ import { withProperties, callWithProperties } from '@brizz/sdk';
301
+
302
+ // Wrapper pattern - properties applied to all calls
303
+ const taggedFn = withProperties({ env: 'prod', feature: 'chat' }, myFunction);
304
+ await taggedFn(args);
305
+
306
+ // Immediate execution - properties applied once
307
+ await callWithProperties({ userId: 'user-123' }, myFunction, null, args);
308
+ ```
309
+
295
310
  ### Handling Method Context
296
311
 
297
312
  When wrapping methods that use `this`, you have several options:
@@ -334,6 +349,18 @@ const sessionedProcess = withSessionId(
334
349
  **Note:** The arrow function approach (Option 1) is recommended as it's more explicit, avoids lint
335
350
  warnings, and is less prone to `this` binding issues.
336
351
 
352
+ ## Deployment Environment
353
+
354
+ Optionally specify the deployment environment for better filtering and organization:
355
+
356
+ ```typescript
357
+ Brizz.initialize({
358
+ apiKey: 'your-api-key',
359
+ appName: 'my-app',
360
+ environment: 'production', // Optional: 'dev', 'staging', 'production', etc.
361
+ });
362
+ ```
363
+
337
364
  ## Custom Events & Logging
338
365
 
339
366
  Emit custom events and structured logs:
package/dist/index.cjs CHANGED
@@ -34,6 +34,7 @@ __export(src_exports, {
34
34
  DEFAULT_PII_PATTERNS: () => DEFAULT_PII_PATTERNS,
35
35
  LogLevel: () => LogLevel,
36
36
  SeverityNumber: () => import_api_logs2.SeverityNumber,
37
+ callWithProperties: () => callWithProperties,
37
38
  callWithSessionId: () => callWithSessionId,
38
39
  detectRuntime: () => detectRuntime,
39
40
  emitEvent: () => emitEvent,
@@ -47,6 +48,7 @@ __export(src_exports, {
47
48
  maskAttributes: () => maskAttributes,
48
49
  maskValue: () => maskValue,
49
50
  setLogLevel: () => setLogLevel,
51
+ withProperties: () => withProperties,
50
52
  withSessionId: () => withSessionId
51
53
  });
52
54
  module.exports = __toCommonJS(src_exports);
@@ -326,6 +328,7 @@ function resolveConfig(options) {
326
328
  headers: { ...options.headers },
327
329
  apiKey: process.env["BRIZZ_API_KEY"] || options.apiKey,
328
330
  disableBatch: process.env["BRIZZ_DISABLE_BATCH"] === "true" || !!options.disableBatch,
331
+ environment: process.env["BRIZZ_ENVIRONMENT"] || options.environment,
329
332
  logLevel: resolvedLogLevel,
330
333
  masking: resolvedMasking
331
334
  };
@@ -1020,7 +1023,7 @@ function maskStringByPattern(value, pattern, mode = "full") {
1020
1023
  logger.warn("Regex execution failed, skipping masking", error);
1021
1024
  return value;
1022
1025
  }
1023
- for (const matchInfo of matches.reverse()) {
1026
+ for (const matchInfo of matches.toReversed()) {
1024
1027
  let patternName = "unknown";
1025
1028
  if (matchInfo.groups) {
1026
1029
  for (const [groupName, groupValue] of Object.entries(matchInfo.groups)) {
@@ -1266,9 +1269,13 @@ var LoggingModule = class _LoggingModule {
1266
1269
  logger.debug("Creating resource with service name", {
1267
1270
  serviceName: config.appName
1268
1271
  });
1269
- const resource = (0, import_resources.resourceFromAttributes)({
1272
+ const resourceAttributes = {
1270
1273
  "service.name": config.appName
1271
- });
1274
+ };
1275
+ if (config.environment) {
1276
+ resourceAttributes["deployment.environment"] = config.environment;
1277
+ }
1278
+ const resource = (0, import_resources.resourceFromAttributes)(resourceAttributes);
1272
1279
  logger.debug("Creating logger provider with resource");
1273
1280
  this.loggerProvider = new import_sdk_logs2.LoggerProvider({
1274
1281
  resource,
@@ -1459,130 +1466,6 @@ var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otl
1459
1466
  // src/internal/trace/processors/span-processor.ts
1460
1467
  var import_api4 = require("@opentelemetry/api");
1461
1468
  var import_sdk_trace_base = require("@opentelemetry/sdk-trace-base");
1462
-
1463
- // src/internal/trace/transformations/vercel-ai.ts
1464
- var import_ai_semantic_conventions = require("@traceloop/ai-semantic-conventions");
1465
- var AI_GENERATE_TEXT_DO_GENERATE = "ai.generateText.doGenerate";
1466
- var AI_STREAM_TEXT_DO_STREAM = "ai.streamText.doStream";
1467
- var HANDLED_SPAN_NAMES = {
1468
- [AI_GENERATE_TEXT_DO_GENERATE]: "gen_ai.chat",
1469
- [AI_STREAM_TEXT_DO_STREAM]: "gen_ai.chat",
1470
- "ai.streamText": "ai.streamText",
1471
- "ai.toolCall": (span) => {
1472
- const toolName = span.attributes["ai.toolCall.name"];
1473
- return `${String(toolName ?? "unknown")}.tool`;
1474
- }
1475
- };
1476
- var AI_RESPONSE_TEXT = "ai.response.text";
1477
- var AI_PROMPT_MESSAGES = "ai.prompt.messages";
1478
- var AI_USAGE_PROMPT_TOKENS = "ai.usage.promptTokens";
1479
- var AI_USAGE_COMPLETION_TOKENS = "ai.usage.completionTokens";
1480
- var AI_MODEL_PROVIDER = "ai.model.provider";
1481
- var transformAiSdkSpanName = (span) => {
1482
- if (span.name in HANDLED_SPAN_NAMES) {
1483
- const handler = HANDLED_SPAN_NAMES[span.name];
1484
- if (typeof handler === "function") {
1485
- span.name = handler(span);
1486
- } else if (handler) {
1487
- span.name = handler;
1488
- }
1489
- }
1490
- };
1491
- var transformResponseText = (attributes) => {
1492
- if (AI_RESPONSE_TEXT in attributes) {
1493
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_COMPLETIONS}.0.content`] = attributes[AI_RESPONSE_TEXT];
1494
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_COMPLETIONS}.0.role`] = "assistant";
1495
- delete attributes[AI_RESPONSE_TEXT];
1496
- }
1497
- };
1498
- var transformPromptMessages = (attributes) => {
1499
- if (AI_PROMPT_MESSAGES in attributes) {
1500
- try {
1501
- const messages = JSON.parse(attributes[AI_PROMPT_MESSAGES]);
1502
- for (const [index, msg] of messages.entries()) {
1503
- const message = msg;
1504
- logger.debug("Transforming prompt message", { msg: message, type: typeof message.content });
1505
- if (typeof message.content === "string") {
1506
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = message.content;
1507
- } else {
1508
- if (Array.isArray(message.content) && message.content.length > 0) {
1509
- const lastContent = message.content.at(-1);
1510
- if (lastContent?.text) {
1511
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = lastContent.text;
1512
- }
1513
- } else {
1514
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.content`] = JSON.stringify(
1515
- message.content
1516
- );
1517
- }
1518
- }
1519
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_PROMPTS}.${index}.role`] = message.role;
1520
- }
1521
- delete attributes[AI_PROMPT_MESSAGES];
1522
- } catch (error) {
1523
- logger.debug("Skipping prompt messages transformation because of JSON parsing error", {
1524
- e: error
1525
- });
1526
- }
1527
- }
1528
- };
1529
- var transformPromptTokens = (attributes) => {
1530
- if (AI_USAGE_PROMPT_TOKENS in attributes) {
1531
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_PROMPT_TOKENS}`] = attributes[AI_USAGE_PROMPT_TOKENS];
1532
- delete attributes[AI_USAGE_PROMPT_TOKENS];
1533
- }
1534
- };
1535
- var transformCompletionTokens = (attributes) => {
1536
- if (AI_USAGE_COMPLETION_TOKENS in attributes) {
1537
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_COMPLETION_TOKENS}`] = attributes[AI_USAGE_COMPLETION_TOKENS];
1538
- delete attributes[AI_USAGE_COMPLETION_TOKENS];
1539
- }
1540
- };
1541
- var calculateTotalTokens = (attributes) => {
1542
- const promptTokens = attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_PROMPT_TOKENS}`];
1543
- const completionTokens = attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_COMPLETION_TOKENS}`];
1544
- if (promptTokens && completionTokens) {
1545
- attributes[`${import_ai_semantic_conventions.SpanAttributes.LLM_USAGE_TOTAL_TOKENS}`] = Number(promptTokens) + Number(completionTokens);
1546
- }
1547
- };
1548
- var transformVendor = (attributes) => {
1549
- if (AI_MODEL_PROVIDER in attributes) {
1550
- const vendor = attributes[AI_MODEL_PROVIDER];
1551
- attributes[import_ai_semantic_conventions.SpanAttributes.LLM_SYSTEM] = vendor && vendor.startsWith("openai") ? "OpenAI" : vendor;
1552
- delete attributes[AI_MODEL_PROVIDER];
1553
- }
1554
- };
1555
- var transformAiSdkAttributes = (attributes) => {
1556
- transformResponseText(attributes);
1557
- transformPromptMessages(attributes);
1558
- transformPromptTokens(attributes);
1559
- transformCompletionTokens(attributes);
1560
- calculateTotalTokens(attributes);
1561
- transformVendor(attributes);
1562
- };
1563
- var shouldHandleSpan = (span) => {
1564
- return span.name in HANDLED_SPAN_NAMES;
1565
- };
1566
- var transformAiSdkSpan = (span) => {
1567
- if (!shouldHandleSpan(span)) {
1568
- logger.debug("Skipping span transformation", { spanName: span.name });
1569
- return;
1570
- }
1571
- for (const key in span.attributes) {
1572
- if (Number.isNaN(span.attributes[key])) {
1573
- span.attributes[key] = 0;
1574
- }
1575
- }
1576
- logger.debug("Transforming AI SDK span", {
1577
- spanName: span.name,
1578
- spanContext: span.spanContext(),
1579
- attributes: span.attributes
1580
- });
1581
- transformAiSdkSpanName(span);
1582
- transformAiSdkAttributes(span.attributes);
1583
- };
1584
-
1585
- // src/internal/trace/processors/span-processor.ts
1586
1469
  var DEFAULT_MASKING_RULES = [
1587
1470
  {
1588
1471
  mode: "partial",
@@ -1625,10 +1508,6 @@ var BrizzSimpleSpanProcessor = class extends import_sdk_trace_base.SimpleSpanPro
1625
1508
  }
1626
1509
  super.onStart(span, parentContext);
1627
1510
  }
1628
- onEnd(span) {
1629
- transformAiSdkSpan(span);
1630
- super.onEnd(span);
1631
- }
1632
1511
  };
1633
1512
  var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProcessor {
1634
1513
  config;
@@ -1649,10 +1528,6 @@ var BrizzBatchSpanProcessor = class extends import_sdk_trace_base.BatchSpanProce
1649
1528
  }
1650
1529
  super.onStart(span, parentContext);
1651
1530
  }
1652
- onEnd(span) {
1653
- transformAiSdkSpan(span);
1654
- super.onEnd(span);
1655
- }
1656
1531
  };
1657
1532
  function maskSpan(span, config) {
1658
1533
  if (!span.attributes || Object.keys(span.attributes).length === 0) {
@@ -1785,23 +1660,28 @@ function getSpanProcessor() {
1785
1660
 
1786
1661
  // src/internal/trace/session.ts
1787
1662
  var import_api5 = require("@opentelemetry/api");
1788
- function withProperties(properties, fn, thisArg, ...args) {
1789
- if (Object.keys(properties).length === 0) {
1790
- return fn.apply(thisArg, args);
1791
- }
1792
- const newContext = import_api5.context.active().setValue(PROPERTIES_CONTEXT_KEY, properties);
1793
- return import_api5.context.with(newContext, fn, thisArg, ...args);
1663
+ function callWithProperties(properties, fn, thisArg, ...args) {
1664
+ const base = import_api5.context.active();
1665
+ const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
1666
+ const merged = prev ? { ...prev, ...properties } : properties;
1667
+ const next = base.setValue(PROPERTIES_CONTEXT_KEY, merged);
1668
+ return import_api5.context.with(next, fn, thisArg, ...args);
1794
1669
  }
1795
- function withSessionId(sessionId, fn, thisArg) {
1670
+ function withProperties(properties, fn, thisArg) {
1796
1671
  return function wrapped(...args) {
1797
- const base = import_api5.context.active();
1798
- const prev = base.getValue(PROPERTIES_CONTEXT_KEY);
1799
- const next = base.setValue(PROPERTIES_CONTEXT_KEY, prev ? { ...prev, [SESSION_ID]: sessionId } : { [SESSION_ID]: sessionId });
1800
- return import_api5.context.with(next, fn, thisArg ?? this, ...args);
1672
+ return callWithProperties(
1673
+ properties,
1674
+ fn,
1675
+ thisArg !== void 0 ? thisArg : this,
1676
+ ...args
1677
+ );
1801
1678
  };
1802
1679
  }
1680
+ function withSessionId(sessionId, fn, thisArg) {
1681
+ return withProperties({ [SESSION_ID]: sessionId }, fn, thisArg);
1682
+ }
1803
1683
  function callWithSessionId(sessionId, fn, thisArg, ...args) {
1804
- return withProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
1684
+ return callWithProperties({ [SESSION_ID]: sessionId }, fn, thisArg, ...args);
1805
1685
  }
1806
1686
 
1807
1687
  // src/internal/sdk.ts
@@ -1874,12 +1754,16 @@ var _Brizz = class __Brizz {
1874
1754
  }
1875
1755
  const registry = InstrumentationRegistry.getInstance();
1876
1756
  const manualInstrumentations = registry.getManualInstrumentations();
1757
+ const resourceAttributes = {
1758
+ "service.name": resolvedConfig.appName
1759
+ };
1760
+ if (resolvedConfig.environment) {
1761
+ resourceAttributes["deployment.environment"] = resolvedConfig.environment;
1762
+ }
1877
1763
  this._sdk = new import_sdk_node.NodeSDK({
1878
1764
  spanProcessors: [getSpanProcessor()],
1879
1765
  metricReader: getMetricsReader(),
1880
- resource: (0, import_resources2.resourceFromAttributes)({
1881
- "service.name": resolvedConfig.appName
1882
- }),
1766
+ resource: (0, import_resources2.resourceFromAttributes)(resourceAttributes),
1883
1767
  instrumentations: manualInstrumentations
1884
1768
  });
1885
1769
  this._sdk.start();
@@ -2003,7 +1887,10 @@ function detectRuntime() {
2003
1887
  const isESM = noNodeJSGlobals && noModuleSystem;
2004
1888
  const isCJS = hasRequire && typeof module !== "undefined" && typeof exports !== "undefined" && typeof __filename === "string" && typeof __dirname === "string";
2005
1889
  const supportsLoaderAPI = (major ?? 0) >= 21 || (major ?? 0) === 20 && (minor ?? 0) >= 6 || (major ?? 0) === 18 && (minor ?? 0) >= 19;
2006
- const supportsRegister = !!process.features?.typescript || !!globalThis.module?.register;
1890
+ const supportsRegister = (
1891
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1892
+ !!process.features?.typescript || !!globalThis.module?.register
1893
+ );
2007
1894
  logger.debug("Runtime detection results:", {
2008
1895
  nodeVersion: `${major ?? 0}.${minor ?? 0}`,
2009
1896
  isESM,
@@ -2024,6 +1911,7 @@ function detectRuntime() {
2024
1911
  module: typeof module,
2025
1912
  exports: typeof exports,
2026
1913
  "process.features": process.features,
1914
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2027
1915
  "globalThis.module": globalThis.module
2028
1916
  }
2029
1917
  });
@@ -2044,6 +1932,7 @@ var init_exports = {};
2044
1932
  DEFAULT_PII_PATTERNS,
2045
1933
  LogLevel,
2046
1934
  SeverityNumber,
1935
+ callWithProperties,
2047
1936
  callWithSessionId,
2048
1937
  detectRuntime,
2049
1938
  emitEvent,
@@ -2057,6 +1946,7 @@ var init_exports = {};
2057
1946
  maskAttributes,
2058
1947
  maskValue,
2059
1948
  setLogLevel,
1949
+ withProperties,
2060
1950
  withSessionId
2061
1951
  });
2062
1952
  //# sourceMappingURL=index.cjs.map