Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Hogflare is not a full PostHog clone. It does not try to ship PostHog's complete
- [PostHog Compatibility](docs/posthog-compatibility.md): SDK setup, endpoint behavior, persons, groups, feature flags, signing, and enrichment.
- [Import Existing PostHog Data](docs/import-posthog.md): host-side backfill importer for existing PostHog projects.
- [Data Model](docs/data-model.md): event and person row shapes plus DuckDB/R2 SQL query examples.
- [`models/`](models): semantic model definitions for events, sessions, pageviews, persons, identity, groups, attribution, retention, and shared metrics.
- [`models/`](models): semantic model definitions for events, sessions, pageviews, persons, identity, groups, attribution, retention, error tracking, and shared metrics.

## Architecture

Expand Down
299 changes: 299 additions & 0 deletions assets/vendor/POSTHOG-JS-LICENSE

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions assets/vendor/posthog-exception-autocapture-1.373.4.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ new_sqlite_classes = ["PersonIdCounterDurableObject", "GroupDurableObject"]
| `HOGFLARE_REPLAY_EVENTS_TABLE` | No | Iceberg events table queried by replay APIs. Defaults to `default.hogflare_events`. |
| `HOGFLARE_REPLAY_QUERY_LIMIT` | No | Maximum snapshot rows a replay API request can read. Defaults to `5000`. |
| `POSTHOG_SIGNING_SECRET` | No | Enables HMAC request signature checks. |
| `PERSON_DEBUG_TOKEN` | No | Enables `/__debug/person/:id` for deployment verification. |
| `PERSON_DEBUG_TOKEN` | No | Enables authenticated administrative endpoints: `/__debug/person/:id` and error issue status updates. |
| `HOGFLARE_FEATURE_FLAGS` | No | JSON flag config used by `/decide` and `/flags`. |

## Secrets
Expand Down
14 changes: 14 additions & 0 deletions docs/posthog-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,24 @@ Set the SDK host/base URL to your Worker (`https://<your-worker>.workers.dev`) a
- `/alias` creates aliases.
- `/batch` accepts mixed event payloads.
- `/e` accepts browser event payloads.
- `/i/v0/e` accepts PostHog error tracking event payloads.
- `/engage` accepts people updates.
- `/groups` accepts `$groupidentify` payloads.
- `/s` accepts session replay payloads.

## Error Tracking

PostHog SDK error tracking is supported through normal capture ingestion. `posthog.captureException(error, properties)` sends a `$exception` event with `$exception_list`, stack frames, mechanism metadata, optional `$exception_steps`, and any custom properties; Hogflare forwards those fields unchanged to the pipeline.

The documented PostHog manual ingestion endpoint `/i/v0/e/` is also available and uses the same browser event normalization as `/e/`. SDK remote config advertises exception autocapture support and serves the `exception-autocapture.js` helper expected by `posthog-js`.

Error tracking semantic models:

- `error_events` normalizes `$exception` rows into exception type, value, stack frame, fingerprint, user, session, URL, SDK, and grouping fields.
- `error_issues` groups exception events into issue rollups with first/last seen, event count, affected users, affected sessions, latest sample, and status.

Issue status is append-only. `PATCH /errors/api/issues/:fingerprint/status` writes a trusted `$error_issue_status` event with `status` set to `active`, `resolved`, or `ignored`; `error_issues` derives the latest trusted status for that project. The request must include an `api_key` identifying the project and an `x-hogflare-debug-token` header matching `PERSON_DEBUG_TOKEN`. Status updates are disabled when that token is not configured. Client-captured events named `$error_issue_status` are retained as ordinary events but cannot change issue state.

## Persons

Identify, capture `$set` / `$set_once` / `$unset`, and alias events update a person record stored in a Durable Object. The record tracks distinct ID aliases, person properties, and a sequential `id` plus a UUID.
Expand Down
6 changes: 5 additions & 1 deletion docs/product-analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ Product analytics shares the same R2 Data Catalog warehouse credentials as repla
| `HOGFLARE_ANALYTICS_MODEL_DIR` | Optional Sidemantic model directory. Defaults to `models`. |
| `HOGFLARE_ANALYTICS_SIDEMANTIC_SCRIPT` | Optional override for the native analytics worker script. |
| `HOGFLARE_ANALYTICS_PREAGG` | Optional Sidemantic pre-aggregation switch. Defaults to enabled. Set to `0` to disable. |
| `HOGFLARE_ANALYTICS_PREAGG_REFRESH` | Optional materialization switch. Defaults to enabled. Set to `0` to query the source models without building local rollups. |
| `HOGFLARE_ANALYTICS_PREAGG_SCHEMA` | Optional DuckDB schema for Sidemantic rollup tables. Defaults to `sidemantic_preagg`. |
| `HOGFLARE_ANALYTICS_PREAGG_DATABASE` | Optional local DuckDB path used to persist pre-aggregation partitions across worker restarts. Defaults to an account-and-bucket-specific file under `/tmp`. |
| `HOGFLARE_ANALYTICS_PREAGG_REFRESH_INTERVAL_SECONDS` | Optional bounded refresh cadence. Defaults to `3600` seconds. |
| `HOGFLARE_ANALYTICS_PREAGG_FULL_REFRESH_INTERVAL_SECONDS` | Optional full reconciliation cadence for historical backfills. Defaults to `86400` seconds. |

## Routes

Expand All @@ -25,4 +29,4 @@ Product analytics shares the same R2 Data Catalog warehouse credentials as repla
- `/analytics/api/charts` returns overview metrics, a focused trend, and semantic breakdowns including domains, referrers, browser, country, region, and city leaderboards.
- `/replay` serves the replay feature.

At worker startup, Sidemantic materializes known count-based chart shapes into daily pre-aggregation rollups and automatically routes eligible queries through those tables. `metric`, `dimension`, and `granularity` choose the focused chart. `semantic_filters` carries clickable cross-filter state as a JSON object of semantic dimensions to values. Analytics leaderboards use a fixed top-10 row cap plus an Others row.
At worker startup, Sidemantic bootstraps the complete history for known count-based chart shapes. It then refreshes recent day or month partitions on the configured cadence and, by default, performs a persisted full reconciliation daily so historical backfills and offline events cannot remain stale indefinitely. The local DuckDB file preserves partitions and the reconciliation watermark across worker restarts. `metric`, `dimension`, and `granularity` choose the focused chart. `semantic_filters` carries clickable cross-filter state as a JSON object of semantic dimensions to values. Analytics leaderboards use a fixed top-10 row cap plus an Others row.
Loading
Loading