Ticket 102 (splitting the engine into reader/primary/profile actors) was a single multi-thousand-line ticket covering a new actor topology, an EngineHandle API redesign, a query fan-out layer, moving alerts, and a full test-harness rewrite, with some design decisions deliberately left open. Splitting it into six sequenced tickets (profile actor skeleton + signaling, move metric computation, move alert evaluation, split the handle API, query fan-out, test harness rework) lets each land as its own reviewable commit instead of one large speculative rewrite. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TeyhRfMYjMditek6geDRoQ
4.0 KiB
4.0 KiB
104 — Move metric declarations and bucket computation into the profile actor
Summary
Second slice of the split: metric declarations, apply_all_metrics,
and the declare/update/remove/backfill machinery move off the primary
EngineSnapshot and onto the profile actor's ProfileSnapshot
(stood up in 103-profile-actor-skeleton-and-primary-signaling).
The primary keeps raw log storage and param declarations only, per
0001-actor-split's resolved decision that the primary "extracts
declared + auto params only... no metrics, no profile logic." The
profile actor consumes newly-visible primary lines (via the
watch-wake loop from ticket 103) and runs metric regexes against them
itself, building its own bucket data independent of the primary.
Where
src/engine/snapshot/mod.rs:364-434(validate_metric_request,declare_metric,resolve_backfill_and_store_metric) and:434-487(validate_update_metric,update_metric,remove_metric_declaration) — the declare/update/remove machinery to move ontoProfileSnapshot.src/engine/snapshot/mod.rs:587-617(backfill_metric,apply_all_metrics) — backfill replaysself.logs_range()(a primary-side accessor) throughapply_metric_to_log; once metrics live on the profile actor, backfill needs to read logs through the profile actor's cloned primaryIndexReaderinstead ofself.src/engine/handle.rs—EngineMessage::DeclareMetric/UpdateMetric/RemoveMetricDeclarationarms (see the message list atsrc/engine/message.rs:30-63) currently route through the single actor'swrite.mutateagainstEngineSnapshot; these need to route to the profile actor'sProfileSnapshotinstead.src/engine/handle.rs'sIngestarm —snap.apply_all_metrics(...)is called directly afteringest_paramstoday (see ticket 101's change); this call moves out of the primary's ingest closure entirely once the profile actor computes metrics itself from the lines it observes via the watch/read loop, rather than the primary computing them inline.
Scope
- Move
MetricDeclaration/bucket-relatedIndexKey/DataValuevariants' usage (not necessarily their type definitions, which are shared) ontoProfileSnapshot's own index/map, separate from the primary's. - Move
declare_metric/update_metric/remove_metric_declaration/backfill_metric/apply_all_metrics(and their validation counterparts) to operate onProfileSnapshot, reading raw log text via the profile actor's cloned primaryIndexReaderwherever they needlogs_range-style access, instead ofself.indexon the primary. - Remove the
apply_all_metricscall from the primary'sIngestarm inhandle.rs— the primary no longer computes metrics inline; the profile actor's watch-wake loop (from ticket 103) now callsapply_all_metrics-equivalent logic itself per newly-visible line. DeclareMetric/UpdateMetric/RemoveMetricDeclarationmessages need a new route to the profile actor (a secondmpscchannel, or folding into the profile actor's own message enum) — decide the concrete mechanism during implementation;EngineHandle's public API doesn't need to change yet if this ticket keeps routing internal tohandle.rs(full API surface changes are 106-split-enginehandle-api-for-primary-and-profile's scope).- Out of scope: alert evaluation (still reads the primary's snapshot
directly today — 105-move-alert-evaluation-to-profile-actor
moves it), and the profile-switch (
activate_profile) reload path (still targets whatever this ticket lands as the metric-owning actor, but retargetingsrc/api/mod.rs:812-852explicitly is 106-split-enginehandle-api-for-primary-and-profile's scope). - Backfill cost and blocking behavior: per 0001-actor-split's performance rationale, this move is what stops a slow backfill from blocking the primary's ingest/query-serving — confirm with a test that ingesting new lines on the primary keeps working while the profile actor is mid-backfill on a newly declared metric.