@mastra/posthog 0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939
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 +44 -0
- package/LICENSE.md +15 -0
- package/README.md +164 -0
- package/dist/index.cjs +292 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +290 -0
- package/dist/index.js.map +1 -0
- package/dist/tracing.d.ts +43 -0
- package/dist/tracing.d.ts.map +1 -0
- package/package.json +63 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @mastra/posthog
|
|
2
|
+
|
|
3
|
+
## 0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add PostHog AI observability exporter ([#10393](https://github.com/mastra-ai/mastra/pull/10393))
|
|
8
|
+
|
|
9
|
+
Adds a new PostHog exporter for AI tracing that sends spans to PostHog's LLM Analytics platform as structured events ($ai_generation and $ai_span). Features include:
|
|
10
|
+
- Event-based tracing architecture optimized for PostHog's AI analytics
|
|
11
|
+
- Support for privacy mode to exclude sensitive input/output data
|
|
12
|
+
- Serverless optimization with auto-configured batching
|
|
13
|
+
- Token usage normalization for AI SDK v4 and v5 formats
|
|
14
|
+
- Message format transformation for PostHog's strict API requirements
|
|
15
|
+
- 4-tier distinct ID resolution for user identification
|
|
16
|
+
- MODEL_CHUNK streaming event support
|
|
17
|
+
- Regional deployment support (US/EU/self-hosted)
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { Mastra } from '@mastra/core';
|
|
21
|
+
import { Observability } from '@mastra/observability';
|
|
22
|
+
import { PosthogExporter } from '@mastra/posthog';
|
|
23
|
+
|
|
24
|
+
const posthogExporter = new PosthogExporter({
|
|
25
|
+
apiKey: process.env.POSTHOG_API_KEY!,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const mastra = new Mastra({
|
|
29
|
+
observability: new Observability({
|
|
30
|
+
configs: {
|
|
31
|
+
posthog: {
|
|
32
|
+
serviceName: 'my-app',
|
|
33
|
+
exporters: [posthogExporter],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- Updated dependencies [[`2319326`](https://github.com/mastra-ai/mastra/commit/2319326f8c64e503a09bbcf14be2dd65405445e0), [`39c9743`](https://github.com/mastra-ai/mastra/commit/39c97432d084294f8ba85fbf3ef28098ff21459e), [`f743dbb`](https://github.com/mastra-ai/mastra/commit/f743dbb8b40d1627b5c10c0e6fc154f4ebb6e394), [`fec5129`](https://github.com/mastra-ai/mastra/commit/fec5129de7fc64423ea03661a56cef31dc747a0d), [`0491e7c`](https://github.com/mastra-ai/mastra/commit/0491e7c9b714cb0ba22187ee062147ec2dd7c712), [`f6f4903`](https://github.com/mastra-ai/mastra/commit/f6f4903397314f73362061dc5a3e8e7c61ea34aa), [`0e8ed46`](https://github.com/mastra-ai/mastra/commit/0e8ed467c54d6901a6a365f270ec15d6faadb36c), [`6c049d9`](https://github.com/mastra-ai/mastra/commit/6c049d94063fdcbd5b81c4912a2bf82a92c9cc0b), [`910db9e`](https://github.com/mastra-ai/mastra/commit/910db9e0312888495eb5617b567f247d03303814), [`2f897df`](https://github.com/mastra-ai/mastra/commit/2f897df208508f46f51b7625e5dd20c37f93e0e3), [`d629361`](https://github.com/mastra-ai/mastra/commit/d629361a60f6565b5bfb11976fdaf7308af858e2), [`feb7ee4`](https://github.com/mastra-ai/mastra/commit/feb7ee4d09a75edb46c6669a3beaceec78811747), [`08c31c1`](https://github.com/mastra-ai/mastra/commit/08c31c188ebccd598acaf55e888b6397d01f7eae), [`3443770`](https://github.com/mastra-ai/mastra/commit/3443770662df8eb24c9df3589b2792d78cfcb811), [`f0a07e0`](https://github.com/mastra-ai/mastra/commit/f0a07e0111b3307c5fabfa4094c5c2cfb734fbe6), [`aaa40e7`](https://github.com/mastra-ai/mastra/commit/aaa40e788628b319baa8e889407d11ad626547fa), [`1521d71`](https://github.com/mastra-ai/mastra/commit/1521d716e5daedc74690c983fbd961123c56756b), [`9e1911d`](https://github.com/mastra-ai/mastra/commit/9e1911db2b4db85e0e768c3f15e0d61e319869f6), [`c456e01`](https://github.com/mastra-ai/mastra/commit/c456e0149e3c176afcefdbd9bb1d2c5917723725), [`ebac155`](https://github.com/mastra-ai/mastra/commit/ebac15564a590117db7078233f927a7e28a85106), [`dd1c38d`](https://github.com/mastra-ai/mastra/commit/dd1c38d1b75f1b695c27b40d8d9d6ed00d5e0f6f), [`5948e6a`](https://github.com/mastra-ai/mastra/commit/5948e6a5146c83666ba3f294b2be576c82a513fb), [`83b08dc`](https://github.com/mastra-ai/mastra/commit/83b08dcf1bfcc915efab23c09207df90fa247908), [`8940859`](https://github.com/mastra-ai/mastra/commit/89408593658199b4ad67f7b65e888f344e64a442), [`f0f8f12`](https://github.com/mastra-ai/mastra/commit/f0f8f125c308f2d0fd36942ef652fd852df7522f), [`e629310`](https://github.com/mastra-ai/mastra/commit/e629310f1a73fa236d49ec7a1d1cceb6229dc7cc), [`4c6b492`](https://github.com/mastra-ai/mastra/commit/4c6b492c4dd591c6a592520c1f6855d6e936d71f), [`dff01d8`](https://github.com/mastra-ai/mastra/commit/dff01d81ce1f4e4087cfac20fa868e6db138dd14), [`9d819d5`](https://github.com/mastra-ai/mastra/commit/9d819d54b61481639f4008e4694791bddf187edd), [`a64d16a`](https://github.com/mastra-ai/mastra/commit/a64d16aedafe57ee5707bdcc25f96e07fa1a0233), [`fd3d338`](https://github.com/mastra-ai/mastra/commit/fd3d338a2c362174ed5b383f1f011ad9fb0302aa), [`71c8d6c`](https://github.com/mastra-ai/mastra/commit/71c8d6c161253207b2b9588bdadb7eed604f7253), [`6179a9b`](https://github.com/mastra-ai/mastra/commit/6179a9ba36ffac326de3cc3c43cdc8028d37c251), [`c30400a`](https://github.com/mastra-ai/mastra/commit/c30400a49b994b1b97256fe785eb6c906fc2b232), [`00f4921`](https://github.com/mastra-ai/mastra/commit/00f4921dd2c91a1e5446799599ef7116a8214a1a), [`ca8041c`](https://github.com/mastra-ai/mastra/commit/ca8041cce0379fda22ed293a565bcb5b6ddca68a), [`7051bf3`](https://github.com/mastra-ai/mastra/commit/7051bf38b3b122a069008f861f7bfc004a6d9f6e), [`a8f1494`](https://github.com/mastra-ai/mastra/commit/a8f1494f4bbdc2770bcf327d4c7d869e332183f1), [`69e0a87`](https://github.com/mastra-ai/mastra/commit/69e0a878896a2da9494945d86e056a5f8f05b851), [`352a5d6`](https://github.com/mastra-ai/mastra/commit/352a5d625cfe09849b21e8f52a24c9f0366759d5), [`898a972`](https://github.com/mastra-ai/mastra/commit/898a9727d286c2510d6b702dfd367e6aaf5c6b0f), [`0793497`](https://github.com/mastra-ai/mastra/commit/079349753620c40246ffd673e3f9d7d9820beff3), [`a97003a`](https://github.com/mastra-ai/mastra/commit/a97003aa1cf2f4022a41912324a1e77263b326b8), [`01f8878`](https://github.com/mastra-ai/mastra/commit/01f88783de25e4de048c1c8aace43e26373c6ea5), [`5df9cce`](https://github.com/mastra-ai/mastra/commit/5df9cce1a753438413f64c11eeef8f845745c2a8), [`4c77209`](https://github.com/mastra-ai/mastra/commit/4c77209e6c11678808b365d545845918c40045c8), [`a854ede`](https://github.com/mastra-ai/mastra/commit/a854ede62bf5ac0945a624ac48913dd69c73aabf), [`c576fc0`](https://github.com/mastra-ai/mastra/commit/c576fc0b100b2085afded91a37c97a0ea0ec09c7), [`3defc80`](https://github.com/mastra-ai/mastra/commit/3defc80cf2b88a1b7fc1cc4ddcb91e982a614609), [`f111eac`](https://github.com/mastra-ai/mastra/commit/f111eac5de509b2e5fccfc1882e7f74cda264c74), [`00123ba`](https://github.com/mastra-ai/mastra/commit/00123ba96dc9e5cd0b110420ebdba56d8f237b25), [`16153fe`](https://github.com/mastra-ai/mastra/commit/16153fe7eb13c99401f48e6ca32707c965ee28b9), [`9f4a683`](https://github.com/mastra-ai/mastra/commit/9f4a6833e88b52574665c028fd5508ad5c2f6004), [`bc94344`](https://github.com/mastra-ai/mastra/commit/bc943444a1342d8a662151b7bce1df7dae32f59c), [`57d157f`](https://github.com/mastra-ai/mastra/commit/57d157f0b163a95c3e6c9eae31bdb11d1bfc64f9), [`903f67d`](https://github.com/mastra-ai/mastra/commit/903f67d184504a273893818c02b961f5423a79ad), [`d827d08`](https://github.com/mastra-ai/mastra/commit/d827d0808ffe1f3553a84e975806cc989b9735dd), [`2a90c55`](https://github.com/mastra-ai/mastra/commit/2a90c55a86a9210697d5adaab5ee94584b079adc), [`eb09742`](https://github.com/mastra-ai/mastra/commit/eb09742197f66c4c38154c3beec78313e69760b2), [`23c10a1`](https://github.com/mastra-ai/mastra/commit/23c10a1efdd9a693c405511ab2dc8a1236603162), [`96d35f6`](https://github.com/mastra-ai/mastra/commit/96d35f61376bc2b1bf148648a2c1985bd51bef55), [`5cbe88a`](https://github.com/mastra-ai/mastra/commit/5cbe88aefbd9f933bca669fd371ea36bf939ac6d), [`a1bd7b8`](https://github.com/mastra-ai/mastra/commit/a1bd7b8571db16b94eb01588f451a74758c96d65), [`d78b38d`](https://github.com/mastra-ai/mastra/commit/d78b38d898fce285260d3bbb4befade54331617f), [`a0a5b4b`](https://github.com/mastra-ai/mastra/commit/a0a5b4bbebe6c701ebbadf744873aa0d5ca01371), [`0633100`](https://github.com/mastra-ai/mastra/commit/0633100a911ad22f5256471bdf753da21c104742), [`c710c16`](https://github.com/mastra-ai/mastra/commit/c710c1652dccfdc4111c8412bca7a6bb1d48b441), [`354ad0b`](https://github.com/mastra-ai/mastra/commit/354ad0b7b1b8183ac567f236a884fc7ede6d7138), [`cfae733`](https://github.com/mastra-ai/mastra/commit/cfae73394f4920635e6c919c8e95ff9a0788e2e5), [`e3dfda7`](https://github.com/mastra-ai/mastra/commit/e3dfda7b11bf3b8c4bb55637028befb5f387fc74), [`69ea758`](https://github.com/mastra-ai/mastra/commit/69ea758358edd7117f191c2e69c8bb5fc79e7a1a), [`651e772`](https://github.com/mastra-ai/mastra/commit/651e772eb1475fb13e126d3fcc01751297a88214), [`993ad98`](https://github.com/mastra-ai/mastra/commit/993ad98d7ad3bebda9ecef5fec5c94349a0d04bc), [`676ccc7`](https://github.com/mastra-ai/mastra/commit/676ccc7fe92468d2d45d39c31a87825c89fd1ea0), [`3ff2c17`](https://github.com/mastra-ai/mastra/commit/3ff2c17a58e312fad5ea37377262c12d92ca0908), [`844ea5d`](https://github.com/mastra-ai/mastra/commit/844ea5dc0c248961e7bf73629ae7dcff503e853c), [`398fde3`](https://github.com/mastra-ai/mastra/commit/398fde3f39e707cda79372cdae8f9870e3b57c8d), [`c10398d`](https://github.com/mastra-ai/mastra/commit/c10398d5b88f1d4af556f4267ff06f1d11e89179), [`f0f8f12`](https://github.com/mastra-ai/mastra/commit/f0f8f125c308f2d0fd36942ef652fd852df7522f), [`b61b93f`](https://github.com/mastra-ai/mastra/commit/b61b93f9e058b11dd2eec169853175d31dbdd567), [`bae33d9`](https://github.com/mastra-ai/mastra/commit/bae33d91a63fbb64d1e80519e1fc1acaed1e9013), [`0d7618b`](https://github.com/mastra-ai/mastra/commit/0d7618bc650bf2800934b243eca5648f4aeed9c2), [`7b763e5`](https://github.com/mastra-ai/mastra/commit/7b763e52fc3eaf699c2a99f2adf418dd46e4e9a5), [`d36cfbb`](https://github.com/mastra-ai/mastra/commit/d36cfbbb6565ba5f827883cc9bb648eb14befdc1), [`3697853`](https://github.com/mastra-ai/mastra/commit/3697853deeb72017d90e0f38a93c1e29221aeca0), [`b2e45ec`](https://github.com/mastra-ai/mastra/commit/b2e45eca727a8db01a81ba93f1a5219c7183c839), [`43ca8f2`](https://github.com/mastra-ai/mastra/commit/43ca8f2c7334851cc7b4d3d2f037d8784bfbdd5f), [`d6d49f7`](https://github.com/mastra-ai/mastra/commit/d6d49f7b8714fa19a52ff9c7cf7fb7e73751901e), [`00c2387`](https://github.com/mastra-ai/mastra/commit/00c2387f5f04a365316f851e58666ac43f8c4edf), [`a534e95`](https://github.com/mastra-ai/mastra/commit/a534e9591f83b3cc1ebff99c67edf4cda7bf81d3), [`9d0e7fe`](https://github.com/mastra-ai/mastra/commit/9d0e7feca8ed98de959f53476ee1456073673348), [`53d927c`](https://github.com/mastra-ai/mastra/commit/53d927cc6f03bff33655b7e2b788da445a08731d), [`ad6250d`](https://github.com/mastra-ai/mastra/commit/ad6250dbdaad927e29f74a27b83f6c468b50a705), [`3f2faf2`](https://github.com/mastra-ai/mastra/commit/3f2faf2e2d685d6c053cc5af1bf9fedf267b2ce5), [`22f64bc`](https://github.com/mastra-ai/mastra/commit/22f64bc1d37149480b58bf2fefe35b79a1e3e7d5), [`3a73998`](https://github.com/mastra-ai/mastra/commit/3a73998fa4ebeb7f3dc9301afe78095fc63e7999), [`83d5942`](https://github.com/mastra-ai/mastra/commit/83d5942669ce7bba4a6ca4fd4da697a10eb5ebdc), [`b7959e6`](https://github.com/mastra-ai/mastra/commit/b7959e6e25a46b480f9ea2217c4c6c588c423791), [`bda6370`](https://github.com/mastra-ai/mastra/commit/bda637009360649aaf579919e7873e33553c273e), [`d7acd8e`](https://github.com/mastra-ai/mastra/commit/d7acd8e987b5d7eff4fd98b0906c17c06a2e83d5), [`c7f1f7d`](https://github.com/mastra-ai/mastra/commit/c7f1f7d24f61f247f018cc2d1f33bf63212959a7), [`0bddc6d`](https://github.com/mastra-ai/mastra/commit/0bddc6d8dbd6f6008c0cba2e4960a2da75a55af1), [`735d8c1`](https://github.com/mastra-ai/mastra/commit/735d8c1c0d19fbc09e6f8b66cf41bc7655993838), [`acf322e`](https://github.com/mastra-ai/mastra/commit/acf322e0f1fd0189684cf529d91c694bea918a45), [`2ca67cc`](https://github.com/mastra-ai/mastra/commit/2ca67cc3bb1f6a617353fdcab197d9efebe60d6f), [`e16d553`](https://github.com/mastra-ai/mastra/commit/e16d55338403c7553531cc568125c63d53653dff), [`c942802`](https://github.com/mastra-ai/mastra/commit/c942802a477a925b01859a7b8688d4355715caaa), [`a0c8c1b`](https://github.com/mastra-ai/mastra/commit/a0c8c1b87d4fee252aebda73e8637fbe01d761c9), [`cc34739`](https://github.com/mastra-ai/mastra/commit/cc34739c34b6266a91bea561119240a7acf47887), [`c218bd3`](https://github.com/mastra-ai/mastra/commit/c218bd3759e32423735b04843a09404572631014), [`9e67002`](https://github.com/mastra-ai/mastra/commit/9e67002b52c9be19936c420a489dbee9c5fd6a78), [`2c4438b`](https://github.com/mastra-ai/mastra/commit/2c4438b87817ab7eed818c7990fef010475af1a3), [`35edc49`](https://github.com/mastra-ai/mastra/commit/35edc49ac0556db609189641d6341e76771b81fc), [`4d59f58`](https://github.com/mastra-ai/mastra/commit/4d59f58de2d90d6e2810a19d4518e38ddddb9038), [`2b8893c`](https://github.com/mastra-ai/mastra/commit/2b8893cb108ef9acb72ee7835cd625610d2c1a4a), [`8e5c75b`](https://github.com/mastra-ai/mastra/commit/8e5c75bdb1d08a42d45309a4c72def4b6890230f), [`e1bb9c9`](https://github.com/mastra-ai/mastra/commit/e1bb9c94b4eb68b019ae275981be3feb769b5365), [`351a11f`](https://github.com/mastra-ai/mastra/commit/351a11fcaf2ed1008977fa9b9a489fc422e51cd4), [`e59e0d3`](https://github.com/mastra-ai/mastra/commit/e59e0d32afb5fcf2c9f3c00c8f81f6c21d3a63fa), [`465ac05`](https://github.com/mastra-ai/mastra/commit/465ac0526a91d175542091c675181f1a96c98c46), [`fa8409b`](https://github.com/mastra-ai/mastra/commit/fa8409bc39cfd8ba6643b9db5269b90b22e2a2f7), [`e7266a2`](https://github.com/mastra-ai/mastra/commit/e7266a278db02035c97a5e9cd9d1669a6b7a535d), [`173c535`](https://github.com/mastra-ai/mastra/commit/173c535c0645b0da404fe09f003778f0b0d4e019)]:
|
|
43
|
+
- @mastra/core@0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939
|
|
44
|
+
- @mastra/observability@0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Apache License 2.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kepler Software, Inc.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# @mastra/posthog
|
|
2
|
+
|
|
3
|
+
PostHog AI Observability exporter for Mastra applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @mastra/posthog
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { PosthogExporter } from '@mastra/posthog';
|
|
15
|
+
|
|
16
|
+
// Use with Mastra
|
|
17
|
+
const mastra = new Mastra({
|
|
18
|
+
...,
|
|
19
|
+
observability: {
|
|
20
|
+
configs: {
|
|
21
|
+
posthog: {
|
|
22
|
+
serviceName: 'service',
|
|
23
|
+
exporters: [
|
|
24
|
+
new PosthogExporter({
|
|
25
|
+
apiKey: process.env.POSTHOG_API_KEY,
|
|
26
|
+
host: 'https://us.i.posthog.com', // optional, defaults to US region
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
### AI Tracing
|
|
38
|
+
|
|
39
|
+
- **Event-based architecture**: Captures LLM calls and operations as PostHog events
|
|
40
|
+
- **LLM analytics**: Automatic tracking of token usage, latency, and costs
|
|
41
|
+
- **Streaming support**: Handles streaming LLM responses with MODEL_CHUNK events
|
|
42
|
+
- **Privacy mode**: Optional exclusion of input/output data for sensitive applications
|
|
43
|
+
- **Serverless optimized**: Auto-configures batching for serverless environments
|
|
44
|
+
|
|
45
|
+
### Supported Event Types
|
|
46
|
+
|
|
47
|
+
- `$ai_generation`: LLM model calls (MODEL_GENERATION, MODEL_STEP)
|
|
48
|
+
- `$ai_span`: Operations like tool calls, workflows, and streaming chunks
|
|
49
|
+
- Hierarchical traces with parent-child relationships via `$ai_parent_id`
|
|
50
|
+
- Session grouping with `$ai_session_id`
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
### Basic Configuration
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
new PosthogExporter({
|
|
58
|
+
apiKey: process.env.POSTHOG_API_KEY,
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Advanced Configuration
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
new PosthogExporter({
|
|
66
|
+
// Required
|
|
67
|
+
apiKey: process.env.POSTHOG_API_KEY,
|
|
68
|
+
|
|
69
|
+
// Optional: Region/Host
|
|
70
|
+
host: 'https://eu.i.posthog.com', // EU region
|
|
71
|
+
// or
|
|
72
|
+
host: 'https://your-instance.com', // Self-hosted
|
|
73
|
+
|
|
74
|
+
// Optional: Batching (defaults: flushAt=20, flushInterval=10000)
|
|
75
|
+
flushAt: 20, // Batch size before auto-flush
|
|
76
|
+
flushInterval: 10000, // Flush interval in milliseconds
|
|
77
|
+
|
|
78
|
+
// Optional: Serverless mode (auto-configures smaller batches)
|
|
79
|
+
serverless: true, // Sets flushAt=10, flushInterval=2000
|
|
80
|
+
|
|
81
|
+
// Optional: User identification
|
|
82
|
+
defaultDistinctId: 'anonymous', // Fallback if no userId in metadata
|
|
83
|
+
|
|
84
|
+
// Optional: Privacy
|
|
85
|
+
enablePrivacyMode: false, // Set to true to exclude input/output from LLM events
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Serverless Environments
|
|
90
|
+
|
|
91
|
+
When deploying to serverless environments (Lambda, Vercel Functions, etc.), enable serverless mode:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
new PosthogExporter({
|
|
95
|
+
apiKey: process.env.POSTHOG_API_KEY,
|
|
96
|
+
serverless: true, // Auto-configures for serverless
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Important**: Always call `await mastra.shutdown()` before your serverless function exits to flush remaining events.
|
|
101
|
+
|
|
102
|
+
### Privacy Mode
|
|
103
|
+
|
|
104
|
+
To exclude sensitive input/output data while still tracking token usage and latency:
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
new PosthogExporter({
|
|
108
|
+
apiKey: process.env.POSTHOG_API_KEY,
|
|
109
|
+
enablePrivacyMode: true, // Excludes $ai_input and $ai_output_choices
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Note: Privacy mode only applies to `$ai_generation` events. Span events (tool calls, etc.) still include input/output state.
|
|
114
|
+
|
|
115
|
+
## Metadata
|
|
116
|
+
|
|
117
|
+
Include metadata in your Mastra spans to enrich PostHog events:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// User identification
|
|
121
|
+
{
|
|
122
|
+
metadata: {
|
|
123
|
+
userId: 'user-123', // → distinctId in PostHog
|
|
124
|
+
sessionId: 'session-abc', // → $ai_session_id for grouping
|
|
125
|
+
|
|
126
|
+
// Custom properties (passed through to PostHog)
|
|
127
|
+
environment: 'production',
|
|
128
|
+
version: '1.0.0',
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Cost Tracking
|
|
134
|
+
|
|
135
|
+
PostHog automatically calculates costs from:
|
|
136
|
+
|
|
137
|
+
- Model name + token counts (uses OpenRouter pricing data)
|
|
138
|
+
- Or you can send pre-calculated costs in span attributes
|
|
139
|
+
|
|
140
|
+
## Viewing Data in PostHog
|
|
141
|
+
|
|
142
|
+
1. Navigate to **Product Analytics** → **Events**
|
|
143
|
+
2. Filter for events starting with `$ai_`
|
|
144
|
+
3. Use the **AI Observability** dashboard (if available in your PostHog plan)
|
|
145
|
+
4. Query events by:
|
|
146
|
+
- `$ai_trace_id`: Group all events in a trace
|
|
147
|
+
- `$ai_session_id`: Group traces in a session
|
|
148
|
+
- `$ai_model`: Filter by model (e.g., "gpt-4o")
|
|
149
|
+
- `$ai_provider`: Filter by provider (e.g., "openai")
|
|
150
|
+
|
|
151
|
+
## Environment Variables
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# Required
|
|
155
|
+
POSTHOG_API_KEY=phc_...
|
|
156
|
+
|
|
157
|
+
# Optional
|
|
158
|
+
POSTHOG_HOST=https://us.i.posthog.com # or eu.i.posthog.com
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Links
|
|
162
|
+
|
|
163
|
+
- [PostHog LLM Analytics Documentation](https://posthog.com/docs/ai-engineering/langchain-integration)
|
|
164
|
+
- [Mastra Observability Documentation](https://mastra.ai/docs/observability)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var observability$1 = require('@mastra/core/observability');
|
|
4
|
+
var observability = require('@mastra/observability');
|
|
5
|
+
var posthogNode = require('posthog-node');
|
|
6
|
+
|
|
7
|
+
// src/tracing.ts
|
|
8
|
+
var PosthogExporter = class _PosthogExporter extends observability.BaseExporter {
|
|
9
|
+
name = "posthog";
|
|
10
|
+
client;
|
|
11
|
+
config;
|
|
12
|
+
traceMap = /* @__PURE__ */ new Map();
|
|
13
|
+
static SERVERLESS_FLUSH_AT = 10;
|
|
14
|
+
static SERVERLESS_FLUSH_INTERVAL = 2e3;
|
|
15
|
+
static DEFAULT_FLUSH_AT = 20;
|
|
16
|
+
static DEFAULT_FLUSH_INTERVAL = 1e4;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super(config);
|
|
19
|
+
this.config = config;
|
|
20
|
+
if (!config.apiKey) {
|
|
21
|
+
this.setDisabled("Missing required API key");
|
|
22
|
+
this.client = null;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const clientConfig = this.buildClientConfig(config);
|
|
26
|
+
this.client = new posthogNode.PostHog(config.apiKey, clientConfig);
|
|
27
|
+
this.logInitialization(config.serverless ?? false, clientConfig);
|
|
28
|
+
}
|
|
29
|
+
buildClientConfig(config) {
|
|
30
|
+
const isServerless = config.serverless ?? false;
|
|
31
|
+
const flushAt = config.flushAt ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_AT : _PosthogExporter.DEFAULT_FLUSH_AT);
|
|
32
|
+
const flushInterval = config.flushInterval ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_INTERVAL : _PosthogExporter.DEFAULT_FLUSH_INTERVAL);
|
|
33
|
+
const host = config.host || process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
34
|
+
if (!config.host && !process.env.POSTHOG_HOST) {
|
|
35
|
+
this.logger.warn(
|
|
36
|
+
'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.'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
host,
|
|
41
|
+
flushAt,
|
|
42
|
+
flushInterval,
|
|
43
|
+
privacyMode: config.enablePrivacyMode
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
logInitialization(isServerless, config) {
|
|
47
|
+
const message = isServerless ? "PostHog exporter initialized in serverless mode" : "PostHog exporter initialized";
|
|
48
|
+
this.logger.info(message, config);
|
|
49
|
+
}
|
|
50
|
+
async _exportTracingEvent(event) {
|
|
51
|
+
if (!this.client) return;
|
|
52
|
+
try {
|
|
53
|
+
if (event.exportedSpan.isEvent) {
|
|
54
|
+
if (event.type === "span_started") {
|
|
55
|
+
await this.captureEventSpan(event.exportedSpan);
|
|
56
|
+
}
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
switch (event.type) {
|
|
60
|
+
case "span_started":
|
|
61
|
+
await this.handleSpanStarted(event.exportedSpan);
|
|
62
|
+
break;
|
|
63
|
+
case "span_updated":
|
|
64
|
+
break;
|
|
65
|
+
case "span_ended":
|
|
66
|
+
await this.handleSpanEnded(event.exportedSpan);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
this.logger.error("PostHog exporter error", { error, event });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async handleSpanStarted(span) {
|
|
74
|
+
let traceData = this.traceMap.get(span.traceId);
|
|
75
|
+
if (!traceData) {
|
|
76
|
+
traceData = {
|
|
77
|
+
spans: /* @__PURE__ */ new Map(),
|
|
78
|
+
distinctId: void 0
|
|
79
|
+
};
|
|
80
|
+
this.traceMap.set(span.traceId, traceData);
|
|
81
|
+
}
|
|
82
|
+
traceData.spans.set(span.id, {
|
|
83
|
+
startTime: this.toDate(span.startTime),
|
|
84
|
+
type: span.type
|
|
85
|
+
});
|
|
86
|
+
if (!traceData.distinctId) {
|
|
87
|
+
const userId = span.metadata?.userId;
|
|
88
|
+
if (userId) {
|
|
89
|
+
traceData.distinctId = String(userId);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async handleSpanEnded(span) {
|
|
94
|
+
const traceData = this.traceMap.get(span.traceId);
|
|
95
|
+
if (!traceData) {
|
|
96
|
+
this.logger.warn(`Trace data not found for ended span: ${span.id}`);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const cachedSpan = traceData.spans.get(span.id);
|
|
100
|
+
if (!cachedSpan) {
|
|
101
|
+
this.logger.warn(`Span cache not found for ended span: ${span.id}`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const startTime = cachedSpan.startTime.getTime();
|
|
105
|
+
const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();
|
|
106
|
+
const latency = (endTime - startTime) / 1e3;
|
|
107
|
+
const eventName = this.mapToPostHogEvent(span.type);
|
|
108
|
+
const distinctId = this.getDistinctId(span, traceData);
|
|
109
|
+
const properties = this.buildEventProperties(span, latency);
|
|
110
|
+
this.client.capture({
|
|
111
|
+
distinctId,
|
|
112
|
+
event: eventName,
|
|
113
|
+
properties,
|
|
114
|
+
timestamp: new Date(endTime)
|
|
115
|
+
});
|
|
116
|
+
traceData.spans.delete(span.id);
|
|
117
|
+
if (traceData.spans.size === 0) {
|
|
118
|
+
this.traceMap.delete(span.traceId);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async captureEventSpan(span) {
|
|
122
|
+
const eventName = this.mapToPostHogEvent(span.type);
|
|
123
|
+
const traceData = this.traceMap.get(span.traceId);
|
|
124
|
+
const distinctId = this.getDistinctId(span, traceData);
|
|
125
|
+
const properties = this.buildEventProperties(span, 0);
|
|
126
|
+
this.client.capture({
|
|
127
|
+
distinctId,
|
|
128
|
+
event: eventName,
|
|
129
|
+
properties,
|
|
130
|
+
timestamp: span.endTime ? new Date(span.endTime) : /* @__PURE__ */ new Date()
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async shutdown() {
|
|
134
|
+
if (this.client) {
|
|
135
|
+
await this.client.shutdown();
|
|
136
|
+
}
|
|
137
|
+
this.traceMap.clear();
|
|
138
|
+
await super.shutdown();
|
|
139
|
+
this.logger.info("PostHog exporter shutdown complete");
|
|
140
|
+
}
|
|
141
|
+
toDate(timestamp) {
|
|
142
|
+
return timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
143
|
+
}
|
|
144
|
+
mapToPostHogEvent(spanType) {
|
|
145
|
+
switch (spanType) {
|
|
146
|
+
case observability$1.SpanType.MODEL_GENERATION:
|
|
147
|
+
case observability$1.SpanType.MODEL_STEP:
|
|
148
|
+
return "$ai_generation";
|
|
149
|
+
case observability$1.SpanType.MODEL_CHUNK:
|
|
150
|
+
case observability$1.SpanType.TOOL_CALL:
|
|
151
|
+
case observability$1.SpanType.MCP_TOOL_CALL:
|
|
152
|
+
case observability$1.SpanType.PROCESSOR_RUN:
|
|
153
|
+
case observability$1.SpanType.AGENT_RUN:
|
|
154
|
+
case observability$1.SpanType.WORKFLOW_RUN:
|
|
155
|
+
case observability$1.SpanType.GENERIC:
|
|
156
|
+
default:
|
|
157
|
+
return "$ai_span";
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
getDistinctId(span, traceData) {
|
|
161
|
+
if (span.metadata?.userId) {
|
|
162
|
+
return String(span.metadata.userId);
|
|
163
|
+
}
|
|
164
|
+
if (traceData?.distinctId) {
|
|
165
|
+
return traceData.distinctId;
|
|
166
|
+
}
|
|
167
|
+
if (this.config.defaultDistinctId) {
|
|
168
|
+
return this.config.defaultDistinctId;
|
|
169
|
+
}
|
|
170
|
+
return "anonymous";
|
|
171
|
+
}
|
|
172
|
+
buildEventProperties(span, latency) {
|
|
173
|
+
const baseProperties = {
|
|
174
|
+
$ai_trace_id: span.traceId,
|
|
175
|
+
$ai_latency: latency,
|
|
176
|
+
$ai_is_error: !!span.errorInfo
|
|
177
|
+
};
|
|
178
|
+
if (span.parentSpanId) {
|
|
179
|
+
baseProperties.$ai_parent_id = span.parentSpanId;
|
|
180
|
+
}
|
|
181
|
+
if (span.metadata?.sessionId) {
|
|
182
|
+
baseProperties.$ai_session_id = span.metadata.sessionId;
|
|
183
|
+
}
|
|
184
|
+
if (span.type === observability$1.SpanType.MODEL_GENERATION || span.type === observability$1.SpanType.MODEL_STEP) {
|
|
185
|
+
baseProperties.$ai_generation_id = span.id;
|
|
186
|
+
return { ...baseProperties, ...this.buildGenerationProperties(span) };
|
|
187
|
+
} else {
|
|
188
|
+
baseProperties.$ai_span_id = span.id;
|
|
189
|
+
baseProperties.$ai_span_name = span.name;
|
|
190
|
+
return { ...baseProperties, ...this.buildSpanProperties(span) };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
extractErrorProperties(span) {
|
|
194
|
+
if (!span.errorInfo) {
|
|
195
|
+
return {};
|
|
196
|
+
}
|
|
197
|
+
const props = {
|
|
198
|
+
error_message: span.errorInfo.message
|
|
199
|
+
};
|
|
200
|
+
if (span.errorInfo.id) {
|
|
201
|
+
props.error_id = span.errorInfo.id;
|
|
202
|
+
}
|
|
203
|
+
if (span.errorInfo.category) {
|
|
204
|
+
props.error_category = span.errorInfo.category;
|
|
205
|
+
}
|
|
206
|
+
return props;
|
|
207
|
+
}
|
|
208
|
+
extractCustomMetadata(span) {
|
|
209
|
+
const { userId, sessionId, ...customMetadata } = span.metadata ?? {};
|
|
210
|
+
return customMetadata;
|
|
211
|
+
}
|
|
212
|
+
buildGenerationProperties(span) {
|
|
213
|
+
const props = {};
|
|
214
|
+
const attrs = span.attributes ?? {};
|
|
215
|
+
props.$ai_model = attrs.model || "unknown-model";
|
|
216
|
+
props.$ai_provider = attrs.provider || "unknown-provider";
|
|
217
|
+
if (span.input) props.$ai_input = this.formatMessages(span.input, "user");
|
|
218
|
+
if (span.output) props.$ai_output_choices = this.formatMessages(span.output, "assistant");
|
|
219
|
+
if (attrs.usage) {
|
|
220
|
+
const { usage } = attrs;
|
|
221
|
+
const inputTokens = usage.inputTokens ?? usage.promptTokens;
|
|
222
|
+
const outputTokens = usage.outputTokens ?? usage.completionTokens;
|
|
223
|
+
const totalTokens = usage.totalTokens;
|
|
224
|
+
if (inputTokens !== void 0) props.$ai_input_tokens = inputTokens;
|
|
225
|
+
if (outputTokens !== void 0) props.$ai_output_tokens = outputTokens;
|
|
226
|
+
if (totalTokens !== void 0) props.$ai_total_tokens = totalTokens;
|
|
227
|
+
if (usage.reasoningTokens !== void 0) props.reasoning_tokens = usage.reasoningTokens;
|
|
228
|
+
if (usage.cachedInputTokens !== void 0) props.cached_input_tokens = usage.cachedInputTokens;
|
|
229
|
+
}
|
|
230
|
+
if (attrs.parameters) {
|
|
231
|
+
if (attrs.parameters.temperature !== void 0) props.$ai_temperature = attrs.parameters.temperature;
|
|
232
|
+
if (attrs.parameters.maxOutputTokens !== void 0) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;
|
|
233
|
+
}
|
|
234
|
+
if (attrs.streaming !== void 0) props.$ai_stream = attrs.streaming;
|
|
235
|
+
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
236
|
+
}
|
|
237
|
+
buildSpanProperties(span) {
|
|
238
|
+
const props = {};
|
|
239
|
+
if (span.input) props.$ai_input_state = span.input;
|
|
240
|
+
if (span.output) props.$ai_output_state = span.output;
|
|
241
|
+
if (span.type === observability$1.SpanType.MODEL_CHUNK) {
|
|
242
|
+
const attrs = span.attributes;
|
|
243
|
+
if (attrs?.chunkType) props.chunk_type = attrs.chunkType;
|
|
244
|
+
if (attrs?.sequenceNumber !== void 0) props.chunk_sequence_number = attrs.sequenceNumber;
|
|
245
|
+
}
|
|
246
|
+
if (span.attributes) {
|
|
247
|
+
Object.assign(props, span.attributes);
|
|
248
|
+
}
|
|
249
|
+
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
250
|
+
}
|
|
251
|
+
formatMessages(data, defaultRole = "user") {
|
|
252
|
+
if (this.isMessageArray(data)) {
|
|
253
|
+
return data.map((msg) => this.normalizeMessage(msg));
|
|
254
|
+
}
|
|
255
|
+
if (typeof data === "string") {
|
|
256
|
+
return [{ role: defaultRole, content: [{ type: "text", text: data }] }];
|
|
257
|
+
}
|
|
258
|
+
return [{ role: defaultRole, content: [{ type: "text", text: this.safeStringify(data) }] }];
|
|
259
|
+
}
|
|
260
|
+
isMessageArray(data) {
|
|
261
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
return data.every((item) => typeof item === "object" && item !== null && "role" in item && "content" in item);
|
|
265
|
+
}
|
|
266
|
+
normalizeMessage(msg) {
|
|
267
|
+
if (typeof msg.content === "string") {
|
|
268
|
+
return {
|
|
269
|
+
role: msg.role,
|
|
270
|
+
content: [{ type: "text", text: msg.content }]
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
role: msg.role,
|
|
275
|
+
content: msg.content
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
safeStringify(data) {
|
|
279
|
+
try {
|
|
280
|
+
return JSON.stringify(data);
|
|
281
|
+
} catch {
|
|
282
|
+
if (typeof data === "object" && data !== null) {
|
|
283
|
+
return `[Non-serializable ${data.constructor?.name || "Object"}]`;
|
|
284
|
+
}
|
|
285
|
+
return String(data);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
exports.PosthogExporter = PosthogExporter;
|
|
291
|
+
//# sourceMappingURL=index.cjs.map
|
|
292
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +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 } 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\ninterface PostHogMessage {\n role: 'user' | 'assistant' | 'system' | 'tool';\n content: PostHogContent[];\n}\n\ninterface PostHogContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface MastraMessage {\n role: string;\n content: string | MastraContent[];\n}\n\ninterface MastraContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ntype SpanData = string | MastraMessage[] | Record<string, unknown> | unknown;\n\nexport interface PosthogExporterConfig extends BaseExporterConfig {\n apiKey: string;\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n serverless?: boolean;\n defaultDistinctId?: string;\n enablePrivacyMode?: boolean;\n}\n\ntype SpanCache = {\n startTime: Date;\n type: SpanType;\n};\n\ntype TraceMetadata = {\n spans: Map<string, SpanCache>;\n distinctId?: string;\n};\n\nexport class PosthogExporter extends BaseExporter {\n name = 'posthog';\n private client: PostHog;\n private config: PosthogExporterConfig;\n private traceMap = new Map<string, TraceMetadata>();\n\n private static readonly SERVERLESS_FLUSH_AT = 10;\n private static readonly SERVERLESS_FLUSH_INTERVAL = 2000;\n private static readonly DEFAULT_FLUSH_AT = 20;\n private static readonly DEFAULT_FLUSH_INTERVAL = 10000;\n\n constructor(config: PosthogExporterConfig) {\n super(config);\n this.config = config;\n\n if (!config.apiKey) {\n this.setDisabled('Missing required API key');\n this.client = null as any;\n return;\n }\n\n const clientConfig = this.buildClientConfig(config);\n this.client = new PostHog(config.apiKey, clientConfig);\n this.logInitialization(config.serverless ?? false, clientConfig);\n }\n\n private buildClientConfig(config: PosthogExporterConfig): {\n host: string;\n flushAt: number;\n flushInterval: number;\n privacyMode?: boolean;\n } {\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 },\n ): void {\n const message = isServerless ? 'PostHog exporter initialized in serverless mode' : 'PostHog exporter initialized';\n\n this.logger.info(message, config);\n }\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.client) return;\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 });\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 this.logger.warn(`Trace data not found for ended span: ${span.id}`);\n return;\n }\n\n const cachedSpan = traceData.spans.get(span.id);\n if (!cachedSpan) {\n this.logger.warn(`Span cache not found for ended span: ${span.id}`);\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 eventName = this.mapToPostHogEvent(span.type);\n const distinctId = this.getDistinctId(span, traceData);\n const properties = this.buildEventProperties(span, latency);\n\n this.client.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: new Date(endTime),\n });\n\n traceData.spans.delete(span.id);\n if (traceData.spans.size === 0) {\n this.traceMap.delete(span.traceId);\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 switch (spanType) {\n case SpanType.MODEL_GENERATION:\n case SpanType.MODEL_STEP:\n return '$ai_generation';\n case SpanType.MODEL_CHUNK:\n case SpanType.TOOL_CALL:\n case SpanType.MCP_TOOL_CALL:\n case SpanType.PROCESSOR_RUN:\n case SpanType.AGENT_RUN:\n case SpanType.WORKFLOW_RUN:\n case SpanType.GENERIC:\n default:\n return '$ai_span';\n }\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 private buildEventProperties(span: AnyExportedSpan, latency: number): 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 baseProperties.$ai_parent_id = span.parentSpanId;\n }\n\n if (span.metadata?.sessionId) {\n baseProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {\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 if (attrs.usage) {\n const { usage } = attrs;\n const inputTokens = usage.inputTokens ?? usage.promptTokens;\n const outputTokens = usage.outputTokens ?? usage.completionTokens;\n const totalTokens = usage.totalTokens;\n\n if (inputTokens !== undefined) props.$ai_input_tokens = inputTokens;\n if (outputTokens !== undefined) props.$ai_output_tokens = outputTokens;\n if (totalTokens !== undefined) props.$ai_total_tokens = totalTokens;\n\n if (usage.reasoningTokens !== undefined) props.reasoning_tokens = usage.reasoningTokens;\n if (usage.cachedInputTokens !== undefined) props.cached_input_tokens = usage.cachedInputTokens;\n }\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"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { SpanType } from '@mastra/core/observability';
|
|
2
|
+
import { BaseExporter } from '@mastra/observability';
|
|
3
|
+
import { PostHog } from 'posthog-node';
|
|
4
|
+
|
|
5
|
+
// src/tracing.ts
|
|
6
|
+
var PosthogExporter = class _PosthogExporter extends BaseExporter {
|
|
7
|
+
name = "posthog";
|
|
8
|
+
client;
|
|
9
|
+
config;
|
|
10
|
+
traceMap = /* @__PURE__ */ new Map();
|
|
11
|
+
static SERVERLESS_FLUSH_AT = 10;
|
|
12
|
+
static SERVERLESS_FLUSH_INTERVAL = 2e3;
|
|
13
|
+
static DEFAULT_FLUSH_AT = 20;
|
|
14
|
+
static DEFAULT_FLUSH_INTERVAL = 1e4;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
super(config);
|
|
17
|
+
this.config = config;
|
|
18
|
+
if (!config.apiKey) {
|
|
19
|
+
this.setDisabled("Missing required API key");
|
|
20
|
+
this.client = null;
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const clientConfig = this.buildClientConfig(config);
|
|
24
|
+
this.client = new PostHog(config.apiKey, clientConfig);
|
|
25
|
+
this.logInitialization(config.serverless ?? false, clientConfig);
|
|
26
|
+
}
|
|
27
|
+
buildClientConfig(config) {
|
|
28
|
+
const isServerless = config.serverless ?? false;
|
|
29
|
+
const flushAt = config.flushAt ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_AT : _PosthogExporter.DEFAULT_FLUSH_AT);
|
|
30
|
+
const flushInterval = config.flushInterval ?? (isServerless ? _PosthogExporter.SERVERLESS_FLUSH_INTERVAL : _PosthogExporter.DEFAULT_FLUSH_INTERVAL);
|
|
31
|
+
const host = config.host || process.env.POSTHOG_HOST || "https://us.i.posthog.com";
|
|
32
|
+
if (!config.host && !process.env.POSTHOG_HOST) {
|
|
33
|
+
this.logger.warn(
|
|
34
|
+
'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.'
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
host,
|
|
39
|
+
flushAt,
|
|
40
|
+
flushInterval,
|
|
41
|
+
privacyMode: config.enablePrivacyMode
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
logInitialization(isServerless, config) {
|
|
45
|
+
const message = isServerless ? "PostHog exporter initialized in serverless mode" : "PostHog exporter initialized";
|
|
46
|
+
this.logger.info(message, config);
|
|
47
|
+
}
|
|
48
|
+
async _exportTracingEvent(event) {
|
|
49
|
+
if (!this.client) return;
|
|
50
|
+
try {
|
|
51
|
+
if (event.exportedSpan.isEvent) {
|
|
52
|
+
if (event.type === "span_started") {
|
|
53
|
+
await this.captureEventSpan(event.exportedSpan);
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
switch (event.type) {
|
|
58
|
+
case "span_started":
|
|
59
|
+
await this.handleSpanStarted(event.exportedSpan);
|
|
60
|
+
break;
|
|
61
|
+
case "span_updated":
|
|
62
|
+
break;
|
|
63
|
+
case "span_ended":
|
|
64
|
+
await this.handleSpanEnded(event.exportedSpan);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
this.logger.error("PostHog exporter error", { error, event });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async handleSpanStarted(span) {
|
|
72
|
+
let traceData = this.traceMap.get(span.traceId);
|
|
73
|
+
if (!traceData) {
|
|
74
|
+
traceData = {
|
|
75
|
+
spans: /* @__PURE__ */ new Map(),
|
|
76
|
+
distinctId: void 0
|
|
77
|
+
};
|
|
78
|
+
this.traceMap.set(span.traceId, traceData);
|
|
79
|
+
}
|
|
80
|
+
traceData.spans.set(span.id, {
|
|
81
|
+
startTime: this.toDate(span.startTime),
|
|
82
|
+
type: span.type
|
|
83
|
+
});
|
|
84
|
+
if (!traceData.distinctId) {
|
|
85
|
+
const userId = span.metadata?.userId;
|
|
86
|
+
if (userId) {
|
|
87
|
+
traceData.distinctId = String(userId);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async handleSpanEnded(span) {
|
|
92
|
+
const traceData = this.traceMap.get(span.traceId);
|
|
93
|
+
if (!traceData) {
|
|
94
|
+
this.logger.warn(`Trace data not found for ended span: ${span.id}`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const cachedSpan = traceData.spans.get(span.id);
|
|
98
|
+
if (!cachedSpan) {
|
|
99
|
+
this.logger.warn(`Span cache not found for ended span: ${span.id}`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const startTime = cachedSpan.startTime.getTime();
|
|
103
|
+
const endTime = span.endTime ? this.toDate(span.endTime).getTime() : Date.now();
|
|
104
|
+
const latency = (endTime - startTime) / 1e3;
|
|
105
|
+
const eventName = this.mapToPostHogEvent(span.type);
|
|
106
|
+
const distinctId = this.getDistinctId(span, traceData);
|
|
107
|
+
const properties = this.buildEventProperties(span, latency);
|
|
108
|
+
this.client.capture({
|
|
109
|
+
distinctId,
|
|
110
|
+
event: eventName,
|
|
111
|
+
properties,
|
|
112
|
+
timestamp: new Date(endTime)
|
|
113
|
+
});
|
|
114
|
+
traceData.spans.delete(span.id);
|
|
115
|
+
if (traceData.spans.size === 0) {
|
|
116
|
+
this.traceMap.delete(span.traceId);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async captureEventSpan(span) {
|
|
120
|
+
const eventName = this.mapToPostHogEvent(span.type);
|
|
121
|
+
const traceData = this.traceMap.get(span.traceId);
|
|
122
|
+
const distinctId = this.getDistinctId(span, traceData);
|
|
123
|
+
const properties = this.buildEventProperties(span, 0);
|
|
124
|
+
this.client.capture({
|
|
125
|
+
distinctId,
|
|
126
|
+
event: eventName,
|
|
127
|
+
properties,
|
|
128
|
+
timestamp: span.endTime ? new Date(span.endTime) : /* @__PURE__ */ new Date()
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async shutdown() {
|
|
132
|
+
if (this.client) {
|
|
133
|
+
await this.client.shutdown();
|
|
134
|
+
}
|
|
135
|
+
this.traceMap.clear();
|
|
136
|
+
await super.shutdown();
|
|
137
|
+
this.logger.info("PostHog exporter shutdown complete");
|
|
138
|
+
}
|
|
139
|
+
toDate(timestamp) {
|
|
140
|
+
return timestamp instanceof Date ? timestamp : new Date(timestamp);
|
|
141
|
+
}
|
|
142
|
+
mapToPostHogEvent(spanType) {
|
|
143
|
+
switch (spanType) {
|
|
144
|
+
case SpanType.MODEL_GENERATION:
|
|
145
|
+
case SpanType.MODEL_STEP:
|
|
146
|
+
return "$ai_generation";
|
|
147
|
+
case SpanType.MODEL_CHUNK:
|
|
148
|
+
case SpanType.TOOL_CALL:
|
|
149
|
+
case SpanType.MCP_TOOL_CALL:
|
|
150
|
+
case SpanType.PROCESSOR_RUN:
|
|
151
|
+
case SpanType.AGENT_RUN:
|
|
152
|
+
case SpanType.WORKFLOW_RUN:
|
|
153
|
+
case SpanType.GENERIC:
|
|
154
|
+
default:
|
|
155
|
+
return "$ai_span";
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
getDistinctId(span, traceData) {
|
|
159
|
+
if (span.metadata?.userId) {
|
|
160
|
+
return String(span.metadata.userId);
|
|
161
|
+
}
|
|
162
|
+
if (traceData?.distinctId) {
|
|
163
|
+
return traceData.distinctId;
|
|
164
|
+
}
|
|
165
|
+
if (this.config.defaultDistinctId) {
|
|
166
|
+
return this.config.defaultDistinctId;
|
|
167
|
+
}
|
|
168
|
+
return "anonymous";
|
|
169
|
+
}
|
|
170
|
+
buildEventProperties(span, latency) {
|
|
171
|
+
const baseProperties = {
|
|
172
|
+
$ai_trace_id: span.traceId,
|
|
173
|
+
$ai_latency: latency,
|
|
174
|
+
$ai_is_error: !!span.errorInfo
|
|
175
|
+
};
|
|
176
|
+
if (span.parentSpanId) {
|
|
177
|
+
baseProperties.$ai_parent_id = span.parentSpanId;
|
|
178
|
+
}
|
|
179
|
+
if (span.metadata?.sessionId) {
|
|
180
|
+
baseProperties.$ai_session_id = span.metadata.sessionId;
|
|
181
|
+
}
|
|
182
|
+
if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {
|
|
183
|
+
baseProperties.$ai_generation_id = span.id;
|
|
184
|
+
return { ...baseProperties, ...this.buildGenerationProperties(span) };
|
|
185
|
+
} else {
|
|
186
|
+
baseProperties.$ai_span_id = span.id;
|
|
187
|
+
baseProperties.$ai_span_name = span.name;
|
|
188
|
+
return { ...baseProperties, ...this.buildSpanProperties(span) };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
extractErrorProperties(span) {
|
|
192
|
+
if (!span.errorInfo) {
|
|
193
|
+
return {};
|
|
194
|
+
}
|
|
195
|
+
const props = {
|
|
196
|
+
error_message: span.errorInfo.message
|
|
197
|
+
};
|
|
198
|
+
if (span.errorInfo.id) {
|
|
199
|
+
props.error_id = span.errorInfo.id;
|
|
200
|
+
}
|
|
201
|
+
if (span.errorInfo.category) {
|
|
202
|
+
props.error_category = span.errorInfo.category;
|
|
203
|
+
}
|
|
204
|
+
return props;
|
|
205
|
+
}
|
|
206
|
+
extractCustomMetadata(span) {
|
|
207
|
+
const { userId, sessionId, ...customMetadata } = span.metadata ?? {};
|
|
208
|
+
return customMetadata;
|
|
209
|
+
}
|
|
210
|
+
buildGenerationProperties(span) {
|
|
211
|
+
const props = {};
|
|
212
|
+
const attrs = span.attributes ?? {};
|
|
213
|
+
props.$ai_model = attrs.model || "unknown-model";
|
|
214
|
+
props.$ai_provider = attrs.provider || "unknown-provider";
|
|
215
|
+
if (span.input) props.$ai_input = this.formatMessages(span.input, "user");
|
|
216
|
+
if (span.output) props.$ai_output_choices = this.formatMessages(span.output, "assistant");
|
|
217
|
+
if (attrs.usage) {
|
|
218
|
+
const { usage } = attrs;
|
|
219
|
+
const inputTokens = usage.inputTokens ?? usage.promptTokens;
|
|
220
|
+
const outputTokens = usage.outputTokens ?? usage.completionTokens;
|
|
221
|
+
const totalTokens = usage.totalTokens;
|
|
222
|
+
if (inputTokens !== void 0) props.$ai_input_tokens = inputTokens;
|
|
223
|
+
if (outputTokens !== void 0) props.$ai_output_tokens = outputTokens;
|
|
224
|
+
if (totalTokens !== void 0) props.$ai_total_tokens = totalTokens;
|
|
225
|
+
if (usage.reasoningTokens !== void 0) props.reasoning_tokens = usage.reasoningTokens;
|
|
226
|
+
if (usage.cachedInputTokens !== void 0) props.cached_input_tokens = usage.cachedInputTokens;
|
|
227
|
+
}
|
|
228
|
+
if (attrs.parameters) {
|
|
229
|
+
if (attrs.parameters.temperature !== void 0) props.$ai_temperature = attrs.parameters.temperature;
|
|
230
|
+
if (attrs.parameters.maxOutputTokens !== void 0) props.$ai_max_tokens = attrs.parameters.maxOutputTokens;
|
|
231
|
+
}
|
|
232
|
+
if (attrs.streaming !== void 0) props.$ai_stream = attrs.streaming;
|
|
233
|
+
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
234
|
+
}
|
|
235
|
+
buildSpanProperties(span) {
|
|
236
|
+
const props = {};
|
|
237
|
+
if (span.input) props.$ai_input_state = span.input;
|
|
238
|
+
if (span.output) props.$ai_output_state = span.output;
|
|
239
|
+
if (span.type === SpanType.MODEL_CHUNK) {
|
|
240
|
+
const attrs = span.attributes;
|
|
241
|
+
if (attrs?.chunkType) props.chunk_type = attrs.chunkType;
|
|
242
|
+
if (attrs?.sequenceNumber !== void 0) props.chunk_sequence_number = attrs.sequenceNumber;
|
|
243
|
+
}
|
|
244
|
+
if (span.attributes) {
|
|
245
|
+
Object.assign(props, span.attributes);
|
|
246
|
+
}
|
|
247
|
+
return { ...props, ...this.extractErrorProperties(span), ...this.extractCustomMetadata(span) };
|
|
248
|
+
}
|
|
249
|
+
formatMessages(data, defaultRole = "user") {
|
|
250
|
+
if (this.isMessageArray(data)) {
|
|
251
|
+
return data.map((msg) => this.normalizeMessage(msg));
|
|
252
|
+
}
|
|
253
|
+
if (typeof data === "string") {
|
|
254
|
+
return [{ role: defaultRole, content: [{ type: "text", text: data }] }];
|
|
255
|
+
}
|
|
256
|
+
return [{ role: defaultRole, content: [{ type: "text", text: this.safeStringify(data) }] }];
|
|
257
|
+
}
|
|
258
|
+
isMessageArray(data) {
|
|
259
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
return data.every((item) => typeof item === "object" && item !== null && "role" in item && "content" in item);
|
|
263
|
+
}
|
|
264
|
+
normalizeMessage(msg) {
|
|
265
|
+
if (typeof msg.content === "string") {
|
|
266
|
+
return {
|
|
267
|
+
role: msg.role,
|
|
268
|
+
content: [{ type: "text", text: msg.content }]
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
return {
|
|
272
|
+
role: msg.role,
|
|
273
|
+
content: msg.content
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
safeStringify(data) {
|
|
277
|
+
try {
|
|
278
|
+
return JSON.stringify(data);
|
|
279
|
+
} catch {
|
|
280
|
+
if (typeof data === "object" && data !== null) {
|
|
281
|
+
return `[Non-serializable ${data.constructor?.name || "Object"}]`;
|
|
282
|
+
}
|
|
283
|
+
return String(data);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
export { PosthogExporter };
|
|
289
|
+
//# sourceMappingURL=index.js.map
|
|
290
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tracing.ts"],"names":[],"mappings":";;;;;AAkDO,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,YAAA,CAAa;AAAA,EAChD,IAAA,GAAO,SAAA;AAAA,EACC,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,uBAAe,GAAA,EAA2B;AAAA,EAElD,OAAwB,mBAAA,GAAsB,EAAA;AAAA,EAC9C,OAAwB,yBAAA,GAA4B,GAAA;AAAA,EACpD,OAAwB,gBAAA,GAAmB,EAAA;AAAA,EAC3C,OAAwB,sBAAA,GAAyB,GAAA;AAAA,EAEjD,YAAY,MAAA,EAA+B;AACzC,IAAA,KAAA,CAAM,MAAM,CAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAEd,IAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,MAAA,IAAA,CAAK,YAAY,0BAA0B,CAAA;AAC3C,MAAA,IAAA,CAAK,MAAA,GAAS,IAAA;AACd,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,iBAAA,CAAkB,MAAM,CAAA;AAClD,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,OAAA,CAAQ,MAAA,CAAO,QAAQ,YAAY,CAAA;AACrD,IAAA,IAAA,CAAK,iBAAA,CAAkB,MAAA,CAAO,UAAA,IAAc,KAAA,EAAO,YAAY,CAAA;AAAA,EACjE;AAAA,EAEQ,kBAAkB,MAAA,EAKxB;AACA,IAAA,MAAM,YAAA,GAAe,OAAO,UAAA,IAAc,KAAA;AAC1C,IAAA,MAAM,UACJ,MAAA,CAAO,OAAA,KAAY,YAAA,GAAe,gBAAA,CAAgB,sBAAsB,gBAAA,CAAgB,gBAAA,CAAA;AAC1F,IAAA,MAAM,gBACJ,MAAA,CAAO,aAAA,KACN,YAAA,GAAe,gBAAA,CAAgB,4BAA4B,gBAAA,CAAgB,sBAAA,CAAA;AAE9E,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,IAAQ,OAAA,CAAQ,IAAI,YAAA,IAAgB,0BAAA;AAExD,IAAA,IAAI,CAAC,MAAA,CAAO,IAAA,IAAQ,CAAC,OAAA,CAAQ,IAAI,YAAA,EAAc;AAC7C,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,QACV;AAAA,OAGF;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,OAAA;AAAA,MACA,aAAA;AAAA,MACA,aAAa,MAAA,CAAO;AAAA,KACtB;AAAA,EACF;AAAA,EAEQ,iBAAA,CACN,cACA,MAAA,EACM;AACN,IAAA,MAAM,OAAA,GAAU,eAAe,iDAAA,GAAoD,8BAAA;AAEnF,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAA,EAAS,MAAM,CAAA;AAAA,EAClC;AAAA,EAEA,MAAgB,oBAAoB,KAAA,EAAoC;AACtE,IAAA,IAAI,CAAC,KAAK,MAAA,EAAQ;AAElB,IAAA,IAAI;AACF,MAAA,IAAI,KAAA,CAAM,aAAa,OAAA,EAAS;AAC9B,QAAA,IAAI,KAAA,CAAM,SAAS,cAAA,EAAgB;AACjC,UAAA,MAAM,IAAA,CAAK,gBAAA,CAAiB,KAAA,CAAM,YAAY,CAAA;AAAA,QAChD;AACA,QAAA;AAAA,MACF;AAEA,MAAA,QAAQ,MAAM,IAAA;AAAM,QAClB,KAAK,cAAA;AACH,UAAA,MAAM,IAAA,CAAK,iBAAA,CAAkB,KAAA,CAAM,YAAY,CAAA;AAC/C,UAAA;AAAA,QACF,KAAK,cAAA;AACH,UAAA;AAAA,QACF,KAAK,YAAA;AACH,UAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,KAAA,CAAM,YAAY,CAAA;AAC7C,UAAA;AAAA;AACJ,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,wBAAA,EAA0B,EAAE,KAAA,EAAO,OAAO,CAAA;AAAA,IAC9D;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,IAAA,EAAsC;AACpE,IAAA,IAAI,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,OAAO,CAAA;AAE9C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,SAAA,GAAY;AAAA,QACV,KAAA,sBAAW,GAAA,EAAI;AAAA,QACf,UAAA,EAAY;AAAA,OACd;AACA,MAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS,SAAS,CAAA;AAAA,IAC3C;AAEA,IAAA,SAAA,CAAU,KAAA,CAAM,GAAA,CAAI,IAAA,CAAK,EAAA,EAAI;AAAA,MAC3B,SAAA,EAAW,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAAA,MACrC,MAAM,IAAA,CAAK;AAAA,KACZ,CAAA;AAED,IAAA,IAAI,CAAC,UAAU,UAAA,EAAY;AACzB,MAAA,MAAM,MAAA,GAAS,KAAK,QAAA,EAAU,MAAA;AAC9B,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,SAAA,CAAU,UAAA,GAAa,OAAO,MAAM,CAAA;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,IAAA,EAAsC;AAClE,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,OAAO,CAAA;AAEhD,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,qCAAA,EAAwC,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAClE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,SAAA,CAAU,KAAA,CAAM,GAAA,CAAI,KAAK,EAAE,CAAA;AAC9C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,qCAAA,EAAwC,IAAA,CAAK,EAAE,CAAA,CAAE,CAAA;AAClE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,UAAA,CAAW,SAAA,CAAU,OAAA,EAAQ;AAC/C,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,OAAA,EAAQ,GAAI,IAAA,CAAK,GAAA,EAAI;AAC9E,IAAA,MAAM,OAAA,GAAA,CAAW,UAAU,SAAA,IAAa,GAAA;AAExC,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAA;AAClD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,aAAA,CAAc,IAAA,EAAM,SAAS,CAAA;AACrD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,oBAAA,CAAqB,IAAA,EAAM,OAAO,CAAA;AAE1D,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ;AAAA,MAClB,UAAA;AAAA,MACA,KAAA,EAAO,SAAA;AAAA,MACP,UAAA;AAAA,MACA,SAAA,EAAW,IAAI,IAAA,CAAK,OAAO;AAAA,KAC5B,CAAA;AAED,IAAA,SAAA,CAAU,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA;AAC9B,IAAA,IAAI,SAAA,CAAU,KAAA,CAAM,IAAA,KAAS,CAAA,EAAG;AAC9B,MAAA,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB,IAAA,EAAsC;AACnE,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAA;AAClD,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,KAAK,OAAO,CAAA;AAEhD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,aAAA,CAAc,IAAA,EAAM,SAAS,CAAA;AACrD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,oBAAA,CAAqB,IAAA,EAAM,CAAC,CAAA;AAEpD,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ;AAAA,MAClB,UAAA;AAAA,MACA,KAAA,EAAO,SAAA;AAAA,MACP,UAAA;AAAA,MACA,SAAA,EAAW,KAAK,OAAA,GAAU,IAAI,KAAK,IAAA,CAAK,OAAO,CAAA,mBAAI,IAAI,IAAA;AAAK,KAC7D,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,QAAA,GAA0B;AAC9B,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,MAAM,IAAA,CAAK,OAAO,QAAA,EAAS;AAAA,IAC7B;AACA,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AACpB,IAAA,MAAM,MAAM,QAAA,EAAS;AACrB,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,oCAAoC,CAAA;AAAA,EACvD;AAAA,EAEQ,OAAO,SAAA,EAAgC;AAC7C,IAAA,OAAO,SAAA,YAAqB,IAAA,GAAO,SAAA,GAAY,IAAI,KAAK,SAAS,CAAA;AAAA,EACnE;AAAA,EAEQ,kBAAkB,QAAA,EAA4B;AACpD,IAAA,QAAQ,QAAA;AAAU,MAChB,KAAK,QAAA,CAAS,gBAAA;AAAA,MACd,KAAK,QAAA,CAAS,UAAA;AACZ,QAAA,OAAO,gBAAA;AAAA,MACT,KAAK,QAAA,CAAS,WAAA;AAAA,MACd,KAAK,QAAA,CAAS,SAAA;AAAA,MACd,KAAK,QAAA,CAAS,aAAA;AAAA,MACd,KAAK,QAAA,CAAS,aAAA;AAAA,MACd,KAAK,QAAA,CAAS,SAAA;AAAA,MACd,KAAK,QAAA,CAAS,YAAA;AAAA,MACd,KAAK,QAAA,CAAS,OAAA;AAAA,MACd;AACE,QAAA,OAAO,UAAA;AAAA;AACX,EACF;AAAA,EAEQ,aAAA,CAAc,MAAuB,SAAA,EAAmC;AAC9E,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,MAAA,OAAO,MAAA,CAAO,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAAA,IACpC;AAEA,IAAA,IAAI,WAAW,UAAA,EAAY;AACzB,MAAA,OAAO,SAAA,CAAU,UAAA;AAAA,IACnB;AAEA,IAAA,IAAI,IAAA,CAAK,OAAO,iBAAA,EAAmB;AACjC,MAAA,OAAO,KAAK,MAAA,CAAO,iBAAA;AAAA,IACrB;AAEA,IAAA,OAAO,WAAA;AAAA,EACT;AAAA,EAEQ,oBAAA,CAAqB,MAAuB,OAAA,EAAsC;AACxF,IAAA,MAAM,cAAA,GAAsC;AAAA,MAC1C,cAAc,IAAA,CAAK,OAAA;AAAA,MACnB,WAAA,EAAa,OAAA;AAAA,MACb,YAAA,EAAc,CAAC,CAAC,IAAA,CAAK;AAAA,KACvB;AAEA,IAAA,IAAI,KAAK,YAAA,EAAc;AACrB,MAAA,cAAA,CAAe,gBAAgB,IAAA,CAAK,YAAA;AAAA,IACtC;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC5B,MAAA,cAAA,CAAe,cAAA,GAAiB,KAAK,QAAA,CAAS,SAAA;AAAA,IAChD;AAEA,IAAA,IAAI,KAAK,IAAA,KAAS,QAAA,CAAS,oBAAoB,IAAA,CAAK,IAAA,KAAS,SAAS,UAAA,EAAY;AAChF,MAAA,cAAA,CAAe,oBAAoB,IAAA,CAAK,EAAA;AACxC,MAAA,OAAO,EAAE,GAAG,cAAA,EAAgB,GAAG,IAAA,CAAK,yBAAA,CAA0B,IAAI,CAAA,EAAE;AAAA,IACtE,CAAA,MAAO;AACL,MAAA,cAAA,CAAe,cAAc,IAAA,CAAK,EAAA;AAClC,MAAA,cAAA,CAAe,gBAAgB,IAAA,CAAK,IAAA;AACpC,MAAA,OAAO,EAAE,GAAG,cAAA,EAAgB,GAAG,IAAA,CAAK,mBAAA,CAAoB,IAAI,CAAA,EAAE;AAAA,IAChE;AAAA,EACF;AAAA,EAEQ,uBAAuB,IAAA,EAA4C;AACzE,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,OAAO,EAAC;AAAA,IACV;AAEA,IAAA,MAAM,KAAA,GAAgC;AAAA,MACpC,aAAA,EAAe,KAAK,SAAA,CAAU;AAAA,KAChC;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,EAAA,EAAI;AACrB,MAAA,KAAA,CAAM,QAAA,GAAW,KAAK,SAAA,CAAU,EAAA;AAAA,IAClC;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,QAAA,EAAU;AAC3B,MAAA,KAAA,CAAM,cAAA,GAAiB,KAAK,SAAA,CAAU,QAAA;AAAA,IACxC;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEQ,sBAAsB,IAAA,EAA4C;AACxE,IAAA,MAAM,EAAE,QAAQ,SAAA,EAAW,GAAG,gBAAe,GAAI,IAAA,CAAK,YAAY,EAAC;AACnE,IAAA,OAAO,cAAA;AAAA,EACT;AAAA,EAEQ,0BAA0B,IAAA,EAA4C;AAC5E,IAAA,MAAM,QAA6B,EAAC;AACpC,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,UAAA,IAAc,EAAC;AAEnC,IAAA,KAAA,CAAM,SAAA,GAAY,MAAM,KAAA,IAAS,eAAA;AACjC,IAAA,KAAA,CAAM,YAAA,GAAe,MAAM,QAAA,IAAY,kBAAA;AAEvC,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,CAAM,SAAA,GAAY,KAAK,cAAA,CAAe,IAAA,CAAK,OAAO,MAAM,CAAA;AACxE,IAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,CAAM,kBAAA,GAAqB,KAAK,cAAA,CAAe,IAAA,CAAK,QAAQ,WAAW,CAAA;AAExF,IAAA,IAAI,MAAM,KAAA,EAAO;AACf,MAAA,MAAM,EAAE,OAAM,GAAI,KAAA;AAClB,MAAA,MAAM,WAAA,GAAc,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,YAAA;AAC/C,MAAA,MAAM,YAAA,GAAe,KAAA,CAAM,YAAA,IAAgB,KAAA,CAAM,gBAAA;AACjD,MAAA,MAAM,cAAc,KAAA,CAAM,WAAA;AAE1B,MAAA,IAAI,WAAA,KAAgB,MAAA,EAAW,KAAA,CAAM,gBAAA,GAAmB,WAAA;AACxD,MAAA,IAAI,YAAA,KAAiB,MAAA,EAAW,KAAA,CAAM,iBAAA,GAAoB,YAAA;AAC1D,MAAA,IAAI,WAAA,KAAgB,MAAA,EAAW,KAAA,CAAM,gBAAA,GAAmB,WAAA;AAExD,MAAA,IAAI,KAAA,CAAM,eAAA,KAAoB,MAAA,EAAW,KAAA,CAAM,mBAAmB,KAAA,CAAM,eAAA;AACxE,MAAA,IAAI,KAAA,CAAM,iBAAA,KAAsB,MAAA,EAAW,KAAA,CAAM,sBAAsB,KAAA,CAAM,iBAAA;AAAA,IAC/E;AAEA,IAAA,IAAI,MAAM,UAAA,EAAY;AACpB,MAAA,IAAI,MAAM,UAAA,CAAW,WAAA,KAAgB,QAAW,KAAA,CAAM,eAAA,GAAkB,MAAM,UAAA,CAAW,WAAA;AACzF,MAAA,IAAI,MAAM,UAAA,CAAW,eAAA,KAAoB,QAAW,KAAA,CAAM,cAAA,GAAiB,MAAM,UAAA,CAAW,eAAA;AAAA,IAC9F;AACA,IAAA,IAAI,KAAA,CAAM,SAAA,KAAc,MAAA,EAAW,KAAA,CAAM,aAAa,KAAA,CAAM,SAAA;AAE5D,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,GAAG,IAAA,CAAK,sBAAA,CAAuB,IAAI,CAAA,EAAG,GAAG,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,EAAE;AAAA,EAC/F;AAAA,EAEQ,oBAAoB,IAAA,EAA4C;AACtE,IAAA,MAAM,QAA6B,EAAC;AAEpC,IAAA,IAAI,IAAA,CAAK,KAAA,EAAO,KAAA,CAAM,eAAA,GAAkB,IAAA,CAAK,KAAA;AAC7C,IAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,gBAAA,GAAmB,IAAA,CAAK,MAAA;AAE/C,IAAA,IAAI,IAAA,CAAK,IAAA,KAAS,QAAA,CAAS,WAAA,EAAa;AACtC,MAAA,MAAM,QAAQ,IAAA,CAAK,UAAA;AACnB,MAAA,IAAI,KAAA,EAAO,SAAA,EAAW,KAAA,CAAM,UAAA,GAAa,KAAA,CAAM,SAAA;AAC/C,MAAA,IAAI,KAAA,EAAO,cAAA,KAAmB,MAAA,EAAW,KAAA,CAAM,wBAAwB,KAAA,CAAM,cAAA;AAAA,IAC/E;AAEA,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA;AAAA,IACtC;AAEA,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,GAAG,IAAA,CAAK,sBAAA,CAAuB,IAAI,CAAA,EAAG,GAAG,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,EAAE;AAAA,EAC/F;AAAA,EAEQ,cAAA,CAAe,IAAA,EAAgB,WAAA,GAAoC,MAAA,EAA0B;AACnG,IAAA,IAAI,IAAA,CAAK,cAAA,CAAe,IAAI,CAAA,EAAG;AAC7B,MAAA,OAAO,KAAK,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAC,CAAA;AAAA,IACnD;AAEA,IAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,GAAG,CAAA;AAAA,IACxE;AAEA,IAAA,OAAO,CAAC,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAK,aAAA,CAAc,IAAI,CAAA,EAAG,GAAG,CAAA;AAAA,EAC5F;AAAA,EAEQ,eAAe,IAAA,EAAwC;AAC7D,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,WAAW,CAAA,EAAG;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,IAAA,KAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,IAAQ,MAAA,IAAU,IAAA,IAAQ,SAAA,IAAa,IAAI,CAAA;AAAA,EAC5G;AAAA,EAEQ,iBAAiB,GAAA,EAAoC;AAC3D,IAAA,IAAI,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,EAAU;AACnC,MAAA,OAAO;AAAA,QACL,MAAM,GAAA,CAAI,IAAA;AAAA,QACV,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,GAAA,CAAI,SAAS;AAAA,OAC/C;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI;AAAA,KACf;AAAA,EACF;AAAA,EAEQ,cAAc,IAAA,EAAuB;AAC3C,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,UAAU,IAAI,CAAA;AAAA,IAC5B,CAAA,CAAA,MAAQ;AACN,MAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,QAAA,OAAO,CAAA,kBAAA,EAAqB,IAAA,CAAK,WAAA,EAAa,IAAA,IAAQ,QAAQ,CAAA,CAAA,CAAA;AAAA,MAChE;AACA,MAAA,OAAO,OAAO,IAAI,CAAA;AAAA,IACpB;AAAA,EACF;AACF","file":"index.js","sourcesContent":["import type { TracingEvent, AnyExportedSpan, ModelGenerationAttributes } 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\ninterface PostHogMessage {\n role: 'user' | 'assistant' | 'system' | 'tool';\n content: PostHogContent[];\n}\n\ninterface PostHogContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ninterface MastraMessage {\n role: string;\n content: string | MastraContent[];\n}\n\ninterface MastraContent {\n type: string;\n text?: string;\n [key: string]: unknown;\n}\n\ntype SpanData = string | MastraMessage[] | Record<string, unknown> | unknown;\n\nexport interface PosthogExporterConfig extends BaseExporterConfig {\n apiKey: string;\n host?: string;\n flushAt?: number;\n flushInterval?: number;\n serverless?: boolean;\n defaultDistinctId?: string;\n enablePrivacyMode?: boolean;\n}\n\ntype SpanCache = {\n startTime: Date;\n type: SpanType;\n};\n\ntype TraceMetadata = {\n spans: Map<string, SpanCache>;\n distinctId?: string;\n};\n\nexport class PosthogExporter extends BaseExporter {\n name = 'posthog';\n private client: PostHog;\n private config: PosthogExporterConfig;\n private traceMap = new Map<string, TraceMetadata>();\n\n private static readonly SERVERLESS_FLUSH_AT = 10;\n private static readonly SERVERLESS_FLUSH_INTERVAL = 2000;\n private static readonly DEFAULT_FLUSH_AT = 20;\n private static readonly DEFAULT_FLUSH_INTERVAL = 10000;\n\n constructor(config: PosthogExporterConfig) {\n super(config);\n this.config = config;\n\n if (!config.apiKey) {\n this.setDisabled('Missing required API key');\n this.client = null as any;\n return;\n }\n\n const clientConfig = this.buildClientConfig(config);\n this.client = new PostHog(config.apiKey, clientConfig);\n this.logInitialization(config.serverless ?? false, clientConfig);\n }\n\n private buildClientConfig(config: PosthogExporterConfig): {\n host: string;\n flushAt: number;\n flushInterval: number;\n privacyMode?: boolean;\n } {\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 },\n ): void {\n const message = isServerless ? 'PostHog exporter initialized in serverless mode' : 'PostHog exporter initialized';\n\n this.logger.info(message, config);\n }\n\n protected async _exportTracingEvent(event: TracingEvent): Promise<void> {\n if (!this.client) return;\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 });\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 this.logger.warn(`Trace data not found for ended span: ${span.id}`);\n return;\n }\n\n const cachedSpan = traceData.spans.get(span.id);\n if (!cachedSpan) {\n this.logger.warn(`Span cache not found for ended span: ${span.id}`);\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 eventName = this.mapToPostHogEvent(span.type);\n const distinctId = this.getDistinctId(span, traceData);\n const properties = this.buildEventProperties(span, latency);\n\n this.client.capture({\n distinctId,\n event: eventName,\n properties,\n timestamp: new Date(endTime),\n });\n\n traceData.spans.delete(span.id);\n if (traceData.spans.size === 0) {\n this.traceMap.delete(span.traceId);\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 switch (spanType) {\n case SpanType.MODEL_GENERATION:\n case SpanType.MODEL_STEP:\n return '$ai_generation';\n case SpanType.MODEL_CHUNK:\n case SpanType.TOOL_CALL:\n case SpanType.MCP_TOOL_CALL:\n case SpanType.PROCESSOR_RUN:\n case SpanType.AGENT_RUN:\n case SpanType.WORKFLOW_RUN:\n case SpanType.GENERIC:\n default:\n return '$ai_span';\n }\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 private buildEventProperties(span: AnyExportedSpan, latency: number): 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 baseProperties.$ai_parent_id = span.parentSpanId;\n }\n\n if (span.metadata?.sessionId) {\n baseProperties.$ai_session_id = span.metadata.sessionId;\n }\n\n if (span.type === SpanType.MODEL_GENERATION || span.type === SpanType.MODEL_STEP) {\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 if (attrs.usage) {\n const { usage } = attrs;\n const inputTokens = usage.inputTokens ?? usage.promptTokens;\n const outputTokens = usage.outputTokens ?? usage.completionTokens;\n const totalTokens = usage.totalTokens;\n\n if (inputTokens !== undefined) props.$ai_input_tokens = inputTokens;\n if (outputTokens !== undefined) props.$ai_output_tokens = outputTokens;\n if (totalTokens !== undefined) props.$ai_total_tokens = totalTokens;\n\n if (usage.reasoningTokens !== undefined) props.reasoning_tokens = usage.reasoningTokens;\n if (usage.cachedInputTokens !== undefined) props.cached_input_tokens = usage.cachedInputTokens;\n }\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"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { TracingEvent } from '@mastra/core/observability';
|
|
2
|
+
import type { BaseExporterConfig } from '@mastra/observability';
|
|
3
|
+
import { BaseExporter } from '@mastra/observability';
|
|
4
|
+
export interface PosthogExporterConfig extends BaseExporterConfig {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
host?: string;
|
|
7
|
+
flushAt?: number;
|
|
8
|
+
flushInterval?: number;
|
|
9
|
+
serverless?: boolean;
|
|
10
|
+
defaultDistinctId?: string;
|
|
11
|
+
enablePrivacyMode?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class PosthogExporter extends BaseExporter {
|
|
14
|
+
name: string;
|
|
15
|
+
private client;
|
|
16
|
+
private config;
|
|
17
|
+
private traceMap;
|
|
18
|
+
private static readonly SERVERLESS_FLUSH_AT;
|
|
19
|
+
private static readonly SERVERLESS_FLUSH_INTERVAL;
|
|
20
|
+
private static readonly DEFAULT_FLUSH_AT;
|
|
21
|
+
private static readonly DEFAULT_FLUSH_INTERVAL;
|
|
22
|
+
constructor(config: PosthogExporterConfig);
|
|
23
|
+
private buildClientConfig;
|
|
24
|
+
private logInitialization;
|
|
25
|
+
protected _exportTracingEvent(event: TracingEvent): Promise<void>;
|
|
26
|
+
private handleSpanStarted;
|
|
27
|
+
private handleSpanEnded;
|
|
28
|
+
private captureEventSpan;
|
|
29
|
+
shutdown(): Promise<void>;
|
|
30
|
+
private toDate;
|
|
31
|
+
private mapToPostHogEvent;
|
|
32
|
+
private getDistinctId;
|
|
33
|
+
private buildEventProperties;
|
|
34
|
+
private extractErrorProperties;
|
|
35
|
+
private extractCustomMetadata;
|
|
36
|
+
private buildGenerationProperties;
|
|
37
|
+
private buildSpanProperties;
|
|
38
|
+
private formatMessages;
|
|
39
|
+
private isMessageArray;
|
|
40
|
+
private normalizeMessage;
|
|
41
|
+
private safeStringify;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=tracing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracing.d.ts","sourceRoot":"","sources":["../src/tracing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAA8C,MAAM,4BAA4B,CAAC;AAE3G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AA2BrD,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAYD,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,IAAI,SAAa;IACjB,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,QAAQ,CAAoC;IAEpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAM;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAQ;IACzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAM;IAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAS;gBAE3C,MAAM,EAAE,qBAAqB;IAezC,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,iBAAiB;cAST,mBAAmB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;YA0BzD,iBAAiB;YAwBjB,eAAe;YAmCf,gBAAgB;IAexB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,sBAAsB;IAoB9B,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,yBAAyB;IAiCjC,OAAO,CAAC,mBAAmB;IAmB3B,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,aAAa;CAUtB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mastra/posthog",
|
|
3
|
+
"version": "0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939",
|
|
4
|
+
"description": "PostHog observability provider for Mastra",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"CHANGELOG.md"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"require": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.cjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"license": "Apache-2.0",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"posthog-node": "^4.0.1",
|
|
28
|
+
"@mastra/observability": "0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@microsoft/api-extractor": "^7.52.8",
|
|
32
|
+
"@types/node": "^20.19.0",
|
|
33
|
+
"eslint": "^9.37.0",
|
|
34
|
+
"tsup": "^8.5.0",
|
|
35
|
+
"typescript": "^5.8.3",
|
|
36
|
+
"vitest": "^3.2.4",
|
|
37
|
+
"@mastra/core": "0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939",
|
|
38
|
+
"@internal/types-builder": "0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939",
|
|
39
|
+
"@internal/lint": "0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@mastra/core": "0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://mastra.ai",
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/mastra-ai/mastra.git",
|
|
48
|
+
"directory": "observability/posthog"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/mastra-ai/mastra/issues"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=22.13.0"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsup --silent --config tsup.config.ts",
|
|
58
|
+
"build:watch": "pnpm build --watch",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest watch",
|
|
61
|
+
"lint": "eslint ."
|
|
62
|
+
}
|
|
63
|
+
}
|