name: community-metrics description: Add or change community metrics in the 6529 SEIZE backend by updating metric rollup enums, recorder methods, recording call sites, optional historical backfills, OpenAPI response models, and community-metrics API aggregation. Use when adding new community metrics, exposing metric summaries or series, tracking community activity, or changing MetricsRecorder/MetricsDb behavior.
Community Metrics
Use this workflow for metrics based on metric_rollup_hour and exposed through /community-metrics.
Workflow
- Define the metric contract before editing:
- enum name in
UPPER_SNAKE_CASE - event source and recording call sites
- aggregation semantics: event count, value sum, latest overwritten value, distinct scoped count, or custom query
- dimensions stored in
scope,key1, orkey2 - whether historical backfill is required
- enum name in
- Locate the current implementation with
rg:MetricRollupHourMetricinsrc/entities/IMetricRollupHour.tsMetricsRecorderinsrc/metrics/MetricsRecorder.tsMetricsDbinsrc/metrics/MetricsDb.ts- community API code in
src/api-serverless/src/community-metrics/ - OpenAPI contract in
src/api-serverless/openapi.yaml
- Add the enum value to
MetricRollupHourMetric. Keep the persisted enum string identical to the enum key. - Add a focused
MetricsRecordermethod. UsemetricsDb.upsertMetricRollupHourwith the current rollup fields:event_countfor occurrence countsvalue_sumfor numeric totals or latest samplesscope,key1, andkey2for dimensions or distinct countingoverwrite: truefor latest-state metrics such as profile counts or network TDH
- Wire the recorder after the primary action succeeds. Pass the existing
RequestContextso timers and transactions are preserved. - Expose the metric only where needed:
- update
src/api-serverless/openapi.yamlresponse schemas for summary, series, or mint metrics - run
cd src/api-serverless && npm run restructure-openapi && npm run generate - update
CommunityMetricsServiceaggregation and mapping - update
community-metrics.routes.tsonly when route validation or query behavior changes
- update
- Add or update tests next to the changed code. Prefer focused service/DB tests; use
src/profiles/abusiveness-check.db.test.tsas the pattern for DB/repository tests. - Run
npm run lintfrom the repo root after changes.
Backfills
Do not create a migration by default. If the user explicitly asks for historical data or the feature would be misleading without it, create a data-only backfill migration:
npm run migrate:new backfill-metric-name-metric
Write SQL in the up migration only, delete the generated .down.sql, and leave the JS down() implementation as a no-op. The repo is entities-first for schema/table changes: prefer TypeORM entities plus dbMigrationsLoop sync, and avoid schema migrations unless the user explicitly asks for one. Reserve migrations primarily for one-off data backfills or rare view changes.
Aggregation Patterns
- Simple counter: increment
event_count: 1, read summedevent_count. - Numeric total: set
value_sumto the numeric delta, read summedvalue_sum. - Latest sample: set
event_count: 1,value_sum, andoverwrite: true, then read the latest sample in the requested period. - Per-identity or per-entity metric: store the dimension in
scope; usekey1andkey2only when a second or third dimension is needed. - Distinct activity: record dimensions consistently and aggregate with
getMetricBucketDistinctCountsor a purpose-built query.
Validation
- Metric name, dimensions, aggregation, and backfill behavior are clear.
- Enum value added to
MetricRollupHourMetricinsrc/entities/IMetricRollupHour.ts. - Recording function created in
MetricsRecorder. - Recording function called in all identified locations.
- Backfill migration created only if explicitly required.
- OpenAPI schema updated and generated types refreshed when API output changes.
- Aggregation logic added to
CommunityMetricsService. - Tests cover recording and exposed aggregation behavior.
-
npm run lintpasses.