analyticssim
GitHub用于拦截和检查 PostHog 及 Customer.io 分析调用的模拟服务,支持在测试中验证追踪事件是否触发,提供记录查询、断言及故障注入功能。
Trigger Scenarios
Install
npx skills add langwatch/langwatch --skill analyticssim -g -y
SKILL.md
Frontmatter
{
"name": "analyticssim",
"description": "Catch and inspect PostHog and Customer.io calls with analyticssim, haven's product-analytics stand-in. Use when someone says 'haven analytics', 'did the tracking event fire', 'posthog events', 'customer.io identify', 'analyticssim', 'nurturing calls', 'haven sim analytics', 'haven up +analytics', 'what did the app send to analytics', or needs to assert on analytics in a test.",
"user-invocable": true
}
analyticssim
Fakes PostHog (posthog-node /batch/, posthog-js /e/, /flags/) and Customer.io (CDP
/v1/*, Track API). Every call becomes one normalized record in memory. Keys are accepted
and never checked: a dev shim, never expose it. Code: services/sims/analyticssim, console
apps/sims/src/analytics.
Run it
- Opt-in:
haven up +analytics(sticky). Runs in thegolane by default (seesims). - Console and ingest base URL:
https://analytics.<slug>.langwatch.localhost;haven statusshows the loopback port. - The overlay points the PostHog host and Customer.io base at it with dummy keys where none
is set. Standalone:
make service svc=analyticssim(:5596).
Inspect and assert
GET /_sim/api/records?provider=posthog|customerio&kind=event|identify|alias|group&id=&name=
GET /_sim/api/status
DELETE /_sim/api/records
GET|PUT /_sim/api/settings {"forcedError": 0|4xx|5xx}: capture calls (PostHog, Customer.io) answer that status
Records carry provider, kind, distinctId, name, properties, receivedAt and raw.
Newest first. Assert: trigger the action, then filter by id and name.
Seed and reset
ANALYTICSSIM_SEED=1(haven sets it) loads sample PostHog and Customer.io records.- Reset with
DELETE /_sim/api/records; a restart also empties it (nothing persists).
Tests and load
- Post PostHog batches or Customer.io calls at the loopback port; 16 MiB body cap.
- The store is a fixed ring: adding is O(1).
ANALYTICSSIM_MAX_RECORDS(default 5000),ANALYTICSSIM_MAX_RAW_BYTES(default 65536; bigger raw bodies become a size marker). Benchmark:go test -bench . -benchmem ./services/sims/analyticssim.
From a terminal or agent
--json on every read; non-zero exit on failure; --stack <slug> reads another worktree.
haven sim analytics status # record count + activity (last 5 min, distinct ids, last call)
haven sim analytics list [--provider] [--kind] [--event|--name] [--id] | clear
haven sim analytics record <id> # one record: properties, raw call (no public `get` yet: the CLI's internal spelling)
haven sim analytics fault <4xx|5xx|off> # the next capture calls fail with that status; off clears it
haven sim analytics wait --event <name> [--provider] [--kind] [--id] [--timeout 30s] # exit 66 on timeout
The console shows the same: an Activity panel, provider tabs, kind and search filters, and "Records for this id" on a record narrows the list to that distinct id.
Version History
- c0c14dc Current 2026-10-19 19:31


