HarperFast / HarperFast/harper
recordAnalytics: support arbitrary key/value dimensions
- Dominant language
- JavaScript
- Stars
- 89
- Forks
- 10
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 200
Description
`server.recordAnalytics` currently accepts only three fixed positional dimensions (`path`, `method`, `type`), which forces consumers to encode unrelated dimensions into those slots or split a metric into multiple metrics. The PXG team has asked for a custom-dimensions API.
## Desired API
Additive to the current signature (existing 3-positional form remains supported for back-compat):
```ts
recordAnalytics(value: number | boolean, metric: string, dimensions?: Record): void;
```
Example:
```ts
recordAnalytics(1000, 'response_time', { device_type: 'mobile', status_code: 200 });
```
## Implementation notes
- Current impl ([resources/analytics/write.ts:729](resources/analytics/write.ts)) builds the aggregation key by concatenating `metric-path-method-type`. With variable dimensions, the key needs a stable canonicalization (sorted keys, joined). Cardinality of the dimension set affects memory in `activeActions`.
- Downstream consumers (the analytics report payload, listeners via `addAnalyticsListener`, and storage in the `analytics` table) need to surface custom dimensions — likely as a nested object rather than the current flat fields.
- Existing `path` / `method` / `type` callers and dashboards should continue to work unchanged.
## Acceptance criteria
- New dimensions-object form is supported alongside the positional form.
- Aggregation correctly groups records sharing the same `(metric, dimensions)` tuple.
- Reported analytics include custom dimensions in a structured way that the metrics exporter / Grafana plugin can consume.
- Document the new signature; deprecate the positional form in docs (without removing).
## Open design questions (keeps this Not Ready)
- Cardinality guardrails — recommend bounded values (status code, device type) and warn against unbounded ones (user IDs). Should we enforce a per-metric dimension allowlist or a cardinality cap at recording time? Without guardrails, customer misuse could blow up memory in `activeActions` and storage size.
- How should custom dimensions surface in the existing Prometheus exporter and Grafana plugin? Mapping a variable-cardinality record onto Prometheus labels requires a registration step.
- Naming / collision rules with the reserved `path` / `method` / `type` keys.
---
Tracked in Jira: [CORE-3075](https://harperdb.atlassian.net/browse/CORE-3075)
🤖 Filed by Claude on behalf of Kris.
Contributor guide
Assessment
This issue has not been assessed yet.