@mastra/posthog 1.0.0-beta.10 → 1.0.0-beta.12
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 +60 -0
- package/README.md +34 -3
- package/dist/index.cjs +85 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +86 -113
- package/dist/index.js.map +1 -1
- package/dist/tracing.d.ts +48 -17
- package/dist/tracing.d.ts.map +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# @mastra/posthog
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.12
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added `TrackingExporter` base class with improved handling for: ([#11870](https://github.com/mastra-ai/mastra/pull/11870))
|
|
8
|
+
- **Out-of-order span processing**: Spans that arrive before their parents are now queued and processed once dependencies are available
|
|
9
|
+
- **Delayed cleanup**: Trace data is retained briefly after spans end to handle late-arriving updates
|
|
10
|
+
- **Memory management**: Configurable limits on pending and total traces to prevent memory leaks
|
|
11
|
+
|
|
12
|
+
New configuration options on `TrackingExporterConfig`:
|
|
13
|
+
- `earlyQueueMaxAttempts` - Max retry attempts for queued events (default: 5)
|
|
14
|
+
- `earlyQueueTTLMs` - TTL for queued events in ms (default: 30000)
|
|
15
|
+
- `traceCleanupDelayMs` - Delay before cleaning up completed traces (default: 30000)
|
|
16
|
+
- `maxPendingCleanupTraces` - Soft cap on traces awaiting cleanup (default: 100)
|
|
17
|
+
- `maxTotalTraces` - Hard cap on total traces (default: 500)
|
|
18
|
+
|
|
19
|
+
Updated @mastra/braintrust, @mastra/langfuse, @mastra/langsmith, @mastra/posthog to use the new TrackingExporter
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [[`ebae12a`](https://github.com/mastra-ai/mastra/commit/ebae12a2dd0212e75478981053b148a2c246962d), [`c61a0a5`](https://github.com/mastra-ai/mastra/commit/c61a0a5de4904c88fd8b3718bc26d1be1c2ec6e7), [`69136e7`](https://github.com/mastra-ai/mastra/commit/69136e748e32f57297728a4e0f9a75988462f1a7), [`449aed2`](https://github.com/mastra-ai/mastra/commit/449aed2ba9d507b75bf93d427646ea94f734dfd1), [`eb648a2`](https://github.com/mastra-ai/mastra/commit/eb648a2cc1728f7678768dd70cd77619b448dab9), [`0131105`](https://github.com/mastra-ai/mastra/commit/0131105532e83bdcbb73352fc7d0879eebf140dc), [`9d5059e`](https://github.com/mastra-ai/mastra/commit/9d5059eae810829935fb08e81a9bb7ecd5b144a7), [`ef756c6`](https://github.com/mastra-ai/mastra/commit/ef756c65f82d16531c43f49a27290a416611e526), [`b00ccd3`](https://github.com/mastra-ai/mastra/commit/b00ccd325ebd5d9e37e34dd0a105caae67eb568f), [`3bdfa75`](https://github.com/mastra-ai/mastra/commit/3bdfa7507a91db66f176ba8221aa28dd546e464a), [`e770de9`](https://github.com/mastra-ai/mastra/commit/e770de941a287a49b1964d44db5a5763d19890a6), [`52e2716`](https://github.com/mastra-ai/mastra/commit/52e2716b42df6eff443de72360ae83e86ec23993), [`27b4040`](https://github.com/mastra-ai/mastra/commit/27b4040bfa1a95d92546f420a02a626b1419a1d6), [`610a70b`](https://github.com/mastra-ai/mastra/commit/610a70bdad282079f0c630e0d7bb284578f20151), [`8dc7f55`](https://github.com/mastra-ai/mastra/commit/8dc7f55900395771da851dc7d78d53ae84fe34ec), [`8379099`](https://github.com/mastra-ai/mastra/commit/8379099fc467af6bef54dd7f80c9bd75bf8bbddf), [`b06be72`](https://github.com/mastra-ai/mastra/commit/b06be7223d5ef23edc98c01a67ef713c6cc039f9), [`8c0ec25`](https://github.com/mastra-ai/mastra/commit/8c0ec25646c8a7df253ed1e5ff4863a0d3f1316c), [`ff4d9a6`](https://github.com/mastra-ai/mastra/commit/ff4d9a6704fc87b31a380a76ed22736fdedbba5a), [`69821ef`](https://github.com/mastra-ai/mastra/commit/69821ef806482e2c44e2197ac0b050c3fe3a5285), [`1ed5716`](https://github.com/mastra-ai/mastra/commit/1ed5716830867b3774c4a1b43cc0d82935f32b96), [`4186bdd`](https://github.com/mastra-ai/mastra/commit/4186bdd00731305726fa06adba0b076a1d50b49f), [`7aaf973`](https://github.com/mastra-ai/mastra/commit/7aaf973f83fbbe9521f1f9e7a4fd99b8de464617)]:
|
|
24
|
+
- @mastra/core@1.0.0-beta.22
|
|
25
|
+
- @mastra/observability@1.0.0-beta.11
|
|
26
|
+
|
|
27
|
+
## 1.0.0-beta.11
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- feat(observability): add zero-config environment variable support for all exporters ([#11686](https://github.com/mastra-ai/mastra/pull/11686))
|
|
32
|
+
|
|
33
|
+
All observability exporters now support zero-config setup via environment variables. Set the appropriate environment variables and instantiate exporters with no configuration:
|
|
34
|
+
- **Langfuse**: `LANGFUSE_PUBLIC_KEY`, `LANGFUSE_SECRET_KEY`, `LANGFUSE_BASE_URL`
|
|
35
|
+
- **Braintrust**: `BRAINTRUST_API_KEY`, `BRAINTRUST_ENDPOINT`
|
|
36
|
+
- **PostHog**: `POSTHOG_API_KEY`, `POSTHOG_HOST`
|
|
37
|
+
- **Arize/Phoenix**: `ARIZE_SPACE_ID`, `ARIZE_API_KEY`, `ARIZE_PROJECT_NAME`, `PHOENIX_ENDPOINT`, `PHOENIX_API_KEY`, `PHOENIX_PROJECT_NAME`
|
|
38
|
+
- **OTEL Providers**:
|
|
39
|
+
- Dash0: `DASH0_API_KEY`, `DASH0_ENDPOINT`, `DASH0_DATASET`
|
|
40
|
+
- SigNoz: `SIGNOZ_API_KEY`, `SIGNOZ_REGION`, `SIGNOZ_ENDPOINT`
|
|
41
|
+
- New Relic: `NEW_RELIC_LICENSE_KEY`, `NEW_RELIC_ENDPOINT`
|
|
42
|
+
- Traceloop: `TRACELOOP_API_KEY`, `TRACELOOP_DESTINATION_ID`, `TRACELOOP_ENDPOINT`
|
|
43
|
+
- Laminar: `LMNR_PROJECT_API_KEY`, `LAMINAR_ENDPOINT`
|
|
44
|
+
|
|
45
|
+
Example usage:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Zero-config - reads from environment variables
|
|
49
|
+
new LangfuseExporter();
|
|
50
|
+
new BraintrustExporter();
|
|
51
|
+
new PosthogExporter();
|
|
52
|
+
new ArizeExporter();
|
|
53
|
+
new OtelExporter({ provider: { signoz: {} } });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Explicit configuration still works and takes precedence over environment variables.
|
|
57
|
+
|
|
58
|
+
### Patch Changes
|
|
59
|
+
|
|
60
|
+
- Updated dependencies [[`08766f1`](https://github.com/mastra-ai/mastra/commit/08766f15e13ac0692fde2a8bd366c2e16e4321df), [`ae8baf7`](https://github.com/mastra-ai/mastra/commit/ae8baf7d8adcb0ff9dac11880400452bc49b33ff), [`cfabdd4`](https://github.com/mastra-ai/mastra/commit/cfabdd4aae7a726b706942d6836eeca110fb6267), [`a0e437f`](https://github.com/mastra-ai/mastra/commit/a0e437fac561b28ee719e0302d72b2f9b4c138f0), [`bec5efd`](https://github.com/mastra-ai/mastra/commit/bec5efde96653ccae6604e68c696d1bc6c1a0bf5), [`9eedf7d`](https://github.com/mastra-ai/mastra/commit/9eedf7de1d6e0022a2f4e5e9e6fe1ec468f9b43c)]:
|
|
61
|
+
- @mastra/core@1.0.0-beta.21
|
|
62
|
+
|
|
3
63
|
## 1.0.0-beta.10
|
|
4
64
|
|
|
5
65
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -10,19 +10,50 @@ npm install @mastra/posthog
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
+
### Zero-Config Setup
|
|
14
|
+
|
|
15
|
+
The exporter automatically reads credentials from environment variables:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Required
|
|
19
|
+
POSTHOG_API_KEY=phc_...
|
|
20
|
+
|
|
21
|
+
# Optional
|
|
22
|
+
POSTHOG_HOST=https://us.i.posthog.com # or eu.i.posthog.com
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { PosthogExporter } from '@mastra/posthog';
|
|
27
|
+
|
|
28
|
+
const mastra = new Mastra({
|
|
29
|
+
...,
|
|
30
|
+
observability: {
|
|
31
|
+
configs: {
|
|
32
|
+
posthog: {
|
|
33
|
+
serviceName: 'my-service',
|
|
34
|
+
exporters: [new PosthogExporter()],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Explicit Configuration
|
|
42
|
+
|
|
43
|
+
You can also pass credentials directly:
|
|
44
|
+
|
|
13
45
|
```typescript
|
|
14
46
|
import { PosthogExporter } from '@mastra/posthog';
|
|
15
47
|
|
|
16
|
-
// Use with Mastra
|
|
17
48
|
const mastra = new Mastra({
|
|
18
49
|
...,
|
|
19
50
|
observability: {
|
|
20
51
|
configs: {
|
|
21
52
|
posthog: {
|
|
22
|
-
serviceName: 'service',
|
|
53
|
+
serviceName: 'my-service',
|
|
23
54
|
exporters: [
|
|
24
55
|
new PosthogExporter({
|
|
25
|
-
apiKey:
|
|
56
|
+
apiKey: 'phc_...',
|
|
26
57
|
host: 'https://us.i.posthog.com', // optional, defaults to US region
|
|
27
58
|
}),
|
|
28
59
|
],
|
package/dist/index.cjs
CHANGED
|
@@ -15,26 +15,25 @@ function formatUsageMetrics(usage) {
|
|
|
15
15
|
props.$ai_cache_creation_input_tokens = usage.inputDetails.cacheWrite;
|
|
16
16
|
return props;
|
|
17
17
|
}
|
|
18
|
-
var
|
|
18
|
+
var DISTINCT_ID = "distinctId";
|
|
19
|
+
var PosthogExporter = class _PosthogExporter extends observability.TrackingExporter {
|
|
19
20
|
name = "posthog";
|
|
20
|
-
client;
|
|
21
|
-
config;
|
|
22
|
-
traceMap = /* @__PURE__ */ new Map();
|
|
21
|
+
#client;
|
|
23
22
|
static SERVERLESS_FLUSH_AT = 10;
|
|
24
23
|
static SERVERLESS_FLUSH_INTERVAL = 2e3;
|
|
25
24
|
static DEFAULT_FLUSH_AT = 20;
|
|
26
25
|
static DEFAULT_FLUSH_INTERVAL = 1e4;
|
|
27
|
-
constructor(config) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if (!
|
|
31
|
-
this.setDisabled("Missing required API key");
|
|
32
|
-
this.client = null;
|
|
26
|
+
constructor(config = {}) {
|
|
27
|
+
const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;
|
|
28
|
+
super({ ...config, apiKey });
|
|
29
|
+
if (!apiKey) {
|
|
30
|
+
this.setDisabled("Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.");
|
|
33
31
|
return;
|
|
34
32
|
}
|
|
35
|
-
const clientConfig = this.buildClientConfig(config);
|
|
36
|
-
this
|
|
37
|
-
|
|
33
|
+
const clientConfig = this.buildClientConfig(this.config);
|
|
34
|
+
this.#client = new posthogNode.PostHog(apiKey, clientConfig);
|
|
35
|
+
const message = config.serverless ?? false ? "PostHog exporter initialized in serverless mode" : "PostHog exporter initialized";
|
|
36
|
+
this.logger.debug(message, config);
|
|
38
37
|
}
|
|
39
38
|
buildClientConfig(config) {
|
|
40
39
|
const isServerless = config.serverless ?? false;
|
|
@@ -42,7 +41,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
42
41
|
const flushInterval = config.flushInterval ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_INTERVAL : _PosthogExporter.DEFAULT_FLUSH_INTERVAL);
|
|
43
42
|
const host = config.host || process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
44
43
|
if (!config.host && !process.env.POSTHOG_HOST) {
|
|
45
|
-
this.logger.
|
|
44
|
+
this.logger.info(
|
|
46
45
|
'No PostHog host specified, using US default (https://us.i.posthog.com). For EU region, set `host: "https://eu.i.posthog.com"` in config or POSTHOG_HOST env var. For self-hosted, provide your instance URL.'
|
|
47
46
|
);
|
|
48
47
|
}
|
|
@@ -53,85 +52,59 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
53
52
|
privacyMode: config.enablePrivacyMode
|
|
54
53
|
};
|
|
55
54
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
skipBuildRootTask = true;
|
|
56
|
+
async _buildRoot(_args) {
|
|
57
|
+
throw new Error("Method not implemented.");
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
switch (event.type) {
|
|
72
|
-
case "span_started":
|
|
73
|
-
await this.handleSpanStarted(event.exportedSpan);
|
|
74
|
-
break;
|
|
75
|
-
case "span_updated":
|
|
76
|
-
break;
|
|
77
|
-
case "span_ended":
|
|
78
|
-
await this.handleSpanEnded(event.exportedSpan);
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
} catch (error) {
|
|
82
|
-
this.logger.error("PostHog exporter error", { error, event });
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
async handleSpanStarted(span) {
|
|
86
|
-
let traceData = this.traceMap.get(span.traceId);
|
|
87
|
-
if (!traceData) {
|
|
88
|
-
traceData = {
|
|
89
|
-
spans: /* @__PURE__ */ new Map(),
|
|
90
|
-
distinctId: void 0
|
|
91
|
-
};
|
|
92
|
-
this.traceMap.set(span.traceId, traceData);
|
|
93
|
-
}
|
|
94
|
-
traceData.spans.set(span.id, {
|
|
95
|
-
startTime: this.toDate(span.startTime),
|
|
96
|
-
type: span.type,
|
|
97
|
-
isRootSpan: span.isRootSpan
|
|
59
|
+
skipCachingEventSpans = true;
|
|
60
|
+
async _buildEvent(args) {
|
|
61
|
+
const { span, traceData } = args;
|
|
62
|
+
const eventName = this.mapToPostHogEvent(span.type);
|
|
63
|
+
const distinctId = this.getDistinctId(span, traceData);
|
|
64
|
+
const properties = this.buildEventProperties(span, 0);
|
|
65
|
+
this.#client?.capture({
|
|
66
|
+
distinctId,
|
|
67
|
+
event: eventName,
|
|
68
|
+
properties,
|
|
69
|
+
timestamp: span.endTime ? new Date(span.endTime) : /* @__PURE__ */ new Date()
|
|
98
70
|
});
|
|
99
|
-
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
async _buildSpan(args) {
|
|
74
|
+
const { span, traceData } = args;
|
|
75
|
+
if (!traceData.hasExtraValue(DISTINCT_ID)) {
|
|
100
76
|
const userId = span.metadata?.userId;
|
|
101
77
|
if (userId) {
|
|
102
|
-
traceData.
|
|
78
|
+
traceData.setExtraValue(DISTINCT_ID, String(userId));
|
|
103
79
|
}
|
|
104
80
|
}
|
|
81
|
+
return span;
|
|
105
82
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
83
|
+
skipSpanUpdateEvents = true;
|
|
84
|
+
_updateSpan(_args) {
|
|
85
|
+
throw new Error("Method not implemented.");
|
|
86
|
+
}
|
|
87
|
+
async _finishSpan(args) {
|
|
88
|
+
const { span, traceData } = args;
|
|
89
|
+
const cachedSpan = traceData.getSpan({ spanId: span.id });
|
|
90
|
+
const mergedSpan = !span.input && cachedSpan?.input ? { ...span, input: cachedSpan.input } : span;
|
|
91
|
+
const eventMessage = this.buildEventMessage({ span: mergedSpan, traceData });
|
|
92
|
+
this.#client?.capture(eventMessage);
|
|
93
|
+
}
|
|
94
|
+
async _abortSpan(args) {
|
|
95
|
+
const { span, reason, traceData } = args;
|
|
96
|
+
span.errorInfo = reason;
|
|
97
|
+
const eventMessage = this.buildEventMessage({ span, traceData });
|
|
98
|
+
this.#client?.capture(eventMessage);
|
|
99
|
+
}
|
|
100
|
+
buildEventMessage(args) {
|
|
101
|
+
const { span, traceData } = args;
|
|
116
102
|
const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();
|
|
117
|
-
const latency = (endTime - startTime) / 1e3;
|
|
118
103
|
const distinctId = this.getDistinctId(span, traceData);
|
|
119
104
|
if (span.isRootSpan) {
|
|
120
|
-
this.
|
|
105
|
+
return this.buildRootEventMessage({ span, distinctId, endTime });
|
|
121
106
|
} else {
|
|
122
|
-
|
|
123
|
-
const parentIsRootSpan = this.isParentRootSpan(span, traceData);
|
|
124
|
-
const properties = this.buildEventProperties(span, latency, parentIsRootSpan);
|
|
125
|
-
this.client.capture({
|
|
126
|
-
distinctId,
|
|
127
|
-
event: eventName,
|
|
128
|
-
properties,
|
|
129
|
-
timestamp: new Date(endTime)
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
traceData.spans.delete(span.id);
|
|
133
|
-
if (traceData.spans.size === 0) {
|
|
134
|
-
this.traceMap.delete(span.traceId);
|
|
107
|
+
return this.buildChildEventMessage({ span, distinctId, endTime, traceData });
|
|
135
108
|
}
|
|
136
109
|
}
|
|
137
110
|
/**
|
|
@@ -139,7 +112,8 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
139
112
|
* This gives us control over trace-level metadata like name and tags,
|
|
140
113
|
* rather than relying on PostHog's pseudo-trace auto-creation.
|
|
141
114
|
*/
|
|
142
|
-
|
|
115
|
+
buildRootEventMessage(args) {
|
|
116
|
+
const { span, distinctId, endTime } = args;
|
|
143
117
|
const traceProperties = {
|
|
144
118
|
$ai_trace_id: span.traceId,
|
|
145
119
|
$ai_span_name: span.name,
|
|
@@ -168,32 +142,26 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
168
142
|
}
|
|
169
143
|
const { userId, sessionId, ...customMetadata } = span.metadata ?? {};
|
|
170
144
|
Object.assign(traceProperties, customMetadata);
|
|
171
|
-
|
|
145
|
+
return {
|
|
172
146
|
distinctId,
|
|
173
147
|
event: "$ai_trace",
|
|
174
148
|
properties: traceProperties,
|
|
175
149
|
timestamp: new Date(endTime)
|
|
176
|
-
}
|
|
150
|
+
};
|
|
177
151
|
}
|
|
178
|
-
|
|
152
|
+
buildChildEventMessage(args) {
|
|
153
|
+
const { span, distinctId, endTime, traceData } = args;
|
|
179
154
|
const eventName = this.mapToPostHogEvent(span.type);
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
this.
|
|
155
|
+
const startTime = span.startTime.getTime();
|
|
156
|
+
const latency = (endTime - startTime) / 1e3;
|
|
157
|
+
const parentIsRootSpan = this.isParentRootSpan(span, traceData);
|
|
158
|
+
const properties = this.buildEventProperties(span, latency, parentIsRootSpan);
|
|
159
|
+
return {
|
|
184
160
|
distinctId,
|
|
185
161
|
event: eventName,
|
|
186
162
|
properties,
|
|
187
|
-
timestamp:
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
async shutdown() {
|
|
191
|
-
if (this.client) {
|
|
192
|
-
await this.client.shutdown();
|
|
193
|
-
}
|
|
194
|
-
this.traceMap.clear();
|
|
195
|
-
await super.shutdown();
|
|
196
|
-
this.logger.info("PostHog exporter shutdown complete");
|
|
163
|
+
timestamp: new Date(endTime)
|
|
164
|
+
};
|
|
197
165
|
}
|
|
198
166
|
toDate(timestamp) {
|
|
199
167
|
return timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
@@ -208,8 +176,8 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
208
176
|
if (span.metadata?.userId) {
|
|
209
177
|
return String(span.metadata.userId);
|
|
210
178
|
}
|
|
211
|
-
if (traceData?.
|
|
212
|
-
return traceData.
|
|
179
|
+
if (traceData?.hasExtraValue(DISTINCT_ID)) {
|
|
180
|
+
return String(traceData.getExtraValue(DISTINCT_ID));
|
|
213
181
|
}
|
|
214
182
|
if (this.config.defaultDistinctId) {
|
|
215
183
|
return this.config.defaultDistinctId;
|
|
@@ -225,7 +193,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
225
193
|
if (!span.parentSpanId) {
|
|
226
194
|
return false;
|
|
227
195
|
}
|
|
228
|
-
const parentCache = traceData.
|
|
196
|
+
const parentCache = traceData.getSpan({ spanId: span.parentSpanId });
|
|
229
197
|
if (parentCache) {
|
|
230
198
|
return parentCache.isRootSpan;
|
|
231
199
|
}
|
|
@@ -257,18 +225,18 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
257
225
|
return { ...baseProperties, ...this.buildSpanProperties(span) };
|
|
258
226
|
}
|
|
259
227
|
}
|
|
260
|
-
extractErrorProperties(
|
|
261
|
-
if (!
|
|
228
|
+
extractErrorProperties(errorInfo) {
|
|
229
|
+
if (!errorInfo) {
|
|
262
230
|
return {};
|
|
263
231
|
}
|
|
264
232
|
const props = {
|
|
265
|
-
error_message:
|
|
233
|
+
error_message: errorInfo.message
|
|
266
234
|
};
|
|
267
|
-
if (
|
|
268
|
-
props.error_id =
|
|
235
|
+
if (errorInfo.id) {
|
|
236
|
+
props.error_id = errorInfo.id;
|
|
269
237
|
}
|
|
270
|
-
if (
|
|
271
|
-
props.error_category =
|
|
238
|
+
if (errorInfo.category) {
|
|
239
|
+
props.error_category = errorInfo.category;
|
|
272
240
|
}
|
|
273
241
|
return props;
|
|
274
242
|
}
|
|
@@ -289,7 +257,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
289
257
|
if (attrs.parameters.maxOutputTokens !== void 0) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;
|
|
290
258
|
}
|
|
291
259
|
if (attrs.streaming !== void 0) props.$ai_stream = attrs.streaming;
|
|
292
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
260
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
293
261
|
}
|
|
294
262
|
buildSpanProperties(span) {
|
|
295
263
|
const props = {};
|
|
@@ -303,7 +271,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
303
271
|
if (span.attributes) {
|
|
304
272
|
Object.assign(props, span.attributes);
|
|
305
273
|
}
|
|
306
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
274
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
307
275
|
}
|
|
308
276
|
formatMessages(data, defaultRole = "user") {
|
|
309
277
|
if (this.isMessageArray(data)) {
|
|
@@ -342,6 +310,11 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
342
310
|
return String(data);
|
|
343
311
|
}
|
|
344
312
|
}
|
|
313
|
+
async _postShutdown() {
|
|
314
|
+
if (this.#client) {
|
|
315
|
+
await this.#client.shutdown();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
345
318
|
};
|
|
346
319
|
|
|
347
320
|
exports.PosthogExporter = PosthogExporter;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tracing.ts"],"names":["BaseExporter","PostHog","SpanType"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { TracingEvent, AnyExportedSpan, ModelGenerationAttributes, UsageStats } from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { BaseExporter } from '@mastra/observability';\nimport { PostHog } from 'posthog-node';\n\n/**\n * Token usage format compatible with PostHog.\n * @see https://posthog.com/docs/llm-analytics/generations#event-properties\n */\nexport interface PostHogUsageMetrics {\n $ai_input_tokens?: number;\n $ai_output_tokens?: number;\n $ai_cache_read_input_tokens?: number;\n $ai_cache_creation_input_tokens?: number;\n}\n\n/**\n * Formats UsageStats to PostHog's expected property format.\n *\n * @param usage - The UsageStats from span attributes\n * @returns PostHog-formatted usage properties\n */\nexport function formatUsageMetrics(usage?: UsageStats): PostHogUsageMetrics {\n if (!usage) return {};\n\n const props: PostHogUsageMetrics = {};\n\n if (usage.inputTokens !== undefined) props.$ai_input_tokens = usage.inputTokens;\n if (usage.outputTokens !== undefined) props.$ai_output_tokens = usage.outputTokens;\n\n // Cache read tokens from inputDetails\n if (usage.inputDetails?.cacheRead !== undefined) props.$ai_cache_read_input_tokens = usage.inputDetails.cacheRead;\n\n // Cache write tokens from inputDetails\n if (usage.inputDetails?.cacheWrite !== undefined)\n props.$ai_cache_creation_input_tokens = usage.inputDetails.cacheWrite;\n\n return props;\n}\n\ninterface PostHogMessage {\n role: 'user' | 'assistant' | 'system' | 'tool';\n content: PostHogContent[];\n}\n\ninterface PostHogContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface MastraMessage {\n role: string;\n content: string | MastraContent[];\n}\n\ninterface MastraContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ntype SpanData = string | MastraMessage[] | Record<string, unknown> | unknown;\n\nexport interface PosthogExporterConfig extends BaseExporterConfig {\n apiKey: string;\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n serverless?: boolean;\n defaultDistinctId?: string;\n enablePrivacyMode?: boolean;\n}\n\ntype SpanCache = {\n startTime: Date;\n type: SpanType;\n isRootSpan: boolean;\n};\n\ntype TraceMetadata = {\n spans: Map<string, SpanCache>;\n distinctId?: string;\n};\n\nexport class PosthogExporter extends BaseExporter {\n name = 'posthog';\n private client: PostHog;\n private config: PosthogExporterConfig;\n private traceMap = new Map<string, TraceMetadata>();\n\n private static readonly SERVERLESS_FLUSH_AT = 10;\n private static readonly SERVERLESS_FLUSH_INTERVAL = 2000;\n private static readonly DEFAULT_FLUSH_AT = 20;\n private static readonly DEFAULT_FLUSH_INTERVAL = 10000;\n\n constructor(config: PosthogExporterConfig) {\n super(config);\n this.config = config;\n\n if (!config.apiKey) {\n this.setDisabled('Missing required API key');\n this.client = null as any;\n return;\n }\n\n const clientConfig = this.buildClientConfig(config);\n this.client = new PostHog(config.apiKey, clientConfig);\n this.logInitialization(config.serverless ?? false, clientConfig);\n }\n\n private buildClientConfig(config: PosthogExporterConfig) {\n const isServerless = config.serverless ?? false;\n const flushAt =\n config.flushAt ?? (isServerless ? PosthogExporter.SERVERLESS_FLUSH_AT : PosthogExporter.DEFAULT_FLUSH_AT);\n const flushInterval =\n config.flushInterval ??\n (isServerless ? PosthogExporter.SERVERLESS_FLUSH_INTERVAL : PosthogExporter.DEFAULT_FLUSH_INTERVAL);\n\n const host = config.host || process.env.POSTHOG_HOST || 'https://us.i.posthog.com';\n\n if (!config.host && !process.env.POSTHOG_HOST) {\n this.logger.warn(\n 'No PostHog host specified, using US default (https://us.i.posthog.com). ' +\n 'For EU region, set `host: \"https://eu.i.posthog.com\"` in config or POSTHOG_HOST env var. ' +\n 'For self-hosted, provide your instance URL.',\n );\n }\n\n return {\n host,\n flushAt,\n flushInterval,\n privacyMode: config.enablePrivacyMode,\n };\n }\n\n private logInitialization(\n isServerless: boolean,\n config: { host: string; flushAt: number; flushInterval: number; privacyMode?: boolean },\n ): void {\n const message = isServerless ? 'PostHog exporter initialized in serverless mode' : 'PostHog exporter initialized';\n this.logger.debug(message, config);\n }\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.client) {\n return;\n }\n\n try {\n if (event.exportedSpan.isEvent) {\n if (event.type === 'span_started') {\n await this.captureEventSpan(event.exportedSpan);\n }\n return;\n }\n\n switch (event.type) {\n case 'span_started':\n await this.handleSpanStarted(event.exportedSpan);\n break;\n case 'span_updated':\n break;\n case 'span_ended':\n await this.handleSpanEnded(event.exportedSpan);\n break;\n }\n } catch (error) {\n this.logger.error('PostHog exporter error', { error, event });\n }\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n let traceData = this.traceMap.get(span.traceId);\n\n if (!traceData) {\n traceData = {\n spans: new Map(),\n distinctId: undefined,\n };\n this.traceMap.set(span.traceId, traceData);\n }\n\n traceData.spans.set(span.id, {\n startTime: this.toDate(span.startTime),\n type: span.type,\n isRootSpan: span.isRootSpan,\n });\n\n if (!traceData.distinctId) {\n const userId = span.metadata?.userId;\n if (userId) {\n traceData.distinctId = String(userId);\n }\n }\n }\n\n private async handleSpanEnded(span: AnyExportedSpan): Promise<void> {\n const traceData = this.traceMap.get(span.traceId);\n\n if (!traceData) {\n return;\n }\n\n const cachedSpan = traceData.spans.get(span.id);\n if (!cachedSpan) {\n return;\n }\n\n const startTime = cachedSpan.startTime.getTime();\n const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();\n const latency = (endTime - startTime) / 1000;\n\n const distinctId = this.getDistinctId(span, traceData);\n\n // For root spans, only send $ai_trace (not $ai_span) to avoid duplicate entries\n // For non-root spans, send $ai_span or $ai_generation as normal\n if (span.isRootSpan) {\n this.captureTraceEvent(span, distinctId, endTime);\n } else {\n const eventName = this.mapToPostHogEvent(span.type);\n\n // Check if parent is the root span - if so, use traceId as parent_id\n // since we don't create an $ai_span for root spans\n const parentIsRootSpan = this.isParentRootSpan(span, traceData);\n const properties = this.buildEventProperties(span, latency, parentIsRootSpan);\n\n this.client.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: new Date(endTime),\n });\n }\n\n traceData.spans.delete(span.id);\n if (traceData.spans.size === 0) {\n this.traceMap.delete(span.traceId);\n }\n }\n\n /**\n * Capture an explicit $ai_trace event for root spans.\n * This gives us control over trace-level metadata like name and tags,\n * rather than relying on PostHog's pseudo-trace auto-creation.\n */\n private captureTraceEvent(span: AnyExportedSpan, distinctId: string, endTime: number): void {\n // Note: We don't set $ai_latency on $ai_trace events because PostHog\n // aggregates latency from child events. Setting it here causes double-counting.\n const traceProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_span_name: span.name,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.metadata?.sessionId) {\n traceProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n if (span.input) {\n traceProperties.$ai_input_state = span.input;\n }\n\n if (span.output) {\n traceProperties.$ai_output_state = span.output;\n }\n\n if (span.errorInfo) {\n traceProperties.$ai_error = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id && { id: span.errorInfo.id }),\n ...(span.errorInfo.category && { category: span.errorInfo.category }),\n };\n }\n\n // Add tags as custom properties (PostHog doesn't have native tag support on traces)\n if (span.tags?.length) {\n for (const tag of span.tags) {\n traceProperties[tag] = true;\n }\n }\n\n // Add custom metadata (excluding userId and sessionId which are handled separately)\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n Object.assign(traceProperties, customMetadata);\n\n this.client.capture({\n distinctId,\n event: '$ai_trace',\n properties: traceProperties,\n timestamp: new Date(endTime),\n });\n }\n\n private async captureEventSpan(span: AnyExportedSpan): Promise<void> {\n const eventName = this.mapToPostHogEvent(span.type);\n const traceData = this.traceMap.get(span.traceId);\n\n const distinctId = this.getDistinctId(span, traceData);\n const properties = this.buildEventProperties(span, 0);\n\n this.client.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: span.endTime ? new Date(span.endTime) : new Date(),\n });\n }\n\n async shutdown(): Promise<void> {\n if (this.client) {\n await this.client.shutdown();\n }\n this.traceMap.clear();\n await super.shutdown();\n this.logger.info('PostHog exporter shutdown complete');\n }\n\n private toDate(timestamp: Date | number): Date {\n return timestamp instanceof Date ? timestamp : new Date(timestamp);\n }\n\n private mapToPostHogEvent(spanType: SpanType): string {\n if (spanType == SpanType.MODEL_GENERATION) {\n return '$ai_generation';\n }\n return '$ai_span';\n }\n\n private getDistinctId(span: AnyExportedSpan, traceData?: TraceMetadata): string {\n if (span.metadata?.userId) {\n return String(span.metadata.userId);\n }\n\n if (traceData?.distinctId) {\n return traceData.distinctId;\n }\n\n if (this.config.defaultDistinctId) {\n return this.config.defaultDistinctId;\n }\n\n return 'anonymous';\n }\n\n /**\n * Check if the parent of this span is the root span.\n * We need this because we don't create $ai_span for root spans,\n * so children of root spans should use $ai_trace_id as their $ai_parent_id.\n */\n private isParentRootSpan(span: AnyExportedSpan, traceData: TraceMetadata): boolean {\n if (!span.parentSpanId) {\n return false;\n }\n\n // Look up the parent span in our cache to check if it's a root span\n const parentCache = traceData.spans.get(span.parentSpanId);\n if (parentCache) {\n return parentCache.isRootSpan;\n }\n\n // Parent not found in cache - shouldn't happen normally, but default to false\n return false;\n }\n\n private buildEventProperties(\n span: AnyExportedSpan,\n latency: number,\n parentIsRootSpan: boolean = false,\n ): Record<string, any> {\n const baseProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_latency: latency,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.parentSpanId) {\n // If parent is the root span, use trace_id as parent_id since we don't\n // create an $ai_span for root spans (only $ai_trace)\n baseProperties.$ai_parent_id = parentIsRootSpan ? span.traceId : span.parentSpanId;\n }\n\n if (span.metadata?.sessionId) {\n baseProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n // Include tags for root spans (tags are only set on root spans by design)\n // PostHog doesn't allow setting tags directly, so we iterate through each tag\n // and set it as a property with value true\n if (span.isRootSpan && span.tags?.length) {\n for (const tag of span.tags) {\n baseProperties[tag] = true;\n }\n }\n\n if (span.type === SpanType.MODEL_GENERATION) {\n baseProperties.$ai_generation_id = span.id;\n return { ...baseProperties, ...this.buildGenerationProperties(span) };\n } else {\n baseProperties.$ai_span_id = span.id;\n baseProperties.$ai_span_name = span.name;\n return { ...baseProperties, ...this.buildSpanProperties(span) };\n }\n }\n\n private extractErrorProperties(span: AnyExportedSpan): Record<string, any> {\n if (!span.errorInfo) {\n return {};\n }\n\n const props: Record<string, string> = {\n error_message: span.errorInfo.message,\n };\n\n if (span.errorInfo.id) {\n props.error_id = span.errorInfo.id;\n }\n\n if (span.errorInfo.category) {\n props.error_category = span.errorInfo.category;\n }\n\n return props;\n }\n\n private extractCustomMetadata(span: AnyExportedSpan): Record<string, any> {\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n return customMetadata;\n }\n\n private buildGenerationProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n const attrs = (span.attributes ?? {}) as ModelGenerationAttributes;\n\n props.$ai_model = attrs.model || 'unknown-model';\n props.$ai_provider = attrs.provider || 'unknown-provider';\n\n if (span.input) props.$ai_input = this.formatMessages(span.input, 'user');\n if (span.output) props.$ai_output_choices = this.formatMessages(span.output, 'assistant');\n\n // Extract usage properties using the shared utility\n Object.assign(props, formatUsageMetrics(attrs.usage));\n\n if (attrs.parameters) {\n if (attrs.parameters.temperature !== undefined) props.$ai_temperature = attrs.parameters.temperature;\n if (attrs.parameters.maxOutputTokens !== undefined) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;\n }\n if (attrs.streaming !== undefined) props.$ai_stream = attrs.streaming;\n\n return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };\n }\n\n private buildSpanProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n\n if (span.input) props.$ai_input_state = span.input;\n if (span.output) props.$ai_output_state = span.output;\n\n if (span.type === SpanType.MODEL_CHUNK) {\n const attrs = span.attributes as any;\n if (attrs?.chunkType) props.chunk_type = attrs.chunkType;\n if (attrs?.sequenceNumber !== undefined) props.chunk_sequence_number = attrs.sequenceNumber;\n }\n\n if (span.attributes) {\n Object.assign(props, span.attributes);\n }\n\n return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };\n }\n\n private formatMessages(data: SpanData, defaultRole: 'user' | 'assistant' = 'user'): PostHogMessage[] {\n if (this.isMessageArray(data)) {\n return data.map(msg => this.normalizeMessage(msg));\n }\n\n if (typeof data === 'string') {\n return [{ role: defaultRole, content: [{ type: 'text', text: data }] }];\n }\n\n return [{ role: defaultRole, content: [{ type: 'text', text: this.safeStringify(data) }] }];\n }\n\n private isMessageArray(data: unknown): data is MastraMessage[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n return data.every(item => typeof item === 'object' && item !== null && 'role' in item && 'content' in item);\n }\n\n private normalizeMessage(msg: MastraMessage): PostHogMessage {\n if (typeof msg.content === 'string') {\n return {\n role: msg.role as PostHogMessage['role'],\n content: [{ type: 'text', text: msg.content }],\n };\n }\n\n return {\n role: msg.role as PostHogMessage['role'],\n content: msg.content as PostHogContent[],\n };\n }\n\n private safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/tracing.ts"],"names":["TrackingExporter","PostHog","SpanType"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AnyExportedSpan, ModelGenerationAttributes, SpanErrorInfo, UsageStats } from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport type { TraceData, TrackingExporterConfig } from '@mastra/observability';\nimport { TrackingExporter } from '@mastra/observability';\nimport { PostHog } from 'posthog-node';\nimport type { EventMessage } from 'posthog-node';\n\n/**\n * Token usage format compatible with PostHog.\n * @see https://posthog.com/docs/llm-analytics/generations#event-properties\n */\nexport interface PostHogUsageMetrics {\n $ai_input_tokens?: number;\n $ai_output_tokens?: number;\n $ai_cache_read_input_tokens?: number;\n $ai_cache_creation_input_tokens?: number;\n}\n\n/**\n * Formats UsageStats to PostHog's expected property format.\n *\n * @param usage - The UsageStats from span attributes\n * @returns PostHog-formatted usage properties\n */\nexport function formatUsageMetrics(usage?: UsageStats): PostHogUsageMetrics {\n if (!usage) return {};\n\n const props: PostHogUsageMetrics = {};\n\n if (usage.inputTokens !== undefined) props.$ai_input_tokens = usage.inputTokens;\n if (usage.outputTokens !== undefined) props.$ai_output_tokens = usage.outputTokens;\n\n // Cache read tokens from inputDetails\n if (usage.inputDetails?.cacheRead !== undefined) props.$ai_cache_read_input_tokens = usage.inputDetails.cacheRead;\n\n // Cache write tokens from inputDetails\n if (usage.inputDetails?.cacheWrite !== undefined)\n props.$ai_cache_creation_input_tokens = usage.inputDetails.cacheWrite;\n\n return props;\n}\n\ninterface PostHogMessage {\n role: 'user' | 'assistant' | 'system' | 'tool';\n content: PostHogContent[];\n}\n\ninterface PostHogContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface MastraMessage {\n role: string;\n content: string | MastraContent[];\n}\n\ninterface MastraContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ntype SpanData = string | MastraMessage[] | Record<string, unknown> | unknown;\n\nconst DISTINCT_ID = 'distinctId';\n\nexport interface PosthogExporterConfig extends TrackingExporterConfig {\n /** PostHog API key. Defaults to POSTHOG_API_KEY environment variable. */\n apiKey?: string;\n /** PostHog host URL. Defaults to POSTHOG_HOST environment variable or US region. */\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n serverless?: boolean;\n defaultDistinctId?: string;\n enablePrivacyMode?: boolean;\n}\n\ntype PosthogRoot = unknown;\ntype PosthogSpan = AnyExportedSpan;\n// used as a placeholder for event data since we don't need to cache\n// event data for Posthog\ntype PosthogEvent = boolean;\ntype PosthogMetadata = unknown;\ntype PosthogTraceData = TraceData<PosthogRoot, PosthogSpan, PosthogEvent, PosthogMetadata>;\n\nexport class PosthogExporter extends TrackingExporter<\n PosthogRoot,\n PosthogSpan,\n PosthogEvent,\n PosthogMetadata,\n PosthogExporterConfig\n> {\n name = 'posthog';\n #client: PostHog | undefined;\n\n private static readonly SERVERLESS_FLUSH_AT = 10;\n private static readonly SERVERLESS_FLUSH_INTERVAL = 2000;\n private static readonly DEFAULT_FLUSH_AT = 20;\n private static readonly DEFAULT_FLUSH_INTERVAL = 10000;\n\n constructor(config: PosthogExporterConfig = {}) {\n // Resolve env vars BEFORE calling super (config is readonly in base class)\n const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;\n\n super({ ...config, apiKey });\n\n if (!apiKey) {\n this.setDisabled('Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.');\n return;\n }\n\n const clientConfig = this.buildClientConfig(this.config);\n this.#client = new PostHog(apiKey, clientConfig);\n const message =\n (config.serverless ?? false) ? 'PostHog exporter initialized in serverless mode' : 'PostHog exporter initialized';\n this.logger.debug(message, config);\n }\n\n private buildClientConfig(config: PosthogExporterConfig) {\n const isServerless = config.serverless ?? false;\n const flushAt =\n config.flushAt ?? (isServerless ? PosthogExporter.SERVERLESS_FLUSH_AT : PosthogExporter.DEFAULT_FLUSH_AT);\n const flushInterval =\n config.flushInterval ??\n (isServerless ? PosthogExporter.SERVERLESS_FLUSH_INTERVAL : PosthogExporter.DEFAULT_FLUSH_INTERVAL);\n\n const host = config.host || process.env.POSTHOG_HOST || 'https://us.i.posthog.com';\n\n if (!config.host && !process.env.POSTHOG_HOST) {\n this.logger.info(\n 'No PostHog host specified, using US default (https://us.i.posthog.com). ' +\n 'For EU region, set `host: \"https://eu.i.posthog.com\"` in config or POSTHOG_HOST env var. ' +\n 'For self-hosted, provide your instance URL.',\n );\n }\n\n return {\n host,\n flushAt,\n flushInterval,\n privacyMode: config.enablePrivacyMode,\n };\n }\n\n protected override skipBuildRootTask = true;\n protected override async _buildRoot(_args: {\n span: AnyExportedSpan;\n traceData: PosthogTraceData;\n }): Promise<PosthogRoot | undefined> {\n throw new Error('Method not implemented.');\n }\n\n protected override skipCachingEventSpans = true;\n protected override async _buildEvent(args: {\n span: AnyExportedSpan;\n traceData: PosthogTraceData;\n }): Promise<PosthogEvent> {\n const { span, traceData } = args;\n\n const eventName = this.mapToPostHogEvent(span.type);\n const distinctId = this.getDistinctId(span, traceData);\n const properties = this.buildEventProperties(span, 0);\n\n this.#client?.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: span.endTime ? new Date(span.endTime) : new Date(),\n });\n\n return true;\n }\n\n protected override async _buildSpan(args: {\n span: AnyExportedSpan;\n traceData: PosthogTraceData;\n }): Promise<PosthogSpan | undefined> {\n const { span, traceData } = args;\n if (!traceData.hasExtraValue(DISTINCT_ID)) {\n const userId = span.metadata?.userId;\n if (userId) {\n traceData.setExtraValue(DISTINCT_ID, String(userId));\n }\n }\n\n return span;\n }\n\n protected override skipSpanUpdateEvents = true;\n protected override _updateSpan(_args: { span: AnyExportedSpan; traceData: PosthogTraceData }): Promise<void> {\n throw new Error('Method not implemented.');\n }\n\n protected override async _finishSpan(args: { span: AnyExportedSpan; traceData: PosthogTraceData }): Promise<void> {\n const { span, traceData } = args;\n\n // Merge input from cached span (SPAN_STARTED) if not present on end span\n // This handles the case where input is only sent at start\n const cachedSpan = traceData.getSpan({ spanId: span.id });\n const mergedSpan = !span.input && cachedSpan?.input ? { ...span, input: cachedSpan.input } : span;\n\n const eventMessage = this.buildEventMessage({ span: mergedSpan, traceData });\n this.#client?.capture(eventMessage);\n }\n\n protected override async _abortSpan(args: {\n span: PosthogSpan;\n reason: SpanErrorInfo;\n traceData: PosthogTraceData;\n }): Promise<void> {\n const { span, reason, traceData } = args;\n\n // update span with the abort reason\n span.errorInfo = reason;\n\n const eventMessage = this.buildEventMessage({ span, traceData });\n this.#client?.capture(eventMessage);\n }\n\n private buildEventMessage(args: { span: AnyExportedSpan; traceData: PosthogTraceData }): EventMessage {\n const { span, traceData } = args;\n\n const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();\n\n const distinctId = this.getDistinctId(span, traceData);\n\n if (span.isRootSpan) {\n return this.buildRootEventMessage({ span, distinctId, endTime });\n } else {\n return this.buildChildEventMessage({ span, distinctId, endTime, traceData });\n }\n }\n\n /**\n * Capture an explicit $ai_trace event for root spans.\n * This gives us control over trace-level metadata like name and tags,\n * rather than relying on PostHog's pseudo-trace auto-creation.\n */\n private buildRootEventMessage(args: { span: AnyExportedSpan; distinctId: string; endTime: number }): EventMessage {\n const { span, distinctId, endTime } = args;\n\n // Note: We don't set $ai_latency on $ai_trace events because PostHog\n // aggregates latency from child events. Setting it here causes double-counting.\n const traceProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_span_name: span.name,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.metadata?.sessionId) {\n traceProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n if (span.input) {\n traceProperties.$ai_input_state = span.input;\n }\n\n if (span.output) {\n traceProperties.$ai_output_state = span.output;\n }\n\n if (span.errorInfo) {\n traceProperties.$ai_error = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id && { id: span.errorInfo.id }),\n ...(span.errorInfo.category && { category: span.errorInfo.category }),\n };\n }\n\n // Add tags as custom properties (PostHog doesn't have native tag support on traces)\n if (span.tags?.length) {\n for (const tag of span.tags) {\n traceProperties[tag] = true;\n }\n }\n\n // Add custom metadata (excluding userId and sessionId which are handled separately)\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n Object.assign(traceProperties, customMetadata);\n\n return {\n distinctId,\n event: '$ai_trace',\n properties: traceProperties,\n timestamp: new Date(endTime),\n };\n }\n\n private buildChildEventMessage(args: {\n span: AnyExportedSpan;\n distinctId: string;\n endTime: number;\n traceData: PosthogTraceData;\n }): EventMessage {\n const { span, distinctId, endTime, traceData } = args;\n\n const eventName = this.mapToPostHogEvent(span.type);\n const startTime = span.startTime.getTime();\n const latency = (endTime - startTime) / 1000;\n\n // Check if parent is the root span - if so, use traceId as parent_id\n // since we don't create an $ai_span for root spans\n const parentIsRootSpan = this.isParentRootSpan(span, traceData);\n const properties = this.buildEventProperties(span, latency, parentIsRootSpan);\n\n return {\n distinctId,\n event: eventName,\n properties,\n timestamp: new Date(endTime),\n };\n }\n\n private toDate(timestamp: Date | number): Date {\n return timestamp instanceof Date ? timestamp : new Date(timestamp);\n }\n\n private mapToPostHogEvent(spanType: SpanType): string {\n if (spanType == SpanType.MODEL_GENERATION) {\n return '$ai_generation';\n }\n return '$ai_span';\n }\n\n private getDistinctId(span: AnyExportedSpan, traceData?: PosthogTraceData): string {\n if (span.metadata?.userId) {\n return String(span.metadata.userId);\n }\n\n if (traceData?.hasExtraValue(DISTINCT_ID)) {\n return String(traceData.getExtraValue(DISTINCT_ID));\n }\n\n if (this.config.defaultDistinctId) {\n return this.config.defaultDistinctId;\n }\n\n return 'anonymous';\n }\n\n /**\n * Check if the parent of this span is the root span.\n * We need this because we don't create $ai_span for root spans,\n * so children of root spans should use $ai_trace_id as their $ai_parent_id.\n */\n private isParentRootSpan(span: AnyExportedSpan, traceData: PosthogTraceData): boolean {\n if (!span.parentSpanId) {\n return false;\n }\n\n // Look up the parent span in our cache to check if it's a root span\n const parentCache = traceData.getSpan({ spanId: span.parentSpanId });\n if (parentCache) {\n return parentCache.isRootSpan;\n }\n\n // Parent not found in cache - shouldn't happen normally, but default to false\n return false;\n }\n\n private buildEventProperties(\n span: AnyExportedSpan,\n latency: number,\n parentIsRootSpan: boolean = false,\n ): Record<string, any> {\n const baseProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_latency: latency,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.parentSpanId) {\n // If parent is the root span, use trace_id as parent_id since we don't\n // create an $ai_span for root spans (only $ai_trace)\n baseProperties.$ai_parent_id = parentIsRootSpan ? span.traceId : span.parentSpanId;\n }\n\n if (span.metadata?.sessionId) {\n baseProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n // Include tags for root spans (tags are only set on root spans by design)\n // PostHog doesn't allow setting tags directly, so we iterate through each tag\n // and set it as a property with value true\n if (span.isRootSpan && span.tags?.length) {\n for (const tag of span.tags) {\n baseProperties[tag] = true;\n }\n }\n\n if (span.type === SpanType.MODEL_GENERATION) {\n baseProperties.$ai_generation_id = span.id;\n return { ...baseProperties, ...this.buildGenerationProperties(span) };\n } else {\n baseProperties.$ai_span_id = span.id;\n baseProperties.$ai_span_name = span.name;\n return { ...baseProperties, ...this.buildSpanProperties(span) };\n }\n }\n\n private extractErrorProperties(errorInfo?: SpanErrorInfo): Record<string, any> {\n if (!errorInfo) {\n return {};\n }\n\n const props: Record<string, string> = {\n error_message: errorInfo.message,\n };\n\n if (errorInfo.id) {\n props.error_id = errorInfo.id;\n }\n\n if (errorInfo.category) {\n props.error_category = errorInfo.category;\n }\n\n return props;\n }\n\n private extractCustomMetadata(span: AnyExportedSpan): Record<string, any> {\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n return customMetadata;\n }\n\n private buildGenerationProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n const attrs = (span.attributes ?? {}) as ModelGenerationAttributes;\n\n props.$ai_model = attrs.model || 'unknown-model';\n props.$ai_provider = attrs.provider || 'unknown-provider';\n\n if (span.input) props.$ai_input = this.formatMessages(span.input, 'user');\n if (span.output) props.$ai_output_choices = this.formatMessages(span.output, 'assistant');\n\n // Extract usage properties using the shared utility\n Object.assign(props, formatUsageMetrics(attrs.usage));\n\n if (attrs.parameters) {\n if (attrs.parameters.temperature !== undefined) props.$ai_temperature = attrs.parameters.temperature;\n if (attrs.parameters.maxOutputTokens !== undefined) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;\n }\n if (attrs.streaming !== undefined) props.$ai_stream = attrs.streaming;\n\n return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };\n }\n\n private buildSpanProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n\n if (span.input) props.$ai_input_state = span.input;\n if (span.output) props.$ai_output_state = span.output;\n\n if (span.type === SpanType.MODEL_CHUNK) {\n const attrs = span.attributes as any;\n if (attrs?.chunkType) props.chunk_type = attrs.chunkType;\n if (attrs?.sequenceNumber !== undefined) props.chunk_sequence_number = attrs.sequenceNumber;\n }\n\n if (span.attributes) {\n Object.assign(props, span.attributes);\n }\n\n return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };\n }\n\n private formatMessages(data: SpanData, defaultRole: 'user' | 'assistant' = 'user'): PostHogMessage[] {\n if (this.isMessageArray(data)) {\n return data.map(msg => this.normalizeMessage(msg));\n }\n\n if (typeof data === 'string') {\n return [{ role: defaultRole, content: [{ type: 'text', text: data }] }];\n }\n\n return [{ role: defaultRole, content: [{ type: 'text', text: this.safeStringify(data) }] }];\n }\n\n private isMessageArray(data: unknown): data is MastraMessage[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n return data.every(item => typeof item === 'object' && item !== null && 'role' in item && 'content' in item);\n }\n\n private normalizeMessage(msg: MastraMessage): PostHogMessage {\n if (typeof msg.content === 'string') {\n return {\n role: msg.role as PostHogMessage['role'],\n content: [{ type: 'text', text: msg.content }],\n };\n }\n\n return {\n role: msg.role as PostHogMessage['role'],\n content: msg.content as PostHogContent[],\n };\n }\n\n private safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n }\n\n override async _postShutdown(): Promise<void> {\n if (this.#client) {\n await this.#client.shutdown();\n }\n }\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SpanType } from '@mastra/core/observability';
|
|
2
|
-
import {
|
|
2
|
+
import { TrackingExporter } from '@mastra/observability';
|
|
3
3
|
import { PostHog } from 'posthog-node';
|
|
4
4
|
|
|
5
5
|
// src/tracing.ts
|
|
@@ -13,26 +13,25 @@ function formatUsageMetrics(usage) {
|
|
|
13
13
|
props.$ai_cache_creation_input_tokens = usage.inputDetails.cacheWrite;
|
|
14
14
|
return props;
|
|
15
15
|
}
|
|
16
|
-
var
|
|
16
|
+
var DISTINCT_ID = "distinctId";
|
|
17
|
+
var PosthogExporter = class _PosthogExporter extends TrackingExporter {
|
|
17
18
|
name = "posthog";
|
|
18
|
-
client;
|
|
19
|
-
config;
|
|
20
|
-
traceMap = /* @__PURE__ */ new Map();
|
|
19
|
+
#client;
|
|
21
20
|
static SERVERLESS_FLUSH_AT = 10;
|
|
22
21
|
static SERVERLESS_FLUSH_INTERVAL = 2e3;
|
|
23
22
|
static DEFAULT_FLUSH_AT = 20;
|
|
24
23
|
static DEFAULT_FLUSH_INTERVAL = 1e4;
|
|
25
|
-
constructor(config) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!
|
|
29
|
-
this.setDisabled("Missing required API key");
|
|
30
|
-
this.client = null;
|
|
24
|
+
constructor(config = {}) {
|
|
25
|
+
const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;
|
|
26
|
+
super({ ...config, apiKey });
|
|
27
|
+
if (!apiKey) {
|
|
28
|
+
this.setDisabled("Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.");
|
|
31
29
|
return;
|
|
32
30
|
}
|
|
33
|
-
const clientConfig = this.buildClientConfig(config);
|
|
34
|
-
this
|
|
35
|
-
|
|
31
|
+
const clientConfig = this.buildClientConfig(this.config);
|
|
32
|
+
this.#client = new PostHog(apiKey, clientConfig);
|
|
33
|
+
const message = config.serverless ?? false ? "PostHog exporter initialized in serverless mode" : "PostHog exporter initialized";
|
|
34
|
+
this.logger.debug(message, config);
|
|
36
35
|
}
|
|
37
36
|
buildClientConfig(config) {
|
|
38
37
|
const isServerless = config.serverless ?? false;
|
|
@@ -40,7 +39,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
40
39
|
const flushInterval = config.flushInterval ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_INTERVAL : _PosthogExporter.DEFAULT_FLUSH_INTERVAL);
|
|
41
40
|
const host = config.host || process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
42
41
|
if (!config.host && !process.env.POSTHOG_HOST) {
|
|
43
|
-
this.logger.
|
|
42
|
+
this.logger.info(
|
|
44
43
|
'No PostHog host specified, using US default (https://us.i.posthog.com). For EU region, set `host: "https://eu.i.posthog.com"` in config or POSTHOG_HOST env var. For self-hosted, provide your instance URL.'
|
|
45
44
|
);
|
|
46
45
|
}
|
|
@@ -51,85 +50,59 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
51
50
|
privacyMode: config.enablePrivacyMode
|
|
52
51
|
};
|
|
53
52
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
skipBuildRootTask = true;
|
|
54
|
+
async _buildRoot(_args) {
|
|
55
|
+
throw new Error("Method not implemented.");
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
switch (event.type) {
|
|
70
|
-
case "span_started":
|
|
71
|
-
await this.handleSpanStarted(event.exportedSpan);
|
|
72
|
-
break;
|
|
73
|
-
case "span_updated":
|
|
74
|
-
break;
|
|
75
|
-
case "span_ended":
|
|
76
|
-
await this.handleSpanEnded(event.exportedSpan);
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
} catch (error) {
|
|
80
|
-
this.logger.error("PostHog exporter error", { error, event });
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
async handleSpanStarted(span) {
|
|
84
|
-
let traceData = this.traceMap.get(span.traceId);
|
|
85
|
-
if (!traceData) {
|
|
86
|
-
traceData = {
|
|
87
|
-
spans: /* @__PURE__ */ new Map(),
|
|
88
|
-
distinctId: void 0
|
|
89
|
-
};
|
|
90
|
-
this.traceMap.set(span.traceId, traceData);
|
|
91
|
-
}
|
|
92
|
-
traceData.spans.set(span.id, {
|
|
93
|
-
startTime: this.toDate(span.startTime),
|
|
94
|
-
type: span.type,
|
|
95
|
-
isRootSpan: span.isRootSpan
|
|
57
|
+
skipCachingEventSpans = true;
|
|
58
|
+
async _buildEvent(args) {
|
|
59
|
+
const { span, traceData } = args;
|
|
60
|
+
const eventName = this.mapToPostHogEvent(span.type);
|
|
61
|
+
const distinctId = this.getDistinctId(span, traceData);
|
|
62
|
+
const properties = this.buildEventProperties(span, 0);
|
|
63
|
+
this.#client?.capture({
|
|
64
|
+
distinctId,
|
|
65
|
+
event: eventName,
|
|
66
|
+
properties,
|
|
67
|
+
timestamp: span.endTime ? new Date(span.endTime) : /* @__PURE__ */ new Date()
|
|
96
68
|
});
|
|
97
|
-
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
async _buildSpan(args) {
|
|
72
|
+
const { span, traceData } = args;
|
|
73
|
+
if (!traceData.hasExtraValue(DISTINCT_ID)) {
|
|
98
74
|
const userId = span.metadata?.userId;
|
|
99
75
|
if (userId) {
|
|
100
|
-
traceData.
|
|
76
|
+
traceData.setExtraValue(DISTINCT_ID, String(userId));
|
|
101
77
|
}
|
|
102
78
|
}
|
|
79
|
+
return span;
|
|
103
80
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
81
|
+
skipSpanUpdateEvents = true;
|
|
82
|
+
_updateSpan(_args) {
|
|
83
|
+
throw new Error("Method not implemented.");
|
|
84
|
+
}
|
|
85
|
+
async _finishSpan(args) {
|
|
86
|
+
const { span, traceData } = args;
|
|
87
|
+
const cachedSpan = traceData.getSpan({ spanId: span.id });
|
|
88
|
+
const mergedSpan = !span.input && cachedSpan?.input ? { ...span, input: cachedSpan.input } : span;
|
|
89
|
+
const eventMessage = this.buildEventMessage({ span: mergedSpan, traceData });
|
|
90
|
+
this.#client?.capture(eventMessage);
|
|
91
|
+
}
|
|
92
|
+
async _abortSpan(args) {
|
|
93
|
+
const { span, reason, traceData } = args;
|
|
94
|
+
span.errorInfo = reason;
|
|
95
|
+
const eventMessage = this.buildEventMessage({ span, traceData });
|
|
96
|
+
this.#client?.capture(eventMessage);
|
|
97
|
+
}
|
|
98
|
+
buildEventMessage(args) {
|
|
99
|
+
const { span, traceData } = args;
|
|
114
100
|
const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();
|
|
115
|
-
const latency = (endTime - startTime) / 1e3;
|
|
116
101
|
const distinctId = this.getDistinctId(span, traceData);
|
|
117
102
|
if (span.isRootSpan) {
|
|
118
|
-
this.
|
|
103
|
+
return this.buildRootEventMessage({ span, distinctId, endTime });
|
|
119
104
|
} else {
|
|
120
|
-
|
|
121
|
-
const parentIsRootSpan = this.isParentRootSpan(span, traceData);
|
|
122
|
-
const properties = this.buildEventProperties(span, latency, parentIsRootSpan);
|
|
123
|
-
this.client.capture({
|
|
124
|
-
distinctId,
|
|
125
|
-
event: eventName,
|
|
126
|
-
properties,
|
|
127
|
-
timestamp: new Date(endTime)
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
traceData.spans.delete(span.id);
|
|
131
|
-
if (traceData.spans.size === 0) {
|
|
132
|
-
this.traceMap.delete(span.traceId);
|
|
105
|
+
return this.buildChildEventMessage({ span, distinctId, endTime, traceData });
|
|
133
106
|
}
|
|
134
107
|
}
|
|
135
108
|
/**
|
|
@@ -137,7 +110,8 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
137
110
|
* This gives us control over trace-level metadata like name and tags,
|
|
138
111
|
* rather than relying on PostHog's pseudo-trace auto-creation.
|
|
139
112
|
*/
|
|
140
|
-
|
|
113
|
+
buildRootEventMessage(args) {
|
|
114
|
+
const { span, distinctId, endTime } = args;
|
|
141
115
|
const traceProperties = {
|
|
142
116
|
$ai_trace_id: span.traceId,
|
|
143
117
|
$ai_span_name: span.name,
|
|
@@ -166,32 +140,26 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
166
140
|
}
|
|
167
141
|
const { userId, sessionId, ...customMetadata } = span.metadata ?? {};
|
|
168
142
|
Object.assign(traceProperties, customMetadata);
|
|
169
|
-
|
|
143
|
+
return {
|
|
170
144
|
distinctId,
|
|
171
145
|
event: "$ai_trace",
|
|
172
146
|
properties: traceProperties,
|
|
173
147
|
timestamp: new Date(endTime)
|
|
174
|
-
}
|
|
148
|
+
};
|
|
175
149
|
}
|
|
176
|
-
|
|
150
|
+
buildChildEventMessage(args) {
|
|
151
|
+
const { span, distinctId, endTime, traceData } = args;
|
|
177
152
|
const eventName = this.mapToPostHogEvent(span.type);
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
this.
|
|
153
|
+
const startTime = span.startTime.getTime();
|
|
154
|
+
const latency = (endTime - startTime) / 1e3;
|
|
155
|
+
const parentIsRootSpan = this.isParentRootSpan(span, traceData);
|
|
156
|
+
const properties = this.buildEventProperties(span, latency, parentIsRootSpan);
|
|
157
|
+
return {
|
|
182
158
|
distinctId,
|
|
183
159
|
event: eventName,
|
|
184
160
|
properties,
|
|
185
|
-
timestamp:
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
async shutdown() {
|
|
189
|
-
if (this.client) {
|
|
190
|
-
await this.client.shutdown();
|
|
191
|
-
}
|
|
192
|
-
this.traceMap.clear();
|
|
193
|
-
await super.shutdown();
|
|
194
|
-
this.logger.info("PostHog exporter shutdown complete");
|
|
161
|
+
timestamp: new Date(endTime)
|
|
162
|
+
};
|
|
195
163
|
}
|
|
196
164
|
toDate(timestamp) {
|
|
197
165
|
return timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
@@ -206,8 +174,8 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
206
174
|
if (span.metadata?.userId) {
|
|
207
175
|
return String(span.metadata.userId);
|
|
208
176
|
}
|
|
209
|
-
if (traceData?.
|
|
210
|
-
return traceData.
|
|
177
|
+
if (traceData?.hasExtraValue(DISTINCT_ID)) {
|
|
178
|
+
return String(traceData.getExtraValue(DISTINCT_ID));
|
|
211
179
|
}
|
|
212
180
|
if (this.config.defaultDistinctId) {
|
|
213
181
|
return this.config.defaultDistinctId;
|
|
@@ -223,7 +191,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
223
191
|
if (!span.parentSpanId) {
|
|
224
192
|
return false;
|
|
225
193
|
}
|
|
226
|
-
const parentCache = traceData.
|
|
194
|
+
const parentCache = traceData.getSpan({ spanId: span.parentSpanId });
|
|
227
195
|
if (parentCache) {
|
|
228
196
|
return parentCache.isRootSpan;
|
|
229
197
|
}
|
|
@@ -255,18 +223,18 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
255
223
|
return { ...baseProperties, ...this.buildSpanProperties(span) };
|
|
256
224
|
}
|
|
257
225
|
}
|
|
258
|
-
extractErrorProperties(
|
|
259
|
-
if (!
|
|
226
|
+
extractErrorProperties(errorInfo) {
|
|
227
|
+
if (!errorInfo) {
|
|
260
228
|
return {};
|
|
261
229
|
}
|
|
262
230
|
const props = {
|
|
263
|
-
error_message:
|
|
231
|
+
error_message: errorInfo.message
|
|
264
232
|
};
|
|
265
|
-
if (
|
|
266
|
-
props.error_id =
|
|
233
|
+
if (errorInfo.id) {
|
|
234
|
+
props.error_id = errorInfo.id;
|
|
267
235
|
}
|
|
268
|
-
if (
|
|
269
|
-
props.error_category =
|
|
236
|
+
if (errorInfo.category) {
|
|
237
|
+
props.error_category = errorInfo.category;
|
|
270
238
|
}
|
|
271
239
|
return props;
|
|
272
240
|
}
|
|
@@ -287,7 +255,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
287
255
|
if (attrs.parameters.maxOutputTokens !== void 0) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;
|
|
288
256
|
}
|
|
289
257
|
if (attrs.streaming !== void 0) props.$ai_stream = attrs.streaming;
|
|
290
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
258
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
291
259
|
}
|
|
292
260
|
buildSpanProperties(span) {
|
|
293
261
|
const props = {};
|
|
@@ -301,7 +269,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
301
269
|
if (span.attributes) {
|
|
302
270
|
Object.assign(props, span.attributes);
|
|
303
271
|
}
|
|
304
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
272
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
305
273
|
}
|
|
306
274
|
formatMessages(data, defaultRole = "user") {
|
|
307
275
|
if (this.isMessageArray(data)) {
|
|
@@ -340,6 +308,11 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
340
308
|
return String(data);
|
|
341
309
|
}
|
|
342
310
|
}
|
|
311
|
+
async _postShutdown() {
|
|
312
|
+
if (this.#client) {
|
|
313
|
+
await this.#client.shutdown();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
343
316
|
};
|
|
344
317
|
|
|
345
318
|
export { PosthogExporter, formatUsageMetrics };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tracing.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { TracingEvent, AnyExportedSpan, ModelGenerationAttributes, UsageStats } from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport type { BaseExporterConfig } from '@mastra/observability';\nimport { BaseExporter } from '@mastra/observability';\nimport { PostHog } from 'posthog-node';\n\n/**\n * Token usage format compatible with PostHog.\n * @see https://posthog.com/docs/llm-analytics/generations#event-properties\n */\nexport interface PostHogUsageMetrics {\n $ai_input_tokens?: number;\n $ai_output_tokens?: number;\n $ai_cache_read_input_tokens?: number;\n $ai_cache_creation_input_tokens?: number;\n}\n\n/**\n * Formats UsageStats to PostHog's expected property format.\n *\n * @param usage - The UsageStats from span attributes\n * @returns PostHog-formatted usage properties\n */\nexport function formatUsageMetrics(usage?: UsageStats): PostHogUsageMetrics {\n if (!usage) return {};\n\n const props: PostHogUsageMetrics = {};\n\n if (usage.inputTokens !== undefined) props.$ai_input_tokens = usage.inputTokens;\n if (usage.outputTokens !== undefined) props.$ai_output_tokens = usage.outputTokens;\n\n // Cache read tokens from inputDetails\n if (usage.inputDetails?.cacheRead !== undefined) props.$ai_cache_read_input_tokens = usage.inputDetails.cacheRead;\n\n // Cache write tokens from inputDetails\n if (usage.inputDetails?.cacheWrite !== undefined)\n props.$ai_cache_creation_input_tokens = usage.inputDetails.cacheWrite;\n\n return props;\n}\n\ninterface PostHogMessage {\n role: 'user' | 'assistant' | 'system' | 'tool';\n content: PostHogContent[];\n}\n\ninterface PostHogContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface MastraMessage {\n role: string;\n content: string | MastraContent[];\n}\n\ninterface MastraContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ntype SpanData = string | MastraMessage[] | Record<string, unknown> | unknown;\n\nexport interface PosthogExporterConfig extends BaseExporterConfig {\n apiKey: string;\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n serverless?: boolean;\n defaultDistinctId?: string;\n enablePrivacyMode?: boolean;\n}\n\ntype SpanCache = {\n startTime: Date;\n type: SpanType;\n isRootSpan: boolean;\n};\n\ntype TraceMetadata = {\n spans: Map<string, SpanCache>;\n distinctId?: string;\n};\n\nexport class PosthogExporter extends BaseExporter {\n name = 'posthog';\n private client: PostHog;\n private config: PosthogExporterConfig;\n private traceMap = new Map<string, TraceMetadata>();\n\n private static readonly SERVERLESS_FLUSH_AT = 10;\n private static readonly SERVERLESS_FLUSH_INTERVAL = 2000;\n private static readonly DEFAULT_FLUSH_AT = 20;\n private static readonly DEFAULT_FLUSH_INTERVAL = 10000;\n\n constructor(config: PosthogExporterConfig) {\n super(config);\n this.config = config;\n\n if (!config.apiKey) {\n this.setDisabled('Missing required API key');\n this.client = null as any;\n return;\n }\n\n const clientConfig = this.buildClientConfig(config);\n this.client = new PostHog(config.apiKey, clientConfig);\n this.logInitialization(config.serverless ?? false, clientConfig);\n }\n\n private buildClientConfig(config: PosthogExporterConfig) {\n const isServerless = config.serverless ?? false;\n const flushAt =\n config.flushAt ?? (isServerless ? PosthogExporter.SERVERLESS_FLUSH_AT : PosthogExporter.DEFAULT_FLUSH_AT);\n const flushInterval =\n config.flushInterval ??\n (isServerless ? PosthogExporter.SERVERLESS_FLUSH_INTERVAL : PosthogExporter.DEFAULT_FLUSH_INTERVAL);\n\n const host = config.host || process.env.POSTHOG_HOST || 'https://us.i.posthog.com';\n\n if (!config.host && !process.env.POSTHOG_HOST) {\n this.logger.warn(\n 'No PostHog host specified, using US default (https://us.i.posthog.com). ' +\n 'For EU region, set `host: \"https://eu.i.posthog.com\"` in config or POSTHOG_HOST env var. ' +\n 'For self-hosted, provide your instance URL.',\n );\n }\n\n return {\n host,\n flushAt,\n flushInterval,\n privacyMode: config.enablePrivacyMode,\n };\n }\n\n private logInitialization(\n isServerless: boolean,\n config: { host: string; flushAt: number; flushInterval: number; privacyMode?: boolean },\n ): void {\n const message = isServerless ? 'PostHog exporter initialized in serverless mode' : 'PostHog exporter initialized';\n this.logger.debug(message, config);\n }\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.client) {\n return;\n }\n\n try {\n if (event.exportedSpan.isEvent) {\n if (event.type === 'span_started') {\n await this.captureEventSpan(event.exportedSpan);\n }\n return;\n }\n\n switch (event.type) {\n case 'span_started':\n await this.handleSpanStarted(event.exportedSpan);\n break;\n case 'span_updated':\n break;\n case 'span_ended':\n await this.handleSpanEnded(event.exportedSpan);\n break;\n }\n } catch (error) {\n this.logger.error('PostHog exporter error', { error, event });\n }\n }\n\n private async handleSpanStarted(span: AnyExportedSpan): Promise<void> {\n let traceData = this.traceMap.get(span.traceId);\n\n if (!traceData) {\n traceData = {\n spans: new Map(),\n distinctId: undefined,\n };\n this.traceMap.set(span.traceId, traceData);\n }\n\n traceData.spans.set(span.id, {\n startTime: this.toDate(span.startTime),\n type: span.type,\n isRootSpan: span.isRootSpan,\n });\n\n if (!traceData.distinctId) {\n const userId = span.metadata?.userId;\n if (userId) {\n traceData.distinctId = String(userId);\n }\n }\n }\n\n private async handleSpanEnded(span: AnyExportedSpan): Promise<void> {\n const traceData = this.traceMap.get(span.traceId);\n\n if (!traceData) {\n return;\n }\n\n const cachedSpan = traceData.spans.get(span.id);\n if (!cachedSpan) {\n return;\n }\n\n const startTime = cachedSpan.startTime.getTime();\n const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();\n const latency = (endTime - startTime) / 1000;\n\n const distinctId = this.getDistinctId(span, traceData);\n\n // For root spans, only send $ai_trace (not $ai_span) to avoid duplicate entries\n // For non-root spans, send $ai_span or $ai_generation as normal\n if (span.isRootSpan) {\n this.captureTraceEvent(span, distinctId, endTime);\n } else {\n const eventName = this.mapToPostHogEvent(span.type);\n\n // Check if parent is the root span - if so, use traceId as parent_id\n // since we don't create an $ai_span for root spans\n const parentIsRootSpan = this.isParentRootSpan(span, traceData);\n const properties = this.buildEventProperties(span, latency, parentIsRootSpan);\n\n this.client.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: new Date(endTime),\n });\n }\n\n traceData.spans.delete(span.id);\n if (traceData.spans.size === 0) {\n this.traceMap.delete(span.traceId);\n }\n }\n\n /**\n * Capture an explicit $ai_trace event for root spans.\n * This gives us control over trace-level metadata like name and tags,\n * rather than relying on PostHog's pseudo-trace auto-creation.\n */\n private captureTraceEvent(span: AnyExportedSpan, distinctId: string, endTime: number): void {\n // Note: We don't set $ai_latency on $ai_trace events because PostHog\n // aggregates latency from child events. Setting it here causes double-counting.\n const traceProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_span_name: span.name,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.metadata?.sessionId) {\n traceProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n if (span.input) {\n traceProperties.$ai_input_state = span.input;\n }\n\n if (span.output) {\n traceProperties.$ai_output_state = span.output;\n }\n\n if (span.errorInfo) {\n traceProperties.$ai_error = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id && { id: span.errorInfo.id }),\n ...(span.errorInfo.category && { category: span.errorInfo.category }),\n };\n }\n\n // Add tags as custom properties (PostHog doesn't have native tag support on traces)\n if (span.tags?.length) {\n for (const tag of span.tags) {\n traceProperties[tag] = true;\n }\n }\n\n // Add custom metadata (excluding userId and sessionId which are handled separately)\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n Object.assign(traceProperties, customMetadata);\n\n this.client.capture({\n distinctId,\n event: '$ai_trace',\n properties: traceProperties,\n timestamp: new Date(endTime),\n });\n }\n\n private async captureEventSpan(span: AnyExportedSpan): Promise<void> {\n const eventName = this.mapToPostHogEvent(span.type);\n const traceData = this.traceMap.get(span.traceId);\n\n const distinctId = this.getDistinctId(span, traceData);\n const properties = this.buildEventProperties(span, 0);\n\n this.client.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: span.endTime ? new Date(span.endTime) : new Date(),\n });\n }\n\n async shutdown(): Promise<void> {\n if (this.client) {\n await this.client.shutdown();\n }\n this.traceMap.clear();\n await super.shutdown();\n this.logger.info('PostHog exporter shutdown complete');\n }\n\n private toDate(timestamp: Date | number): Date {\n return timestamp instanceof Date ? timestamp : new Date(timestamp);\n }\n\n private mapToPostHogEvent(spanType: SpanType): string {\n if (spanType == SpanType.MODEL_GENERATION) {\n return '$ai_generation';\n }\n return '$ai_span';\n }\n\n private getDistinctId(span: AnyExportedSpan, traceData?: TraceMetadata): string {\n if (span.metadata?.userId) {\n return String(span.metadata.userId);\n }\n\n if (traceData?.distinctId) {\n return traceData.distinctId;\n }\n\n if (this.config.defaultDistinctId) {\n return this.config.defaultDistinctId;\n }\n\n return 'anonymous';\n }\n\n /**\n * Check if the parent of this span is the root span.\n * We need this because we don't create $ai_span for root spans,\n * so children of root spans should use $ai_trace_id as their $ai_parent_id.\n */\n private isParentRootSpan(span: AnyExportedSpan, traceData: TraceMetadata): boolean {\n if (!span.parentSpanId) {\n return false;\n }\n\n // Look up the parent span in our cache to check if it's a root span\n const parentCache = traceData.spans.get(span.parentSpanId);\n if (parentCache) {\n return parentCache.isRootSpan;\n }\n\n // Parent not found in cache - shouldn't happen normally, but default to false\n return false;\n }\n\n private buildEventProperties(\n span: AnyExportedSpan,\n latency: number,\n parentIsRootSpan: boolean = false,\n ): Record<string, any> {\n const baseProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_latency: latency,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.parentSpanId) {\n // If parent is the root span, use trace_id as parent_id since we don't\n // create an $ai_span for root spans (only $ai_trace)\n baseProperties.$ai_parent_id = parentIsRootSpan ? span.traceId : span.parentSpanId;\n }\n\n if (span.metadata?.sessionId) {\n baseProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n // Include tags for root spans (tags are only set on root spans by design)\n // PostHog doesn't allow setting tags directly, so we iterate through each tag\n // and set it as a property with value true\n if (span.isRootSpan && span.tags?.length) {\n for (const tag of span.tags) {\n baseProperties[tag] = true;\n }\n }\n\n if (span.type === SpanType.MODEL_GENERATION) {\n baseProperties.$ai_generation_id = span.id;\n return { ...baseProperties, ...this.buildGenerationProperties(span) };\n } else {\n baseProperties.$ai_span_id = span.id;\n baseProperties.$ai_span_name = span.name;\n return { ...baseProperties, ...this.buildSpanProperties(span) };\n }\n }\n\n private extractErrorProperties(span: AnyExportedSpan): Record<string, any> {\n if (!span.errorInfo) {\n return {};\n }\n\n const props: Record<string, string> = {\n error_message: span.errorInfo.message,\n };\n\n if (span.errorInfo.id) {\n props.error_id = span.errorInfo.id;\n }\n\n if (span.errorInfo.category) {\n props.error_category = span.errorInfo.category;\n }\n\n return props;\n }\n\n private extractCustomMetadata(span: AnyExportedSpan): Record<string, any> {\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n return customMetadata;\n }\n\n private buildGenerationProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n const attrs = (span.attributes ?? {}) as ModelGenerationAttributes;\n\n props.$ai_model = attrs.model || 'unknown-model';\n props.$ai_provider = attrs.provider || 'unknown-provider';\n\n if (span.input) props.$ai_input = this.formatMessages(span.input, 'user');\n if (span.output) props.$ai_output_choices = this.formatMessages(span.output, 'assistant');\n\n // Extract usage properties using the shared utility\n Object.assign(props, formatUsageMetrics(attrs.usage));\n\n if (attrs.parameters) {\n if (attrs.parameters.temperature !== undefined) props.$ai_temperature = attrs.parameters.temperature;\n if (attrs.parameters.maxOutputTokens !== undefined) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;\n }\n if (attrs.streaming !== undefined) props.$ai_stream = attrs.streaming;\n\n return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };\n }\n\n private buildSpanProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n\n if (span.input) props.$ai_input_state = span.input;\n if (span.output) props.$ai_output_state = span.output;\n\n if (span.type === SpanType.MODEL_CHUNK) {\n const attrs = span.attributes as any;\n if (attrs?.chunkType) props.chunk_type = attrs.chunkType;\n if (attrs?.sequenceNumber !== undefined) props.chunk_sequence_number = attrs.sequenceNumber;\n }\n\n if (span.attributes) {\n Object.assign(props, span.attributes);\n }\n\n return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };\n }\n\n private formatMessages(data: SpanData, defaultRole: 'user' | 'assistant' = 'user'): PostHogMessage[] {\n if (this.isMessageArray(data)) {\n return data.map(msg => this.normalizeMessage(msg));\n }\n\n if (typeof data === 'string') {\n return [{ role: defaultRole, content: [{ type: 'text', text: data }] }];\n }\n\n return [{ role: defaultRole, content: [{ type: 'text', text: this.safeStringify(data) }] }];\n }\n\n private isMessageArray(data: unknown): data is MastraMessage[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n return data.every(item => typeof item === 'object' && item !== null && 'role' in item && 'content' in item);\n }\n\n private normalizeMessage(msg: MastraMessage): PostHogMessage {\n if (typeof msg.content === 'string') {\n return {\n role: msg.role as PostHogMessage['role'],\n content: [{ type: 'text', text: msg.content }],\n };\n }\n\n return {\n role: msg.role as PostHogMessage['role'],\n content: msg.content as PostHogContent[],\n };\n }\n\n private safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/tracing.ts"],"names":[],"mappings":";;;;;AAwBO,SAAS,mBAAmB,KAAA,EAAyC;AAC1E,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAC;AAEpB,EAAA,MAAM,QAA6B,EAAC;AAEpC,EAAA,IAAI,KAAA,CAAM,WAAA,KAAgB,MAAA,EAAW,KAAA,CAAM,mBAAmB,KAAA,CAAM,WAAA;AACpE,EAAA,IAAI,KAAA,CAAM,YAAA,KAAiB,MAAA,EAAW,KAAA,CAAM,oBAAoB,KAAA,CAAM,YAAA;AAGtE,EAAA,IAAI,MAAM,YAAA,EAAc,SAAA,KAAc,QAAW,KAAA,CAAM,2BAAA,GAA8B,MAAM,YAAA,CAAa,SAAA;AAGxG,EAAA,IAAI,KAAA,CAAM,cAAc,UAAA,KAAe,MAAA;AACrC,IAAA,KAAA,CAAM,+BAAA,GAAkC,MAAM,YAAA,CAAa,UAAA;AAE7D,EAAA,OAAO,KAAA;AACT;AA0BA,IAAM,WAAA,GAAc,YAAA;AAsBb,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,gBAAA,CAMnC;AAAA,EACA,IAAA,GAAO,SAAA;AAAA,EACP,OAAA;AAAA,EAEA,OAAwB,mBAAA,GAAsB,EAAA;AAAA,EAC9C,OAAwB,yBAAA,GAA4B,GAAA;AAAA,EACpD,OAAwB,gBAAA,GAAmB,EAAA;AAAA,EAC3C,OAAwB,sBAAA,GAAyB,GAAA;AAAA,EAEjD,WAAA,CAAY,MAAA,GAAgC,EAAC,EAAG;AAE9C,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,IAAU,OAAA,CAAQ,GAAA,CAAI,eAAA;AAE5C,IAAA,KAAA,CAAM,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,CAAA;AAE3B,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,IAAA,CAAK,YAAY,8FAA8F,CAAA;AAC/G,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,iBAAA,CAAkB,IAAA,CAAK,MAAM,CAAA;AACvD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,OAAA,CAAQ,MAAA,EAAQ,YAAY,CAAA;AAC/C,IAAA,MAAM,OAAA,GACH,MAAA,CAAO,UAAA,IAAc,KAAA,GAAS,iDAAA,GAAoD,8BAAA;AACrF,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,MAAM,CAAA;AAAA,EACnC;AAAA,EAEQ,kBAAkB,MAAA,EAA+B;AACvD,IAAA,MAAM,YAAA,GAAe,OAAO,UAAA,IAAc,KAAA;AAC1C,IAAA,MAAM,UACJ,MAAA,CAAO,OAAA,KAAY,YAAA,GAAe,gBAAA,CAAgB,sBAAsB,gBAAA,CAAgB,gBAAA,CAAA;AAC1F,IAAA,MAAM,gBACJ,MAAA,CAAO,aAAA,KACN,YAAA,GAAe,gBAAA,CAAgB,4BAA4B,gBAAA,CAAgB,sBAAA,CAAA;AAE9E,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,IAAQ,OAAA,CAAQ,IAAI,YAAA,IAAgB,0BAAA;AAExD,IAAA,IAAI,CAAC,MAAA,CAAO,IAAA,IAAQ,CAAC,OAAA,CAAQ,IAAI,YAAA,EAAc;AAC7C,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,QACV;AAAA,OAGF;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAa,MAAA,CAAO;AAAA,KACtB;AAAA,EACF;AAAA,EAEmB,iBAAA,GAAoB,IAAA;AAAA,EACvC,MAAyB,WAAW,KAAA,EAGC;AACnC,IAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,EAC3C;AAAA,EAEmB,qBAAA,GAAwB,IAAA;AAAA,EAC3C,MAAyB,YAAY,IAAA,EAGX;AACxB,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAU,GAAI,IAAA;AAE5B,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAA;AAClD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,aAAA,CAAc,IAAA,EAAM,SAAS,CAAA;AACrD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,oBAAA,CAAqB,IAAA,EAAM,CAAC,CAAA;AAEpD,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ;AAAA,MACpB,UAAA;AAAA,MACA,KAAA,EAAO,SAAA;AAAA,MACP,UAAA;AAAA,MACA,SAAA,EAAW,KAAK,OAAA,GAAU,IAAI,KAAK,IAAA,CAAK,OAAO,CAAA,mBAAI,IAAI,IAAA;AAAK,KAC7D,CAAA;AAED,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAyB,WAAW,IAAA,EAGC;AACnC,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAU,GAAI,IAAA;AAC5B,IAAA,IAAI,CAAC,SAAA,CAAU,aAAA,CAAc,WAAW,CAAA,EAAG;AACzC,MAAA,MAAM,MAAA,GAAS,KAAK,QAAA,EAAU,MAAA;AAC9B,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,SAAA,CAAU,aAAA,CAAc,WAAA,EAAa,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,MACrD;AAAA,IACF;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEmB,oBAAA,GAAuB,IAAA;AAAA,EACvB,YAAY,KAAA,EAA8E;AAC3G,IAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,EAC3C;AAAA,EAEA,MAAyB,YAAY,IAAA,EAA6E;AAChH,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAU,GAAI,IAAA;AAI5B,IAAA,MAAM,aAAa,SAAA,CAAU,OAAA,CAAQ,EAAE,MAAA,EAAQ,IAAA,CAAK,IAAI,CAAA;AACxD,IAAA,MAAM,UAAA,GAAa,CAAC,IAAA,CAAK,KAAA,IAAS,UAAA,EAAY,KAAA,GAAQ,EAAE,GAAG,IAAA,EAAM,KAAA,EAAO,UAAA,CAAW,KAAA,EAAM,GAAI,IAAA;AAE7F,IAAA,MAAM,eAAe,IAAA,CAAK,iBAAA,CAAkB,EAAE,IAAA,EAAM,UAAA,EAAY,WAAW,CAAA;AAC3E,IAAA,IAAA,CAAK,OAAA,EAAS,QAAQ,YAAY,CAAA;AAAA,EACpC;AAAA,EAEA,MAAyB,WAAW,IAAA,EAIlB;AAChB,IAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAU,GAAI,IAAA;AAGpC,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AAEjB,IAAA,MAAM,eAAe,IAAA,CAAK,iBAAA,CAAkB,EAAE,IAAA,EAAM,WAAW,CAAA;AAC/D,IAAA,IAAA,CAAK,OAAA,EAAS,QAAQ,YAAY,CAAA;AAAA,EACpC;AAAA,EAEQ,kBAAkB,IAAA,EAA4E;AACpG,IAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAU,GAAI,IAAA;AAE5B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,OAAA,EAAQ,GAAI,IAAA,CAAK,GAAA,EAAI;AAE9E,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,aAAA,CAAc,IAAA,EAAM,SAAS,CAAA;AAErD,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,OAAO,KAAK,qBAAA,CAAsB,EAAE,IAAA,EAAM,UAAA,EAAY,SAAS,CAAA;AAAA,IACjE,CAAA,MAAO;AACL,MAAA,OAAO,KAAK,sBAAA,CAAuB,EAAE,MAAM,UAAA,EAAY,OAAA,EAAS,WAAW,CAAA;AAAA,IAC7E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBAAsB,IAAA,EAAoF;AAChH,IAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAQ,GAAI,IAAA;AAItC,IAAA,MAAM,eAAA,GAAuC;AAAA,MAC3C,cAAc,IAAA,CAAK,OAAA;AAAA,MACnB,eAAe,IAAA,CAAK,IAAA;AAAA,MACpB,YAAA,EAAc,CAAC,CAAC,IAAA,CAAK;AAAA,KACvB;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC5B,MAAA,eAAA,CAAgB,cAAA,GAAiB,KAAK,QAAA,CAAS,SAAA;AAAA,IACjD;AAEA,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,eAAA,CAAgB,kBAAkB,IAAA,CAAK,KAAA;AAAA,IACzC;AAEA,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,eAAA,CAAgB,mBAAmB,IAAA,CAAK,MAAA;AAAA,IAC1C;AAEA,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,eAAA,CAAgB,SAAA,GAAY;AAAA,QAC1B,OAAA,EAAS,KAAK,SAAA,CAAU,OAAA;AAAA,QACxB,GAAI,KAAK,SAAA,CAAU,EAAA,IAAM,EAAE,EAAA,EAAI,IAAA,CAAK,UAAU,EAAA,EAAG;AAAA,QACjD,GAAI,KAAK,SAAA,CAAU,QAAA,IAAY,EAAE,QAAA,EAAU,IAAA,CAAK,UAAU,QAAA;AAAS,OACrE;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAM,MAAA,EAAQ;AACrB,MAAA,KAAA,MAAW,GAAA,IAAO,KAAK,IAAA,EAAM;AAC3B,QAAA,eAAA,CAAgB,GAAG,CAAA,GAAI,IAAA;AAAA,MACzB;AAAA,IACF;AAGA,IAAA,MAAM,EAAE,QAAQ,SAAA,EAAW,GAAG,gBAAe,GAAI,IAAA,CAAK,YAAY,EAAC;AACnE,IAAA,MAAA,CAAO,MAAA,CAAO,iBAAiB,cAAc,CAAA;AAE7C,IAAA,OAAO;AAAA,MACL,UAAA;AAAA,MACA,KAAA,EAAO,WAAA;AAAA,MACP,UAAA,EAAY,eAAA;AAAA,MACZ,SAAA,EAAW,IAAI,IAAA,CAAK,OAAO;AAAA,KAC7B;AAAA,EACF;AAAA,EAEQ,uBAAuB,IAAA,EAKd;AACf,IAAA,MAAM,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS,WAAU,GAAI,IAAA;AAEjD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAA;AAClD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,SAAA,CAAU,OAAA,EAAQ;AACzC,IAAA,MAAM,OAAA,GAAA,CAAW,UAAU,SAAA,IAAa,GAAA;AAIxC,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,gBAAA,CAAiB,IAAA,EAAM,SAAS,CAAA;AAC9D,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,oBAAA,CAAqB,IAAA,EAAM,SAAS,gBAAgB,CAAA;AAE5E,IAAA,OAAO;AAAA,MACL,UAAA;AAAA,MACA,KAAA,EAAO,SAAA;AAAA,MACP,UAAA;AAAA,MACA,SAAA,EAAW,IAAI,IAAA,CAAK,OAAO;AAAA,KAC7B;AAAA,EACF;AAAA,EAEQ,OAAO,SAAA,EAAgC;AAC7C,IAAA,OAAO,SAAA,YAAqB,IAAA,GAAO,SAAA,GAAY,IAAI,KAAK,SAAS,CAAA;AAAA,EACnE;AAAA,EAEQ,kBAAkB,QAAA,EAA4B;AACpD,IAAA,IAAI,QAAA,IAAY,SAAS,gBAAA,EAAkB;AACzC,MAAA,OAAO,gBAAA;AAAA,IACT;AACA,IAAA,OAAO,UAAA;AAAA,EACT;AAAA,EAEQ,aAAA,CAAc,MAAuB,SAAA,EAAsC;AACjF,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,MAAA,OAAO,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAAA,IACpC;AAEA,IAAA,IAAI,SAAA,EAAW,aAAA,CAAc,WAAW,CAAA,EAAG;AACzC,MAAA,OAAO,MAAA,CAAO,SAAA,CAAU,aAAA,CAAc,WAAW,CAAC,CAAA;AAAA,IACpD;AAEA,IAAA,IAAI,IAAA,CAAK,OAAO,iBAAA,EAAmB;AACjC,MAAA,OAAO,KAAK,MAAA,CAAO,iBAAA;AAAA,IACrB;AAEA,IAAA,OAAO,WAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAA,CAAiB,MAAuB,SAAA,EAAsC;AACpF,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc;AACtB,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,MAAM,cAAc,SAAA,CAAU,OAAA,CAAQ,EAAE,MAAA,EAAQ,IAAA,CAAK,cAAc,CAAA;AACnE,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,OAAO,WAAA,CAAY,UAAA;AAAA,IACrB;AAGA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEQ,oBAAA,CACN,IAAA,EACA,OAAA,EACA,gBAAA,GAA4B,KAAA,EACP;AACrB,IAAA,MAAM,cAAA,GAAsC;AAAA,MAC1C,cAAc,IAAA,CAAK,OAAA;AAAA,MACnB,WAAA,EAAa,OAAA;AAAA,MACb,YAAA,EAAc,CAAC,CAAC,IAAA,CAAK;AAAA,KACvB;AAEA,IAAA,IAAI,KAAK,YAAA,EAAc;AAGrB,MAAA,cAAA,CAAe,aAAA,GAAgB,gBAAA,GAAmB,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,YAAA;AAAA,IACxE;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC5B,MAAA,cAAA,CAAe,cAAA,GAAiB,KAAK,QAAA,CAAS,SAAA;AAAA,IAChD;AAKA,IAAA,IAAI,IAAA,CAAK,UAAA,IAAc,IAAA,CAAK,IAAA,EAAM,MAAA,EAAQ;AACxC,MAAA,KAAA,MAAW,GAAA,IAAO,KAAK,IAAA,EAAM;AAC3B,QAAA,cAAA,CAAe,GAAG,CAAA,GAAI,IAAA;AAAA,MACxB;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,QAAA,CAAS,gBAAA,EAAkB;AAC3C,MAAA,cAAA,CAAe,oBAAoB,IAAA,CAAK,EAAA;AACxC,MAAA,OAAO,EAAE,GAAG,cAAA,EAAgB,GAAG,IAAA,CAAK,yBAAA,CAA0B,IAAI,CAAA,EAAE;AAAA,IACtE,CAAA,MAAO;AACL,MAAA,cAAA,CAAe,cAAc,IAAA,CAAK,EAAA;AAClC,MAAA,cAAA,CAAe,gBAAgB,IAAA,CAAK,IAAA;AACpC,MAAA,OAAO,EAAE,GAAG,cAAA,EAAgB,GAAG,IAAA,CAAK,mBAAA,CAAoB,IAAI,CAAA,EAAE;AAAA,IAChE;AAAA,EACF;AAAA,EAEQ,uBAAuB,SAAA,EAAgD;AAC7E,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,OAAO,EAAC;AAAA,IACV;AAEA,IAAA,MAAM,KAAA,GAAgC;AAAA,MACpC,eAAe,SAAA,CAAU;AAAA,KAC3B;AAEA,IAAA,IAAI,UAAU,EAAA,EAAI;AAChB,MAAA,KAAA,CAAM,WAAW,SAAA,CAAU,EAAA;AAAA,IAC7B;AAEA,IAAA,IAAI,UAAU,QAAA,EAAU;AACtB,MAAA,KAAA,CAAM,iBAAiB,SAAA,CAAU,QAAA;AAAA,IACnC;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEQ,sBAAsB,IAAA,EAA4C;AACxE,IAAA,MAAM,EAAE,QAAQ,SAAA,EAAW,GAAG,gBAAe,GAAI,IAAA,CAAK,YAAY,EAAC;AACnE,IAAA,OAAO,cAAA;AAAA,EACT;AAAA,EAEQ,0BAA0B,IAAA,EAA4C;AAC5E,IAAA,MAAM,QAA6B,EAAC;AACpC,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,UAAA,IAAc,EAAC;AAEnC,IAAA,KAAA,CAAM,SAAA,GAAY,MAAM,KAAA,IAAS,eAAA;AACjC,IAAA,KAAA,CAAM,YAAA,GAAe,MAAM,QAAA,IAAY,kBAAA;AAEvC,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,CAAM,SAAA,GAAY,KAAK,cAAA,CAAe,IAAA,CAAK,OAAO,MAAM,CAAA;AACxE,IAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,CAAM,kBAAA,GAAqB,KAAK,cAAA,CAAe,IAAA,CAAK,QAAQ,WAAW,CAAA;AAGxF,IAAA,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,kBAAA,CAAmB,KAAA,CAAM,KAAK,CAAC,CAAA;AAEpD,IAAA,IAAI,MAAM,UAAA,EAAY;AACpB,MAAA,IAAI,MAAM,UAAA,CAAW,WAAA,KAAgB,QAAW,KAAA,CAAM,eAAA,GAAkB,MAAM,UAAA,CAAW,WAAA;AACzF,MAAA,IAAI,MAAM,UAAA,CAAW,eAAA,KAAoB,QAAW,KAAA,CAAM,cAAA,GAAiB,MAAM,UAAA,CAAW,eAAA;AAAA,IAC9F;AACA,IAAA,IAAI,KAAA,CAAM,SAAA,KAAc,MAAA,EAAW,KAAA,CAAM,aAAa,KAAA,CAAM,SAAA;AAE5D,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,GAAG,IAAA,CAAK,sBAAA,CAAuB,IAAA,CAAK,SAAS,CAAA,EAAG,GAAG,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,EAAE;AAAA,EACzG;AAAA,EAEQ,oBAAoB,IAAA,EAA4C;AACtE,IAAA,MAAM,QAA6B,EAAC;AAEpC,IAAA,IAAI,IAAA,CAAK,KAAA,EAAO,KAAA,CAAM,eAAA,GAAkB,IAAA,CAAK,KAAA;AAC7C,IAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,gBAAA,GAAmB,IAAA,CAAK,MAAA;AAE/C,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,QAAA,CAAS,WAAA,EAAa;AACtC,MAAA,MAAM,QAAQ,IAAA,CAAK,UAAA;AACnB,MAAA,IAAI,KAAA,EAAO,SAAA,EAAW,KAAA,CAAM,UAAA,GAAa,KAAA,CAAM,SAAA;AAC/C,MAAA,IAAI,KAAA,EAAO,cAAA,KAAmB,MAAA,EAAW,KAAA,CAAM,wBAAwB,KAAA,CAAM,cAAA;AAAA,IAC/E;AAEA,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA;AAAA,IACtC;AAEA,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,GAAG,IAAA,CAAK,sBAAA,CAAuB,IAAA,CAAK,SAAS,CAAA,EAAG,GAAG,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,EAAE;AAAA,EACzG;AAAA,EAEQ,cAAA,CAAe,IAAA,EAAgB,WAAA,GAAoC,MAAA,EAA0B;AACnG,IAAA,IAAI,IAAA,CAAK,cAAA,CAAe,IAAI,CAAA,EAAG;AAC7B,MAAA,OAAO,KAAK,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAC,CAAA;AAAA,IACnD;AAEA,IAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,GAAG,CAAA;AAAA,IACxE;AAEA,IAAA,OAAO,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAK,aAAA,CAAc,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EAC5F;AAAA,EAEQ,eAAe,IAAA,EAAwC;AAC7D,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,WAAW,CAAA,EAAG;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,IAAA,KAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,IAAQ,MAAA,IAAU,IAAA,IAAQ,SAAA,IAAa,IAAI,CAAA;AAAA,EAC5G;AAAA,EAEQ,iBAAiB,GAAA,EAAoC;AAC3D,IAAA,IAAI,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,EAAU;AACnC,MAAA,OAAO;AAAA,QACL,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,GAAA,CAAI,SAAS;AAAA,OAC/C;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI;AAAA,KACf;AAAA,EACF;AAAA,EAEQ,cAAc,IAAA,EAAuB;AAC3C,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,IAC5B,CAAA,CAAA,MAAQ;AACN,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,QAAA,OAAO,CAAA,kBAAA,EAAqB,IAAA,CAAK,WAAA,EAAa,IAAA,IAAQ,QAAQ,CAAA,CAAA,CAAA;AAAA,MAChE;AACA,MAAA,OAAO,OAAO,IAAI,CAAA;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,MAAe,aAAA,GAA+B;AAC5C,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,IAAA,CAAK,QAAQ,QAAA,EAAS;AAAA,IAC9B;AAAA,EACF;AACF","file":"index.js","sourcesContent":["import type { AnyExportedSpan, ModelGenerationAttributes, SpanErrorInfo, UsageStats } from '@mastra/core/observability';\nimport { SpanType } from '@mastra/core/observability';\nimport type { TraceData, TrackingExporterConfig } from '@mastra/observability';\nimport { TrackingExporter } from '@mastra/observability';\nimport { PostHog } from 'posthog-node';\nimport type { EventMessage } from 'posthog-node';\n\n/**\n * Token usage format compatible with PostHog.\n * @see https://posthog.com/docs/llm-analytics/generations#event-properties\n */\nexport interface PostHogUsageMetrics {\n $ai_input_tokens?: number;\n $ai_output_tokens?: number;\n $ai_cache_read_input_tokens?: number;\n $ai_cache_creation_input_tokens?: number;\n}\n\n/**\n * Formats UsageStats to PostHog's expected property format.\n *\n * @param usage - The UsageStats from span attributes\n * @returns PostHog-formatted usage properties\n */\nexport function formatUsageMetrics(usage?: UsageStats): PostHogUsageMetrics {\n if (!usage) return {};\n\n const props: PostHogUsageMetrics = {};\n\n if (usage.inputTokens !== undefined) props.$ai_input_tokens = usage.inputTokens;\n if (usage.outputTokens !== undefined) props.$ai_output_tokens = usage.outputTokens;\n\n // Cache read tokens from inputDetails\n if (usage.inputDetails?.cacheRead !== undefined) props.$ai_cache_read_input_tokens = usage.inputDetails.cacheRead;\n\n // Cache write tokens from inputDetails\n if (usage.inputDetails?.cacheWrite !== undefined)\n props.$ai_cache_creation_input_tokens = usage.inputDetails.cacheWrite;\n\n return props;\n}\n\ninterface PostHogMessage {\n role: 'user' | 'assistant' | 'system' | 'tool';\n content: PostHogContent[];\n}\n\ninterface PostHogContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface MastraMessage {\n role: string;\n content: string | MastraContent[];\n}\n\ninterface MastraContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ntype SpanData = string | MastraMessage[] | Record<string, unknown> | unknown;\n\nconst DISTINCT_ID = 'distinctId';\n\nexport interface PosthogExporterConfig extends TrackingExporterConfig {\n /** PostHog API key. Defaults to POSTHOG_API_KEY environment variable. */\n apiKey?: string;\n /** PostHog host URL. Defaults to POSTHOG_HOST environment variable or US region. */\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n serverless?: boolean;\n defaultDistinctId?: string;\n enablePrivacyMode?: boolean;\n}\n\ntype PosthogRoot = unknown;\ntype PosthogSpan = AnyExportedSpan;\n// used as a placeholder for event data since we don't need to cache\n// event data for Posthog\ntype PosthogEvent = boolean;\ntype PosthogMetadata = unknown;\ntype PosthogTraceData = TraceData<PosthogRoot, PosthogSpan, PosthogEvent, PosthogMetadata>;\n\nexport class PosthogExporter extends TrackingExporter<\n PosthogRoot,\n PosthogSpan,\n PosthogEvent,\n PosthogMetadata,\n PosthogExporterConfig\n> {\n name = 'posthog';\n #client: PostHog | undefined;\n\n private static readonly SERVERLESS_FLUSH_AT = 10;\n private static readonly SERVERLESS_FLUSH_INTERVAL = 2000;\n private static readonly DEFAULT_FLUSH_AT = 20;\n private static readonly DEFAULT_FLUSH_INTERVAL = 10000;\n\n constructor(config: PosthogExporterConfig = {}) {\n // Resolve env vars BEFORE calling super (config is readonly in base class)\n const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;\n\n super({ ...config, apiKey });\n\n if (!apiKey) {\n this.setDisabled('Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.');\n return;\n }\n\n const clientConfig = this.buildClientConfig(this.config);\n this.#client = new PostHog(apiKey, clientConfig);\n const message =\n (config.serverless ?? false) ? 'PostHog exporter initialized in serverless mode' : 'PostHog exporter initialized';\n this.logger.debug(message, config);\n }\n\n private buildClientConfig(config: PosthogExporterConfig) {\n const isServerless = config.serverless ?? false;\n const flushAt =\n config.flushAt ?? (isServerless ? PosthogExporter.SERVERLESS_FLUSH_AT : PosthogExporter.DEFAULT_FLUSH_AT);\n const flushInterval =\n config.flushInterval ??\n (isServerless ? PosthogExporter.SERVERLESS_FLUSH_INTERVAL : PosthogExporter.DEFAULT_FLUSH_INTERVAL);\n\n const host = config.host || process.env.POSTHOG_HOST || 'https://us.i.posthog.com';\n\n if (!config.host && !process.env.POSTHOG_HOST) {\n this.logger.info(\n 'No PostHog host specified, using US default (https://us.i.posthog.com). ' +\n 'For EU region, set `host: \"https://eu.i.posthog.com\"` in config or POSTHOG_HOST env var. ' +\n 'For self-hosted, provide your instance URL.',\n );\n }\n\n return {\n host,\n flushAt,\n flushInterval,\n privacyMode: config.enablePrivacyMode,\n };\n }\n\n protected override skipBuildRootTask = true;\n protected override async _buildRoot(_args: {\n span: AnyExportedSpan;\n traceData: PosthogTraceData;\n }): Promise<PosthogRoot | undefined> {\n throw new Error('Method not implemented.');\n }\n\n protected override skipCachingEventSpans = true;\n protected override async _buildEvent(args: {\n span: AnyExportedSpan;\n traceData: PosthogTraceData;\n }): Promise<PosthogEvent> {\n const { span, traceData } = args;\n\n const eventName = this.mapToPostHogEvent(span.type);\n const distinctId = this.getDistinctId(span, traceData);\n const properties = this.buildEventProperties(span, 0);\n\n this.#client?.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: span.endTime ? new Date(span.endTime) : new Date(),\n });\n\n return true;\n }\n\n protected override async _buildSpan(args: {\n span: AnyExportedSpan;\n traceData: PosthogTraceData;\n }): Promise<PosthogSpan | undefined> {\n const { span, traceData } = args;\n if (!traceData.hasExtraValue(DISTINCT_ID)) {\n const userId = span.metadata?.userId;\n if (userId) {\n traceData.setExtraValue(DISTINCT_ID, String(userId));\n }\n }\n\n return span;\n }\n\n protected override skipSpanUpdateEvents = true;\n protected override _updateSpan(_args: { span: AnyExportedSpan; traceData: PosthogTraceData }): Promise<void> {\n throw new Error('Method not implemented.');\n }\n\n protected override async _finishSpan(args: { span: AnyExportedSpan; traceData: PosthogTraceData }): Promise<void> {\n const { span, traceData } = args;\n\n // Merge input from cached span (SPAN_STARTED) if not present on end span\n // This handles the case where input is only sent at start\n const cachedSpan = traceData.getSpan({ spanId: span.id });\n const mergedSpan = !span.input && cachedSpan?.input ? { ...span, input: cachedSpan.input } : span;\n\n const eventMessage = this.buildEventMessage({ span: mergedSpan, traceData });\n this.#client?.capture(eventMessage);\n }\n\n protected override async _abortSpan(args: {\n span: PosthogSpan;\n reason: SpanErrorInfo;\n traceData: PosthogTraceData;\n }): Promise<void> {\n const { span, reason, traceData } = args;\n\n // update span with the abort reason\n span.errorInfo = reason;\n\n const eventMessage = this.buildEventMessage({ span, traceData });\n this.#client?.capture(eventMessage);\n }\n\n private buildEventMessage(args: { span: AnyExportedSpan; traceData: PosthogTraceData }): EventMessage {\n const { span, traceData } = args;\n\n const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();\n\n const distinctId = this.getDistinctId(span, traceData);\n\n if (span.isRootSpan) {\n return this.buildRootEventMessage({ span, distinctId, endTime });\n } else {\n return this.buildChildEventMessage({ span, distinctId, endTime, traceData });\n }\n }\n\n /**\n * Capture an explicit $ai_trace event for root spans.\n * This gives us control over trace-level metadata like name and tags,\n * rather than relying on PostHog's pseudo-trace auto-creation.\n */\n private buildRootEventMessage(args: { span: AnyExportedSpan; distinctId: string; endTime: number }): EventMessage {\n const { span, distinctId, endTime } = args;\n\n // Note: We don't set $ai_latency on $ai_trace events because PostHog\n // aggregates latency from child events. Setting it here causes double-counting.\n const traceProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_span_name: span.name,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.metadata?.sessionId) {\n traceProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n if (span.input) {\n traceProperties.$ai_input_state = span.input;\n }\n\n if (span.output) {\n traceProperties.$ai_output_state = span.output;\n }\n\n if (span.errorInfo) {\n traceProperties.$ai_error = {\n message: span.errorInfo.message,\n ...(span.errorInfo.id && { id: span.errorInfo.id }),\n ...(span.errorInfo.category && { category: span.errorInfo.category }),\n };\n }\n\n // Add tags as custom properties (PostHog doesn't have native tag support on traces)\n if (span.tags?.length) {\n for (const tag of span.tags) {\n traceProperties[tag] = true;\n }\n }\n\n // Add custom metadata (excluding userId and sessionId which are handled separately)\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n Object.assign(traceProperties, customMetadata);\n\n return {\n distinctId,\n event: '$ai_trace',\n properties: traceProperties,\n timestamp: new Date(endTime),\n };\n }\n\n private buildChildEventMessage(args: {\n span: AnyExportedSpan;\n distinctId: string;\n endTime: number;\n traceData: PosthogTraceData;\n }): EventMessage {\n const { span, distinctId, endTime, traceData } = args;\n\n const eventName = this.mapToPostHogEvent(span.type);\n const startTime = span.startTime.getTime();\n const latency = (endTime - startTime) / 1000;\n\n // Check if parent is the root span - if so, use traceId as parent_id\n // since we don't create an $ai_span for root spans\n const parentIsRootSpan = this.isParentRootSpan(span, traceData);\n const properties = this.buildEventProperties(span, latency, parentIsRootSpan);\n\n return {\n distinctId,\n event: eventName,\n properties,\n timestamp: new Date(endTime),\n };\n }\n\n private toDate(timestamp: Date | number): Date {\n return timestamp instanceof Date ? timestamp : new Date(timestamp);\n }\n\n private mapToPostHogEvent(spanType: SpanType): string {\n if (spanType == SpanType.MODEL_GENERATION) {\n return '$ai_generation';\n }\n return '$ai_span';\n }\n\n private getDistinctId(span: AnyExportedSpan, traceData?: PosthogTraceData): string {\n if (span.metadata?.userId) {\n return String(span.metadata.userId);\n }\n\n if (traceData?.hasExtraValue(DISTINCT_ID)) {\n return String(traceData.getExtraValue(DISTINCT_ID));\n }\n\n if (this.config.defaultDistinctId) {\n return this.config.defaultDistinctId;\n }\n\n return 'anonymous';\n }\n\n /**\n * Check if the parent of this span is the root span.\n * We need this because we don't create $ai_span for root spans,\n * so children of root spans should use $ai_trace_id as their $ai_parent_id.\n */\n private isParentRootSpan(span: AnyExportedSpan, traceData: PosthogTraceData): boolean {\n if (!span.parentSpanId) {\n return false;\n }\n\n // Look up the parent span in our cache to check if it's a root span\n const parentCache = traceData.getSpan({ spanId: span.parentSpanId });\n if (parentCache) {\n return parentCache.isRootSpan;\n }\n\n // Parent not found in cache - shouldn't happen normally, but default to false\n return false;\n }\n\n private buildEventProperties(\n span: AnyExportedSpan,\n latency: number,\n parentIsRootSpan: boolean = false,\n ): Record<string, any> {\n const baseProperties: Record<string, any> = {\n $ai_trace_id: span.traceId,\n $ai_latency: latency,\n $ai_is_error: !!span.errorInfo,\n };\n\n if (span.parentSpanId) {\n // If parent is the root span, use trace_id as parent_id since we don't\n // create an $ai_span for root spans (only $ai_trace)\n baseProperties.$ai_parent_id = parentIsRootSpan ? span.traceId : span.parentSpanId;\n }\n\n if (span.metadata?.sessionId) {\n baseProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n // Include tags for root spans (tags are only set on root spans by design)\n // PostHog doesn't allow setting tags directly, so we iterate through each tag\n // and set it as a property with value true\n if (span.isRootSpan && span.tags?.length) {\n for (const tag of span.tags) {\n baseProperties[tag] = true;\n }\n }\n\n if (span.type === SpanType.MODEL_GENERATION) {\n baseProperties.$ai_generation_id = span.id;\n return { ...baseProperties, ...this.buildGenerationProperties(span) };\n } else {\n baseProperties.$ai_span_id = span.id;\n baseProperties.$ai_span_name = span.name;\n return { ...baseProperties, ...this.buildSpanProperties(span) };\n }\n }\n\n private extractErrorProperties(errorInfo?: SpanErrorInfo): Record<string, any> {\n if (!errorInfo) {\n return {};\n }\n\n const props: Record<string, string> = {\n error_message: errorInfo.message,\n };\n\n if (errorInfo.id) {\n props.error_id = errorInfo.id;\n }\n\n if (errorInfo.category) {\n props.error_category = errorInfo.category;\n }\n\n return props;\n }\n\n private extractCustomMetadata(span: AnyExportedSpan): Record<string, any> {\n const { userId, sessionId, ...customMetadata } = span.metadata ?? {};\n return customMetadata;\n }\n\n private buildGenerationProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n const attrs = (span.attributes ?? {}) as ModelGenerationAttributes;\n\n props.$ai_model = attrs.model || 'unknown-model';\n props.$ai_provider = attrs.provider || 'unknown-provider';\n\n if (span.input) props.$ai_input = this.formatMessages(span.input, 'user');\n if (span.output) props.$ai_output_choices = this.formatMessages(span.output, 'assistant');\n\n // Extract usage properties using the shared utility\n Object.assign(props, formatUsageMetrics(attrs.usage));\n\n if (attrs.parameters) {\n if (attrs.parameters.temperature !== undefined) props.$ai_temperature = attrs.parameters.temperature;\n if (attrs.parameters.maxOutputTokens !== undefined) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;\n }\n if (attrs.streaming !== undefined) props.$ai_stream = attrs.streaming;\n\n return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };\n }\n\n private buildSpanProperties(span: AnyExportedSpan): Record<string, any> {\n const props: Record<string, any> = {};\n\n if (span.input) props.$ai_input_state = span.input;\n if (span.output) props.$ai_output_state = span.output;\n\n if (span.type === SpanType.MODEL_CHUNK) {\n const attrs = span.attributes as any;\n if (attrs?.chunkType) props.chunk_type = attrs.chunkType;\n if (attrs?.sequenceNumber !== undefined) props.chunk_sequence_number = attrs.sequenceNumber;\n }\n\n if (span.attributes) {\n Object.assign(props, span.attributes);\n }\n\n return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };\n }\n\n private formatMessages(data: SpanData, defaultRole: 'user' | 'assistant' = 'user'): PostHogMessage[] {\n if (this.isMessageArray(data)) {\n return data.map(msg => this.normalizeMessage(msg));\n }\n\n if (typeof data === 'string') {\n return [{ role: defaultRole, content: [{ type: 'text', text: data }] }];\n }\n\n return [{ role: defaultRole, content: [{ type: 'text', text: this.safeStringify(data) }] }];\n }\n\n private isMessageArray(data: unknown): data is MastraMessage[] {\n if (!Array.isArray(data) || data.length === 0) {\n return false;\n }\n\n return data.every(item => typeof item === 'object' && item !== null && 'role' in item && 'content' in item);\n }\n\n private normalizeMessage(msg: MastraMessage): PostHogMessage {\n if (typeof msg.content === 'string') {\n return {\n role: msg.role as PostHogMessage['role'],\n content: [{ type: 'text', text: msg.content }],\n };\n }\n\n return {\n role: msg.role as PostHogMessage['role'],\n content: msg.content as PostHogContent[],\n };\n }\n\n private safeStringify(data: unknown): string {\n try {\n return JSON.stringify(data);\n } catch {\n if (typeof data === 'object' && data !== null) {\n return `[Non-serializable ${data.constructor?.name || 'Object'}]`;\n }\n return String(data);\n }\n }\n\n override async _postShutdown(): Promise<void> {\n if (this.#client) {\n await this.#client.shutdown();\n }\n }\n}\n"]}
|
package/dist/tracing.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
1
|
+
import type { AnyExportedSpan, SpanErrorInfo, UsageStats } from '@mastra/core/observability';
|
|
2
|
+
import type { TraceData, TrackingExporterConfig } from '@mastra/observability';
|
|
3
|
+
import { TrackingExporter } from '@mastra/observability';
|
|
4
4
|
/**
|
|
5
5
|
* Token usage format compatible with PostHog.
|
|
6
6
|
* @see https://posthog.com/docs/llm-analytics/generations#event-properties
|
|
@@ -18,8 +18,10 @@ export interface PostHogUsageMetrics {
|
|
|
18
18
|
* @returns PostHog-formatted usage properties
|
|
19
19
|
*/
|
|
20
20
|
export declare function formatUsageMetrics(usage?: UsageStats): PostHogUsageMetrics;
|
|
21
|
-
export interface PosthogExporterConfig extends
|
|
22
|
-
|
|
21
|
+
export interface PosthogExporterConfig extends TrackingExporterConfig {
|
|
22
|
+
/** PostHog API key. Defaults to POSTHOG_API_KEY environment variable. */
|
|
23
|
+
apiKey?: string;
|
|
24
|
+
/** PostHog host URL. Defaults to POSTHOG_HOST environment variable or US region. */
|
|
23
25
|
host?: string;
|
|
24
26
|
flushAt?: number;
|
|
25
27
|
flushInterval?: number;
|
|
@@ -27,29 +29,56 @@ export interface PosthogExporterConfig extends BaseExporterConfig {
|
|
|
27
29
|
defaultDistinctId?: string;
|
|
28
30
|
enablePrivacyMode?: boolean;
|
|
29
31
|
}
|
|
30
|
-
|
|
32
|
+
type PosthogRoot = unknown;
|
|
33
|
+
type PosthogSpan = AnyExportedSpan;
|
|
34
|
+
type PosthogEvent = boolean;
|
|
35
|
+
type PosthogMetadata = unknown;
|
|
36
|
+
type PosthogTraceData = TraceData<PosthogRoot, PosthogSpan, PosthogEvent, PosthogMetadata>;
|
|
37
|
+
export declare class PosthogExporter extends TrackingExporter<PosthogRoot, PosthogSpan, PosthogEvent, PosthogMetadata, PosthogExporterConfig> {
|
|
38
|
+
#private;
|
|
31
39
|
name: string;
|
|
32
|
-
private client;
|
|
33
|
-
private config;
|
|
34
|
-
private traceMap;
|
|
35
40
|
private static readonly SERVERLESS_FLUSH_AT;
|
|
36
41
|
private static readonly SERVERLESS_FLUSH_INTERVAL;
|
|
37
42
|
private static readonly DEFAULT_FLUSH_AT;
|
|
38
43
|
private static readonly DEFAULT_FLUSH_INTERVAL;
|
|
39
|
-
constructor(config
|
|
44
|
+
constructor(config?: PosthogExporterConfig);
|
|
40
45
|
private buildClientConfig;
|
|
41
|
-
|
|
42
|
-
protected
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
protected skipBuildRootTask: boolean;
|
|
47
|
+
protected _buildRoot(_args: {
|
|
48
|
+
span: AnyExportedSpan;
|
|
49
|
+
traceData: PosthogTraceData;
|
|
50
|
+
}): Promise<PosthogRoot | undefined>;
|
|
51
|
+
protected skipCachingEventSpans: boolean;
|
|
52
|
+
protected _buildEvent(args: {
|
|
53
|
+
span: AnyExportedSpan;
|
|
54
|
+
traceData: PosthogTraceData;
|
|
55
|
+
}): Promise<PosthogEvent>;
|
|
56
|
+
protected _buildSpan(args: {
|
|
57
|
+
span: AnyExportedSpan;
|
|
58
|
+
traceData: PosthogTraceData;
|
|
59
|
+
}): Promise<PosthogSpan | undefined>;
|
|
60
|
+
protected skipSpanUpdateEvents: boolean;
|
|
61
|
+
protected _updateSpan(_args: {
|
|
62
|
+
span: AnyExportedSpan;
|
|
63
|
+
traceData: PosthogTraceData;
|
|
64
|
+
}): Promise<void>;
|
|
65
|
+
protected _finishSpan(args: {
|
|
66
|
+
span: AnyExportedSpan;
|
|
67
|
+
traceData: PosthogTraceData;
|
|
68
|
+
}): Promise<void>;
|
|
69
|
+
protected _abortSpan(args: {
|
|
70
|
+
span: PosthogSpan;
|
|
71
|
+
reason: SpanErrorInfo;
|
|
72
|
+
traceData: PosthogTraceData;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
private buildEventMessage;
|
|
45
75
|
/**
|
|
46
76
|
* Capture an explicit $ai_trace event for root spans.
|
|
47
77
|
* This gives us control over trace-level metadata like name and tags,
|
|
48
78
|
* rather than relying on PostHog's pseudo-trace auto-creation.
|
|
49
79
|
*/
|
|
50
|
-
private
|
|
51
|
-
private
|
|
52
|
-
shutdown(): Promise<void>;
|
|
80
|
+
private buildRootEventMessage;
|
|
81
|
+
private buildChildEventMessage;
|
|
53
82
|
private toDate;
|
|
54
83
|
private mapToPostHogEvent;
|
|
55
84
|
private getDistinctId;
|
|
@@ -68,5 +97,7 @@ export declare class PosthogExporter extends BaseExporter {
|
|
|
68
97
|
private isMessageArray;
|
|
69
98
|
private normalizeMessage;
|
|
70
99
|
private safeStringify;
|
|
100
|
+
_postShutdown(): Promise<void>;
|
|
71
101
|
}
|
|
102
|
+
export {};
|
|
72
103
|
//# sourceMappingURL=tracing.d.ts.map
|
package/dist/tracing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/posthog",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.12",
|
|
4
4
|
"description": "PostHog observability provider for Mastra",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"posthog-node": "^4.0.1",
|
|
28
|
-
"@mastra/observability": "1.0.0-beta.
|
|
28
|
+
"@mastra/observability": "1.0.0-beta.11"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^20.19.0",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"typescript": "^5.9.3",
|
|
35
35
|
"vitest": "^3.2.4",
|
|
36
36
|
"@internal/lint": "0.0.53",
|
|
37
|
-
"@
|
|
37
|
+
"@observability/test-utils": "0.0.1",
|
|
38
|
+
"@mastra/core": "1.0.0-beta.22",
|
|
38
39
|
"@internal/types-builder": "0.0.28"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|