@mastra/posthog 1.0.0-beta.11 → 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 +25 -1
- package/dist/index.cjs +80 -109
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +81 -110
- package/dist/index.js.map +1 -1
- package/dist/tracing.d.ts +44 -15
- package/dist/tracing.d.ts.map +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
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
|
+
|
|
3
27
|
## 1.0.0-beta.11
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -16,7 +40,7 @@
|
|
|
16
40
|
- SigNoz: `SIGNOZ_API_KEY`, `SIGNOZ_REGION`, `SIGNOZ_ENDPOINT`
|
|
17
41
|
- New Relic: `NEW_RELIC_LICENSE_KEY`, `NEW_RELIC_ENDPOINT`
|
|
18
42
|
- Traceloop: `TRACELOOP_API_KEY`, `TRACELOOP_DESTINATION_ID`, `TRACELOOP_ENDPOINT`
|
|
19
|
-
- Laminar: `LMNR_PROJECT_API_KEY`, `LAMINAR_ENDPOINT
|
|
43
|
+
- Laminar: `LMNR_PROJECT_API_KEY`, `LAMINAR_ENDPOINT`
|
|
20
44
|
|
|
21
45
|
Example usage:
|
|
22
46
|
|
package/dist/index.cjs
CHANGED
|
@@ -15,28 +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
26
|
constructor(config = {}) {
|
|
28
|
-
super(config);
|
|
29
27
|
const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;
|
|
28
|
+
super({ ...config, apiKey });
|
|
30
29
|
if (!apiKey) {
|
|
31
30
|
this.setDisabled("Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.");
|
|
32
|
-
this.client = null;
|
|
33
|
-
this.config = config;
|
|
34
31
|
return;
|
|
35
32
|
}
|
|
36
|
-
this.config = { ...config, apiKey };
|
|
37
33
|
const clientConfig = this.buildClientConfig(this.config);
|
|
38
|
-
this
|
|
39
|
-
|
|
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);
|
|
40
37
|
}
|
|
41
38
|
buildClientConfig(config) {
|
|
42
39
|
const isServerless = config.serverless ?? false;
|
|
@@ -44,7 +41,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
44
41
|
const flushInterval = config.flushInterval ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_INTERVAL : _PosthogExporter.DEFAULT_FLUSH_INTERVAL);
|
|
45
42
|
const host = config.host || process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
46
43
|
if (!config.host && !process.env.POSTHOG_HOST) {
|
|
47
|
-
this.logger.
|
|
44
|
+
this.logger.info(
|
|
48
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.'
|
|
49
46
|
);
|
|
50
47
|
}
|
|
@@ -55,85 +52,59 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
55
52
|
privacyMode: config.enablePrivacyMode
|
|
56
53
|
};
|
|
57
54
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
skipBuildRootTask = true;
|
|
56
|
+
async _buildRoot(_args) {
|
|
57
|
+
throw new Error("Method not implemented.");
|
|
61
58
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
switch (event.type) {
|
|
74
|
-
case "span_started":
|
|
75
|
-
await this.handleSpanStarted(event.exportedSpan);
|
|
76
|
-
break;
|
|
77
|
-
case "span_updated":
|
|
78
|
-
break;
|
|
79
|
-
case "span_ended":
|
|
80
|
-
await this.handleSpanEnded(event.exportedSpan);
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
} catch (error) {
|
|
84
|
-
this.logger.error("PostHog exporter error", { error, event });
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async handleSpanStarted(span) {
|
|
88
|
-
let traceData = this.traceMap.get(span.traceId);
|
|
89
|
-
if (!traceData) {
|
|
90
|
-
traceData = {
|
|
91
|
-
spans: /* @__PURE__ */ new Map(),
|
|
92
|
-
distinctId: void 0
|
|
93
|
-
};
|
|
94
|
-
this.traceMap.set(span.traceId, traceData);
|
|
95
|
-
}
|
|
96
|
-
traceData.spans.set(span.id, {
|
|
97
|
-
startTime: this.toDate(span.startTime),
|
|
98
|
-
type: span.type,
|
|
99
|
-
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()
|
|
100
70
|
});
|
|
101
|
-
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
async _buildSpan(args) {
|
|
74
|
+
const { span, traceData } = args;
|
|
75
|
+
if (!traceData.hasExtraValue(DISTINCT_ID)) {
|
|
102
76
|
const userId = span.metadata?.userId;
|
|
103
77
|
if (userId) {
|
|
104
|
-
traceData.
|
|
78
|
+
traceData.setExtraValue(DISTINCT_ID, String(userId));
|
|
105
79
|
}
|
|
106
80
|
}
|
|
81
|
+
return span;
|
|
107
82
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
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;
|
|
118
102
|
const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();
|
|
119
|
-
const latency = (endTime - startTime) / 1e3;
|
|
120
103
|
const distinctId = this.getDistinctId(span, traceData);
|
|
121
104
|
if (span.isRootSpan) {
|
|
122
|
-
this.
|
|
105
|
+
return this.buildRootEventMessage({ span, distinctId, endTime });
|
|
123
106
|
} else {
|
|
124
|
-
|
|
125
|
-
const parentIsRootSpan = this.isParentRootSpan(span, traceData);
|
|
126
|
-
const properties = this.buildEventProperties(span, latency, parentIsRootSpan);
|
|
127
|
-
this.client?.capture({
|
|
128
|
-
distinctId,
|
|
129
|
-
event: eventName,
|
|
130
|
-
properties,
|
|
131
|
-
timestamp: new Date(endTime)
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
traceData.spans.delete(span.id);
|
|
135
|
-
if (traceData.spans.size === 0) {
|
|
136
|
-
this.traceMap.delete(span.traceId);
|
|
107
|
+
return this.buildChildEventMessage({ span, distinctId, endTime, traceData });
|
|
137
108
|
}
|
|
138
109
|
}
|
|
139
110
|
/**
|
|
@@ -141,7 +112,8 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
141
112
|
* This gives us control over trace-level metadata like name and tags,
|
|
142
113
|
* rather than relying on PostHog's pseudo-trace auto-creation.
|
|
143
114
|
*/
|
|
144
|
-
|
|
115
|
+
buildRootEventMessage(args) {
|
|
116
|
+
const { span, distinctId, endTime } = args;
|
|
145
117
|
const traceProperties = {
|
|
146
118
|
$ai_trace_id: span.traceId,
|
|
147
119
|
$ai_span_name: span.name,
|
|
@@ -170,32 +142,26 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
170
142
|
}
|
|
171
143
|
const { userId, sessionId, ...customMetadata } = span.metadata ?? {};
|
|
172
144
|
Object.assign(traceProperties, customMetadata);
|
|
173
|
-
|
|
145
|
+
return {
|
|
174
146
|
distinctId,
|
|
175
147
|
event: "$ai_trace",
|
|
176
148
|
properties: traceProperties,
|
|
177
149
|
timestamp: new Date(endTime)
|
|
178
|
-
}
|
|
150
|
+
};
|
|
179
151
|
}
|
|
180
|
-
|
|
152
|
+
buildChildEventMessage(args) {
|
|
153
|
+
const { span, distinctId, endTime, traceData } = args;
|
|
181
154
|
const eventName = this.mapToPostHogEvent(span.type);
|
|
182
|
-
const
|
|
183
|
-
const
|
|
184
|
-
const
|
|
185
|
-
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 {
|
|
186
160
|
distinctId,
|
|
187
161
|
event: eventName,
|
|
188
162
|
properties,
|
|
189
|
-
timestamp:
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
async shutdown() {
|
|
193
|
-
if (this.client) {
|
|
194
|
-
await this.client.shutdown();
|
|
195
|
-
}
|
|
196
|
-
this.traceMap.clear();
|
|
197
|
-
await super.shutdown();
|
|
198
|
-
this.logger.info("PostHog exporter shutdown complete");
|
|
163
|
+
timestamp: new Date(endTime)
|
|
164
|
+
};
|
|
199
165
|
}
|
|
200
166
|
toDate(timestamp) {
|
|
201
167
|
return timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
@@ -210,8 +176,8 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
210
176
|
if (span.metadata?.userId) {
|
|
211
177
|
return String(span.metadata.userId);
|
|
212
178
|
}
|
|
213
|
-
if (traceData?.
|
|
214
|
-
return traceData.
|
|
179
|
+
if (traceData?.hasExtraValue(DISTINCT_ID)) {
|
|
180
|
+
return String(traceData.getExtraValue(DISTINCT_ID));
|
|
215
181
|
}
|
|
216
182
|
if (this.config.defaultDistinctId) {
|
|
217
183
|
return this.config.defaultDistinctId;
|
|
@@ -227,7 +193,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
227
193
|
if (!span.parentSpanId) {
|
|
228
194
|
return false;
|
|
229
195
|
}
|
|
230
|
-
const parentCache = traceData.
|
|
196
|
+
const parentCache = traceData.getSpan({ spanId: span.parentSpanId });
|
|
231
197
|
if (parentCache) {
|
|
232
198
|
return parentCache.isRootSpan;
|
|
233
199
|
}
|
|
@@ -259,18 +225,18 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
259
225
|
return { ...baseProperties, ...this.buildSpanProperties(span) };
|
|
260
226
|
}
|
|
261
227
|
}
|
|
262
|
-
extractErrorProperties(
|
|
263
|
-
if (!
|
|
228
|
+
extractErrorProperties(errorInfo) {
|
|
229
|
+
if (!errorInfo) {
|
|
264
230
|
return {};
|
|
265
231
|
}
|
|
266
232
|
const props = {
|
|
267
|
-
error_message:
|
|
233
|
+
error_message: errorInfo.message
|
|
268
234
|
};
|
|
269
|
-
if (
|
|
270
|
-
props.error_id =
|
|
235
|
+
if (errorInfo.id) {
|
|
236
|
+
props.error_id = errorInfo.id;
|
|
271
237
|
}
|
|
272
|
-
if (
|
|
273
|
-
props.error_category =
|
|
238
|
+
if (errorInfo.category) {
|
|
239
|
+
props.error_category = errorInfo.category;
|
|
274
240
|
}
|
|
275
241
|
return props;
|
|
276
242
|
}
|
|
@@ -291,7 +257,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
291
257
|
if (attrs.parameters.maxOutputTokens !== void 0) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;
|
|
292
258
|
}
|
|
293
259
|
if (attrs.streaming !== void 0) props.$ai_stream = attrs.streaming;
|
|
294
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
260
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
295
261
|
}
|
|
296
262
|
buildSpanProperties(span) {
|
|
297
263
|
const props = {};
|
|
@@ -305,7 +271,7 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
305
271
|
if (span.attributes) {
|
|
306
272
|
Object.assign(props, span.attributes);
|
|
307
273
|
}
|
|
308
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
274
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
309
275
|
}
|
|
310
276
|
formatMessages(data, defaultRole = "user") {
|
|
311
277
|
if (this.isMessageArray(data)) {
|
|
@@ -344,6 +310,11 @@ var PosthogExporter = class _PosthogExporter extends observability.BaseExporter
|
|
|
344
310
|
return String(data);
|
|
345
311
|
}
|
|
346
312
|
}
|
|
313
|
+
async _postShutdown() {
|
|
314
|
+
if (this.#client) {
|
|
315
|
+
await this.#client.shutdown();
|
|
316
|
+
}
|
|
317
|
+
}
|
|
347
318
|
};
|
|
348
319
|
|
|
349
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 /** 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 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 | null;\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\n // Read API key from config or environment variable\n const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;\n\n if (!apiKey) {\n this.setDisabled('Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.');\n this.client = null;\n this.config = config;\n return;\n }\n\n this.config = { ...config, apiKey };\n const clientConfig = this.buildClientConfig(this.config);\n this.client = new PostHog(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,28 +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
24
|
constructor(config = {}) {
|
|
26
|
-
super(config);
|
|
27
25
|
const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;
|
|
26
|
+
super({ ...config, apiKey });
|
|
28
27
|
if (!apiKey) {
|
|
29
28
|
this.setDisabled("Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.");
|
|
30
|
-
this.client = null;
|
|
31
|
-
this.config = config;
|
|
32
29
|
return;
|
|
33
30
|
}
|
|
34
|
-
this.config = { ...config, apiKey };
|
|
35
31
|
const clientConfig = this.buildClientConfig(this.config);
|
|
36
|
-
this
|
|
37
|
-
|
|
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);
|
|
38
35
|
}
|
|
39
36
|
buildClientConfig(config) {
|
|
40
37
|
const isServerless = config.serverless ?? false;
|
|
@@ -42,7 +39,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
42
39
|
const flushInterval = config.flushInterval ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_INTERVAL : _PosthogExporter.DEFAULT_FLUSH_INTERVAL);
|
|
43
40
|
const host = config.host || process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
44
41
|
if (!config.host && !process.env.POSTHOG_HOST) {
|
|
45
|
-
this.logger.
|
|
42
|
+
this.logger.info(
|
|
46
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.'
|
|
47
44
|
);
|
|
48
45
|
}
|
|
@@ -53,85 +50,59 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
53
50
|
privacyMode: config.enablePrivacyMode
|
|
54
51
|
};
|
|
55
52
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
skipBuildRootTask = true;
|
|
54
|
+
async _buildRoot(_args) {
|
|
55
|
+
throw new Error("Method not implemented.");
|
|
59
56
|
}
|
|
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
|
|
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()
|
|
98
68
|
});
|
|
99
|
-
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
async _buildSpan(args) {
|
|
72
|
+
const { span, traceData } = args;
|
|
73
|
+
if (!traceData.hasExtraValue(DISTINCT_ID)) {
|
|
100
74
|
const userId = span.metadata?.userId;
|
|
101
75
|
if (userId) {
|
|
102
|
-
traceData.
|
|
76
|
+
traceData.setExtraValue(DISTINCT_ID, String(userId));
|
|
103
77
|
}
|
|
104
78
|
}
|
|
79
|
+
return span;
|
|
105
80
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
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;
|
|
116
100
|
const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();
|
|
117
|
-
const latency = (endTime - startTime) / 1e3;
|
|
118
101
|
const distinctId = this.getDistinctId(span, traceData);
|
|
119
102
|
if (span.isRootSpan) {
|
|
120
|
-
this.
|
|
103
|
+
return this.buildRootEventMessage({ span, distinctId, endTime });
|
|
121
104
|
} 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);
|
|
105
|
+
return this.buildChildEventMessage({ span, distinctId, endTime, traceData });
|
|
135
106
|
}
|
|
136
107
|
}
|
|
137
108
|
/**
|
|
@@ -139,7 +110,8 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
139
110
|
* This gives us control over trace-level metadata like name and tags,
|
|
140
111
|
* rather than relying on PostHog's pseudo-trace auto-creation.
|
|
141
112
|
*/
|
|
142
|
-
|
|
113
|
+
buildRootEventMessage(args) {
|
|
114
|
+
const { span, distinctId, endTime } = args;
|
|
143
115
|
const traceProperties = {
|
|
144
116
|
$ai_trace_id: span.traceId,
|
|
145
117
|
$ai_span_name: span.name,
|
|
@@ -168,32 +140,26 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
168
140
|
}
|
|
169
141
|
const { userId, sessionId, ...customMetadata } = span.metadata ?? {};
|
|
170
142
|
Object.assign(traceProperties, customMetadata);
|
|
171
|
-
|
|
143
|
+
return {
|
|
172
144
|
distinctId,
|
|
173
145
|
event: "$ai_trace",
|
|
174
146
|
properties: traceProperties,
|
|
175
147
|
timestamp: new Date(endTime)
|
|
176
|
-
}
|
|
148
|
+
};
|
|
177
149
|
}
|
|
178
|
-
|
|
150
|
+
buildChildEventMessage(args) {
|
|
151
|
+
const { span, distinctId, endTime, traceData } = args;
|
|
179
152
|
const eventName = this.mapToPostHogEvent(span.type);
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
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 {
|
|
184
158
|
distinctId,
|
|
185
159
|
event: eventName,
|
|
186
160
|
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");
|
|
161
|
+
timestamp: new Date(endTime)
|
|
162
|
+
};
|
|
197
163
|
}
|
|
198
164
|
toDate(timestamp) {
|
|
199
165
|
return timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
@@ -208,8 +174,8 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
208
174
|
if (span.metadata?.userId) {
|
|
209
175
|
return String(span.metadata.userId);
|
|
210
176
|
}
|
|
211
|
-
if (traceData?.
|
|
212
|
-
return traceData.
|
|
177
|
+
if (traceData?.hasExtraValue(DISTINCT_ID)) {
|
|
178
|
+
return String(traceData.getExtraValue(DISTINCT_ID));
|
|
213
179
|
}
|
|
214
180
|
if (this.config.defaultDistinctId) {
|
|
215
181
|
return this.config.defaultDistinctId;
|
|
@@ -225,7 +191,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
225
191
|
if (!span.parentSpanId) {
|
|
226
192
|
return false;
|
|
227
193
|
}
|
|
228
|
-
const parentCache = traceData.
|
|
194
|
+
const parentCache = traceData.getSpan({ spanId: span.parentSpanId });
|
|
229
195
|
if (parentCache) {
|
|
230
196
|
return parentCache.isRootSpan;
|
|
231
197
|
}
|
|
@@ -257,18 +223,18 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
257
223
|
return { ...baseProperties, ...this.buildSpanProperties(span) };
|
|
258
224
|
}
|
|
259
225
|
}
|
|
260
|
-
extractErrorProperties(
|
|
261
|
-
if (!
|
|
226
|
+
extractErrorProperties(errorInfo) {
|
|
227
|
+
if (!errorInfo) {
|
|
262
228
|
return {};
|
|
263
229
|
}
|
|
264
230
|
const props = {
|
|
265
|
-
error_message:
|
|
231
|
+
error_message: errorInfo.message
|
|
266
232
|
};
|
|
267
|
-
if (
|
|
268
|
-
props.error_id =
|
|
233
|
+
if (errorInfo.id) {
|
|
234
|
+
props.error_id = errorInfo.id;
|
|
269
235
|
}
|
|
270
|
-
if (
|
|
271
|
-
props.error_category =
|
|
236
|
+
if (errorInfo.category) {
|
|
237
|
+
props.error_category = errorInfo.category;
|
|
272
238
|
}
|
|
273
239
|
return props;
|
|
274
240
|
}
|
|
@@ -289,7 +255,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
289
255
|
if (attrs.parameters.maxOutputTokens !== void 0) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;
|
|
290
256
|
}
|
|
291
257
|
if (attrs.streaming !== void 0) props.$ai_stream = attrs.streaming;
|
|
292
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
258
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
293
259
|
}
|
|
294
260
|
buildSpanProperties(span) {
|
|
295
261
|
const props = {};
|
|
@@ -303,7 +269,7 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
303
269
|
if (span.attributes) {
|
|
304
270
|
Object.assign(props, span.attributes);
|
|
305
271
|
}
|
|
306
|
-
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
272
|
+
return { ...props, ...this.extractErrorProperties(span.errorInfo), ...this.extractCustomMetadata(span) };
|
|
307
273
|
}
|
|
308
274
|
formatMessages(data, defaultRole = "user") {
|
|
309
275
|
if (this.isMessageArray(data)) {
|
|
@@ -342,6 +308,11 @@ var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
|
342
308
|
return String(data);
|
|
343
309
|
}
|
|
344
310
|
}
|
|
311
|
+
async _postShutdown() {
|
|
312
|
+
if (this.#client) {
|
|
313
|
+
await this.#client.shutdown();
|
|
314
|
+
}
|
|
315
|
+
}
|
|
345
316
|
};
|
|
346
317
|
|
|
347
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 /** 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 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 | null;\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\n // Read API key from config or environment variable\n const apiKey = config.apiKey ?? process.env.POSTHOG_API_KEY;\n\n if (!apiKey) {\n this.setDisabled('Missing required API key. Set POSTHOG_API_KEY environment variable or pass apiKey in config.');\n this.client = null;\n this.config = config;\n return;\n }\n\n this.config = { ...config, apiKey };\n const clientConfig = this.buildClientConfig(this.config);\n this.client = new PostHog(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":"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","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,7 +18,7 @@ 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
|
|
21
|
+
export interface PosthogExporterConfig extends TrackingExporterConfig {
|
|
22
22
|
/** PostHog API key. Defaults to POSTHOG_API_KEY environment variable. */
|
|
23
23
|
apiKey?: string;
|
|
24
24
|
/** PostHog host URL. Defaults to POSTHOG_HOST environment variable or US region. */
|
|
@@ -29,29 +29,56 @@ export interface PosthogExporterConfig extends BaseExporterConfig {
|
|
|
29
29
|
defaultDistinctId?: string;
|
|
30
30
|
enablePrivacyMode?: boolean;
|
|
31
31
|
}
|
|
32
|
-
|
|
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;
|
|
33
39
|
name: string;
|
|
34
|
-
private client;
|
|
35
|
-
private config;
|
|
36
|
-
private traceMap;
|
|
37
40
|
private static readonly SERVERLESS_FLUSH_AT;
|
|
38
41
|
private static readonly SERVERLESS_FLUSH_INTERVAL;
|
|
39
42
|
private static readonly DEFAULT_FLUSH_AT;
|
|
40
43
|
private static readonly DEFAULT_FLUSH_INTERVAL;
|
|
41
44
|
constructor(config?: PosthogExporterConfig);
|
|
42
45
|
private buildClientConfig;
|
|
43
|
-
|
|
44
|
-
protected
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
|
47
75
|
/**
|
|
48
76
|
* Capture an explicit $ai_trace event for root spans.
|
|
49
77
|
* This gives us control over trace-level metadata like name and tags,
|
|
50
78
|
* rather than relying on PostHog's pseudo-trace auto-creation.
|
|
51
79
|
*/
|
|
52
|
-
private
|
|
53
|
-
private
|
|
54
|
-
shutdown(): Promise<void>;
|
|
80
|
+
private buildRootEventMessage;
|
|
81
|
+
private buildChildEventMessage;
|
|
55
82
|
private toDate;
|
|
56
83
|
private mapToPostHogEvent;
|
|
57
84
|
private getDistinctId;
|
|
@@ -70,5 +97,7 @@ export declare class PosthogExporter extends BaseExporter {
|
|
|
70
97
|
private isMessageArray;
|
|
71
98
|
private normalizeMessage;
|
|
72
99
|
private safeStringify;
|
|
100
|
+
_postShutdown(): Promise<void>;
|
|
73
101
|
}
|
|
102
|
+
export {};
|
|
74
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": {
|