@mastra/observability 1.0.0-beta.1 → 1.0.0-beta.2
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/CHANGELOG.md +16 -0
- package/dist/config.d.ts +107 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/exporters/index.d.ts +1 -0
- package/dist/exporters/index.d.ts.map +1 -1
- package/dist/exporters/test.d.ts +13 -0
- package/dist/exporters/test.d.ts.map +1 -0
- package/dist/index.cjs +184 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +183 -30
- package/dist/index.js.map +1 -1
- package/dist/instances/base.d.ts +9 -5
- package/dist/instances/base.d.ts.map +1 -1
- package/dist/span_processors/sensitive-data-filter.d.ts +7 -0
- package/dist/span_processors/sensitive-data-filter.d.ts.map +1 -1
- package/dist/spans/base.d.ts +39 -0
- package/dist/spans/base.d.ts.map +1 -1
- package/dist/spans/default.d.ts.map +1 -1
- package/package.json +8 -6
package/dist/index.js
CHANGED
|
@@ -35,18 +35,38 @@ var observabilityInstanceConfigSchema = z.object({
|
|
|
35
35
|
serviceName: z.string().min(1, "Service name is required"),
|
|
36
36
|
sampling: samplingStrategySchema.optional(),
|
|
37
37
|
exporters: z.array(z.any()).optional(),
|
|
38
|
+
bridge: z.any().optional(),
|
|
38
39
|
spanOutputProcessors: z.array(z.any()).optional(),
|
|
39
40
|
includeInternalSpans: z.boolean().optional(),
|
|
40
41
|
requestContextKeys: z.array(z.string()).optional()
|
|
41
|
-
})
|
|
42
|
+
}).refine(
|
|
43
|
+
(data) => {
|
|
44
|
+
const hasExporters = data.exporters && data.exporters.length > 0;
|
|
45
|
+
const hasBridge = !!data.bridge;
|
|
46
|
+
return hasExporters || hasBridge;
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
message: "At least one exporter or a bridge is required"
|
|
50
|
+
}
|
|
51
|
+
);
|
|
42
52
|
var observabilityConfigValueSchema = z.object({
|
|
43
53
|
serviceName: z.string().min(1, "Service name is required"),
|
|
44
54
|
sampling: samplingStrategySchema.optional(),
|
|
45
55
|
exporters: z.array(z.any()).optional(),
|
|
56
|
+
bridge: z.any().optional(),
|
|
46
57
|
spanOutputProcessors: z.array(z.any()).optional(),
|
|
47
58
|
includeInternalSpans: z.boolean().optional(),
|
|
48
59
|
requestContextKeys: z.array(z.string()).optional()
|
|
49
|
-
})
|
|
60
|
+
}).refine(
|
|
61
|
+
(data) => {
|
|
62
|
+
const hasExporters = data.exporters && data.exporters.length > 0;
|
|
63
|
+
const hasBridge = !!data.bridge;
|
|
64
|
+
return hasExporters || hasBridge;
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
message: "At least one exporter or a bridge is required"
|
|
68
|
+
}
|
|
69
|
+
);
|
|
50
70
|
var observabilityRegistryConfigSchema = z.object({
|
|
51
71
|
default: z.object({
|
|
52
72
|
enabled: z.boolean().optional()
|
|
@@ -73,6 +93,18 @@ var observabilityRegistryConfigSchema = z.object({
|
|
|
73
93
|
{
|
|
74
94
|
message: 'A "configSelector" function is required when multiple configs are specified to determine which config to use.'
|
|
75
95
|
}
|
|
96
|
+
).refine(
|
|
97
|
+
(data) => {
|
|
98
|
+
if (data.configSelector) {
|
|
99
|
+
const isDefaultEnabled = data.default?.enabled === true;
|
|
100
|
+
const hasConfigs = data.configs && typeof data.configs === "object" && !Array.isArray(data.configs) ? Object.keys(data.configs).length > 0 : false;
|
|
101
|
+
return isDefaultEnabled || hasConfigs;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
message: 'A "configSelector" requires at least one config or default observability to be configured.'
|
|
107
|
+
}
|
|
76
108
|
);
|
|
77
109
|
var BaseExporter = class {
|
|
78
110
|
/** Mastra logger instance */
|
|
@@ -893,6 +925,27 @@ var DefaultExporter = class extends BaseExporter {
|
|
|
893
925
|
this.logger.info("DefaultExporter shutdown complete");
|
|
894
926
|
}
|
|
895
927
|
};
|
|
928
|
+
|
|
929
|
+
// src/exporters/test.ts
|
|
930
|
+
var TestExporter = class extends BaseExporter {
|
|
931
|
+
name = "tracing-test-exporter";
|
|
932
|
+
#events = [];
|
|
933
|
+
constructor(config = {}) {
|
|
934
|
+
super(config);
|
|
935
|
+
}
|
|
936
|
+
async _exportTracingEvent(event) {
|
|
937
|
+
this.#events.push(event);
|
|
938
|
+
}
|
|
939
|
+
clearEvents() {
|
|
940
|
+
this.#events = [];
|
|
941
|
+
}
|
|
942
|
+
get events() {
|
|
943
|
+
return this.#events;
|
|
944
|
+
}
|
|
945
|
+
async shutdown() {
|
|
946
|
+
this.logger.info("TestExporter shutdown");
|
|
947
|
+
}
|
|
948
|
+
};
|
|
896
949
|
var ModelSpanTracker = class {
|
|
897
950
|
#modelSpan;
|
|
898
951
|
#currentStepSpan;
|
|
@@ -1224,6 +1277,16 @@ function isSpanInternal(spanType, flags) {
|
|
|
1224
1277
|
return false;
|
|
1225
1278
|
}
|
|
1226
1279
|
}
|
|
1280
|
+
function getExternalParentId(options) {
|
|
1281
|
+
if (!options.parent) {
|
|
1282
|
+
return void 0;
|
|
1283
|
+
}
|
|
1284
|
+
if (options.parent.isInternal) {
|
|
1285
|
+
return options.parent.getParentSpanId(false);
|
|
1286
|
+
} else {
|
|
1287
|
+
return options.parent.id;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1227
1290
|
var BaseSpan = class {
|
|
1228
1291
|
name;
|
|
1229
1292
|
type;
|
|
@@ -1238,6 +1301,7 @@ var BaseSpan = class {
|
|
|
1238
1301
|
output;
|
|
1239
1302
|
errorInfo;
|
|
1240
1303
|
metadata;
|
|
1304
|
+
tags;
|
|
1241
1305
|
traceState;
|
|
1242
1306
|
/** Parent span ID (for root spans that are children of external spans) */
|
|
1243
1307
|
parentSpanId;
|
|
@@ -1252,6 +1316,7 @@ var BaseSpan = class {
|
|
|
1252
1316
|
this.isEvent = options.isEvent ?? false;
|
|
1253
1317
|
this.isInternal = isSpanInternal(this.type, options.tracingPolicy?.internal);
|
|
1254
1318
|
this.traceState = options.traceState;
|
|
1319
|
+
this.tags = !options.parent && options.tags?.length ? options.tags : void 0;
|
|
1255
1320
|
if (this.isEvent) {
|
|
1256
1321
|
this.output = deepClean(options.output);
|
|
1257
1322
|
} else {
|
|
@@ -1314,12 +1379,36 @@ var BaseSpan = class {
|
|
|
1314
1379
|
errorInfo: this.errorInfo,
|
|
1315
1380
|
isEvent: this.isEvent,
|
|
1316
1381
|
isRootSpan: this.isRootSpan,
|
|
1317
|
-
parentSpanId: this.getParentSpanId(includeInternalSpans)
|
|
1382
|
+
parentSpanId: this.getParentSpanId(includeInternalSpans),
|
|
1383
|
+
// Tags are only included for root spans
|
|
1384
|
+
...this.isRootSpan && this.tags?.length ? { tags: this.tags } : {}
|
|
1318
1385
|
};
|
|
1319
1386
|
}
|
|
1320
1387
|
get externalTraceId() {
|
|
1321
1388
|
return this.isValid ? this.traceId : void 0;
|
|
1322
1389
|
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Execute an async function within this span's tracing context.
|
|
1392
|
+
* Delegates to the bridge if available.
|
|
1393
|
+
*/
|
|
1394
|
+
async executeInContext(fn) {
|
|
1395
|
+
const bridge = this.observabilityInstance.getBridge();
|
|
1396
|
+
if (bridge?.executeInContext) {
|
|
1397
|
+
return bridge.executeInContext(this.id, fn);
|
|
1398
|
+
}
|
|
1399
|
+
return fn();
|
|
1400
|
+
}
|
|
1401
|
+
/**
|
|
1402
|
+
* Execute a synchronous function within this span's tracing context.
|
|
1403
|
+
* Delegates to the bridge if available.
|
|
1404
|
+
*/
|
|
1405
|
+
executeInContextSync(fn) {
|
|
1406
|
+
const bridge = this.observabilityInstance.getBridge();
|
|
1407
|
+
if (bridge?.executeInContextSync) {
|
|
1408
|
+
return bridge.executeInContextSync(this.id, fn);
|
|
1409
|
+
}
|
|
1410
|
+
return fn();
|
|
1411
|
+
}
|
|
1323
1412
|
};
|
|
1324
1413
|
var DEFAULT_KEYS_TO_STRIP = /* @__PURE__ */ new Set([
|
|
1325
1414
|
"logger",
|
|
@@ -1366,27 +1455,30 @@ var DefaultSpan = class extends BaseSpan {
|
|
|
1366
1455
|
traceId;
|
|
1367
1456
|
constructor(options, observabilityInstance) {
|
|
1368
1457
|
super(options, observabilityInstance);
|
|
1369
|
-
|
|
1458
|
+
const bridge = observabilityInstance.getBridge();
|
|
1459
|
+
if (bridge && !this.isInternal) {
|
|
1460
|
+
const bridgeIds = bridge.createSpan(options);
|
|
1461
|
+
if (bridgeIds) {
|
|
1462
|
+
this.id = bridgeIds.spanId;
|
|
1463
|
+
this.traceId = bridgeIds.traceId;
|
|
1464
|
+
this.parentSpanId = bridgeIds.parentSpanId;
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1370
1468
|
if (options.parent) {
|
|
1371
1469
|
this.traceId = options.parent.traceId;
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
} else {
|
|
1376
|
-
console.error(
|
|
1377
|
-
`[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
|
|
1378
|
-
);
|
|
1379
|
-
this.traceId = generateTraceId();
|
|
1380
|
-
}
|
|
1381
|
-
} else {
|
|
1382
|
-
this.traceId = generateTraceId();
|
|
1470
|
+
this.parentSpanId = options.parent.id;
|
|
1471
|
+
this.id = generateSpanId();
|
|
1472
|
+
return;
|
|
1383
1473
|
}
|
|
1384
|
-
|
|
1474
|
+
this.traceId = getOrCreateTraceId(options);
|
|
1475
|
+
this.id = generateSpanId();
|
|
1476
|
+
if (options.parentSpanId) {
|
|
1385
1477
|
if (isValidSpanId(options.parentSpanId)) {
|
|
1386
1478
|
this.parentSpanId = options.parentSpanId;
|
|
1387
1479
|
} else {
|
|
1388
1480
|
console.error(
|
|
1389
|
-
`[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring
|
|
1481
|
+
`[Mastra Tracing] Invalid parentSpanId: must be 1-16 hexadecimal characters, got "${options.parentSpanId}". Ignoring.`
|
|
1390
1482
|
);
|
|
1391
1483
|
}
|
|
1392
1484
|
}
|
|
@@ -1491,6 +1583,18 @@ function isValidTraceId(traceId) {
|
|
|
1491
1583
|
function isValidSpanId(spanId) {
|
|
1492
1584
|
return /^[0-9a-f]{1,16}$/i.test(spanId);
|
|
1493
1585
|
}
|
|
1586
|
+
function getOrCreateTraceId(options) {
|
|
1587
|
+
if (options.traceId) {
|
|
1588
|
+
if (isValidTraceId(options.traceId)) {
|
|
1589
|
+
return options.traceId;
|
|
1590
|
+
} else {
|
|
1591
|
+
console.error(
|
|
1592
|
+
`[Mastra Tracing] Invalid traceId: must be 1-32 hexadecimal characters, got "${options.traceId}". Generating new trace ID.`
|
|
1593
|
+
);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
return generateTraceId();
|
|
1597
|
+
}
|
|
1494
1598
|
|
|
1495
1599
|
// src/spans/no-op.ts
|
|
1496
1600
|
var NoOpSpan = class extends BaseSpan {
|
|
@@ -1523,13 +1627,17 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1523
1627
|
sampling: config.sampling ?? { type: "always" /* ALWAYS */ },
|
|
1524
1628
|
exporters: config.exporters ?? [],
|
|
1525
1629
|
spanOutputProcessors: config.spanOutputProcessors ?? [],
|
|
1630
|
+
bridge: config.bridge ?? void 0,
|
|
1526
1631
|
includeInternalSpans: config.includeInternalSpans ?? false,
|
|
1527
1632
|
requestContextKeys: config.requestContextKeys ?? []
|
|
1528
1633
|
};
|
|
1634
|
+
if (this.config.bridge?.init) {
|
|
1635
|
+
this.config.bridge.init({ config: this.config });
|
|
1636
|
+
}
|
|
1529
1637
|
}
|
|
1530
1638
|
/**
|
|
1531
1639
|
* Override setLogger to add Observability specific initialization log
|
|
1532
|
-
* and propagate logger to exporters
|
|
1640
|
+
* and propagate logger to exporters and bridge
|
|
1533
1641
|
*/
|
|
1534
1642
|
__setLogger(logger) {
|
|
1535
1643
|
super.__setLogger(logger);
|
|
@@ -1538,8 +1646,11 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1538
1646
|
exporter.__setLogger(logger);
|
|
1539
1647
|
}
|
|
1540
1648
|
});
|
|
1649
|
+
if (this.config.bridge?.__setLogger) {
|
|
1650
|
+
this.config.bridge.__setLogger(logger);
|
|
1651
|
+
}
|
|
1541
1652
|
this.logger.debug(
|
|
1542
|
-
`[Observability] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling
|
|
1653
|
+
`[Observability] Initialized [service=${this.config.serviceName}] [instance=${this.config.name}] [sampling=${this.config.sampling?.type}] [bridge=${!!this.config.bridge}]`
|
|
1543
1654
|
);
|
|
1544
1655
|
}
|
|
1545
1656
|
// ============================================================================
|
|
@@ -1568,11 +1679,15 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1568
1679
|
} else {
|
|
1569
1680
|
traceState = this.computeTraceState(tracingOptions);
|
|
1570
1681
|
}
|
|
1571
|
-
const
|
|
1682
|
+
const tracingMetadata = !options.parent ? tracingOptions?.metadata : void 0;
|
|
1683
|
+
const mergedMetadata = metadata || tracingMetadata ? { ...metadata, ...tracingMetadata } : void 0;
|
|
1684
|
+
const enrichedMetadata = this.extractMetadataFromRequestContext(requestContext, mergedMetadata, traceState);
|
|
1685
|
+
const tags = !options.parent ? tracingOptions?.tags : void 0;
|
|
1572
1686
|
const span = this.createSpan({
|
|
1573
1687
|
...rest,
|
|
1574
1688
|
metadata: enrichedMetadata,
|
|
1575
|
-
traceState
|
|
1689
|
+
traceState,
|
|
1690
|
+
tags
|
|
1576
1691
|
});
|
|
1577
1692
|
if (span.isEvent) {
|
|
1578
1693
|
this.emitSpanEnded(span);
|
|
@@ -1606,6 +1721,12 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1606
1721
|
getSpanOutputProcessors() {
|
|
1607
1722
|
return [...this.spanOutputProcessors];
|
|
1608
1723
|
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Get the bridge instance if configured
|
|
1726
|
+
*/
|
|
1727
|
+
getBridge() {
|
|
1728
|
+
return this.config.bridge;
|
|
1729
|
+
}
|
|
1609
1730
|
/**
|
|
1610
1731
|
* Get the logger instance (for exporters and other components)
|
|
1611
1732
|
*/
|
|
@@ -1650,7 +1771,9 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1650
1771
|
*/
|
|
1651
1772
|
shouldSample(options) {
|
|
1652
1773
|
const { sampling } = this.config;
|
|
1653
|
-
switch (sampling
|
|
1774
|
+
switch (sampling?.type) {
|
|
1775
|
+
case void 0:
|
|
1776
|
+
return true;
|
|
1654
1777
|
case "always" /* ALWAYS */:
|
|
1655
1778
|
return true;
|
|
1656
1779
|
case "never" /* NEVER */:
|
|
@@ -1782,17 +1905,21 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1782
1905
|
}
|
|
1783
1906
|
}
|
|
1784
1907
|
/**
|
|
1785
|
-
* Export tracing event through all exporters (realtime mode)
|
|
1908
|
+
* Export tracing event through all exporters and bridge (realtime mode)
|
|
1786
1909
|
*/
|
|
1787
1910
|
async exportTracingEvent(event) {
|
|
1788
|
-
const
|
|
1911
|
+
const targets = [
|
|
1912
|
+
...this.exporters
|
|
1913
|
+
];
|
|
1914
|
+
if (this.config.bridge) {
|
|
1915
|
+
targets.push(this.config.bridge);
|
|
1916
|
+
}
|
|
1917
|
+
const exportPromises = targets.map(async (target) => {
|
|
1789
1918
|
try {
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
this.logger.debug(`[Observability] Event exported [exporter=${exporter.name}] [type=${event.type}]`);
|
|
1793
|
-
}
|
|
1919
|
+
await target.exportTracingEvent(event);
|
|
1920
|
+
this.logger.debug(`[Observability] Event exported [target=${target.name}] [type=${event.type}]`);
|
|
1794
1921
|
} catch (error) {
|
|
1795
|
-
this.logger.error(`[Observability] Export error [
|
|
1922
|
+
this.logger.error(`[Observability] Export error [target=${target.name}]`, error);
|
|
1796
1923
|
}
|
|
1797
1924
|
});
|
|
1798
1925
|
await Promise.allSettled(exportPromises);
|
|
@@ -1816,6 +1943,9 @@ var BaseObservabilityInstance = class extends MastraBase {
|
|
|
1816
1943
|
...this.exporters.map((e) => e.shutdown()),
|
|
1817
1944
|
...this.spanOutputProcessors.map((p) => p.shutdown())
|
|
1818
1945
|
];
|
|
1946
|
+
if (this.config.bridge) {
|
|
1947
|
+
shutdownPromises.push(this.config.bridge.shutdown());
|
|
1948
|
+
}
|
|
1819
1949
|
await Promise.allSettled(shutdownPromises);
|
|
1820
1950
|
this.logger.info(`[Observability] Shutdown completed [name=${this.name}]`);
|
|
1821
1951
|
}
|
|
@@ -1962,9 +2092,16 @@ var SensitiveDataFilter = class {
|
|
|
1962
2092
|
/**
|
|
1963
2093
|
* Recursively filter objects/arrays for sensitive keys.
|
|
1964
2094
|
* Handles circular references by replacing with a marker.
|
|
2095
|
+
* Also attempts to parse and redact JSON strings.
|
|
1965
2096
|
*/
|
|
1966
2097
|
deepFilter(obj, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1967
2098
|
if (obj === null || typeof obj !== "object") {
|
|
2099
|
+
if (typeof obj === "string") {
|
|
2100
|
+
const trimmed = obj.trim();
|
|
2101
|
+
if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
|
|
2102
|
+
return this.redactJsonString(obj);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
1968
2105
|
return obj;
|
|
1969
2106
|
}
|
|
1970
2107
|
if (seen.has(obj)) {
|
|
@@ -2017,6 +2154,22 @@ var SensitiveDataFilter = class {
|
|
|
2017
2154
|
return normalizedKey === sensitiveField;
|
|
2018
2155
|
});
|
|
2019
2156
|
}
|
|
2157
|
+
/**
|
|
2158
|
+
* Attempt to parse a string as JSON and redact sensitive fields within it.
|
|
2159
|
+
* If parsing fails or no sensitive data is found, returns the original string.
|
|
2160
|
+
*/
|
|
2161
|
+
redactJsonString(str) {
|
|
2162
|
+
try {
|
|
2163
|
+
const parsed = JSON.parse(str);
|
|
2164
|
+
if (parsed && typeof parsed === "object") {
|
|
2165
|
+
const filtered = this.deepFilter(parsed, /* @__PURE__ */ new WeakSet());
|
|
2166
|
+
return JSON.stringify(filtered);
|
|
2167
|
+
}
|
|
2168
|
+
return str;
|
|
2169
|
+
} catch {
|
|
2170
|
+
return str;
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2020
2173
|
/**
|
|
2021
2174
|
* Redact a sensitive value.
|
|
2022
2175
|
* - Full style: replaces with a fixed token.
|
|
@@ -2169,6 +2322,6 @@ var Observability = class extends MastraBase {
|
|
|
2169
2322
|
}
|
|
2170
2323
|
};
|
|
2171
2324
|
|
|
2172
|
-
export { BaseExporter, BaseObservabilityInstance, BaseSpan, CloudExporter, ConsoleExporter, DefaultExporter, DefaultObservabilityInstance, DefaultSpan, ModelSpanTracker, NoOpSpan, Observability, SamplingStrategyType, SensitiveDataFilter, deepClean, observabilityConfigValueSchema, observabilityInstanceConfigSchema, observabilityRegistryConfigSchema, samplingStrategySchema };
|
|
2325
|
+
export { BaseExporter, BaseObservabilityInstance, BaseSpan, CloudExporter, ConsoleExporter, DefaultExporter, DefaultObservabilityInstance, DefaultSpan, ModelSpanTracker, NoOpSpan, Observability, SamplingStrategyType, SensitiveDataFilter, TestExporter, deepClean, getExternalParentId, observabilityConfigValueSchema, observabilityInstanceConfigSchema, observabilityRegistryConfigSchema, samplingStrategySchema };
|
|
2173
2326
|
//# sourceMappingURL=index.js.map
|
|
2174
2327
|
//# sourceMappingURL=index.js.map
|