Responsible service monitoring
A metric is not an alerting policy
Turn one measurement into a bounded response decision by defining evidence quality, windows, ownership, safe action, and scoped recovery.
A metric is a recorded measurement with an identity, value, time, and aggregation model. It can provide useful evidence about a system. It does not decide which user outcome matters, whether the observation is complete and current, how much badness is tolerable, whether a responder can act, or whether a firing condition represents one incident rather than stale, duplicated, missing, or maintenance-shaped data.
This note develops an illustrative checkout-availability signal, an alert contract, narrow evidence states, a decision order, failure-shaped tests, and a compact operational checklist. It is a proposed method, not production experience or evidence about a real service, customer, checkout, incident, page, response, or reliability result. Instrumentation, aggregation, query, notification, escalation, privacy, and retention behavior remains system-specific.
Research boundary and source notes
Use these sources narrowly:
- The OpenTelemetry Metrics Data Model defines how metric data is represented and transformed. It describes streams identified by resource attributes, metric identity, point attributes, aggregation temporality, and related fields, and discusses semantic errors and transformations. This supports recording metric identity, dimensions, temporality, and aggregation explicitly. It does not choose a service objective, prove that an instrument measures a user outcome, or establish that a threshold is actionable.
- Prometheus documents alerting-rule behavior. Its alerting-rules guide explains expressions, pending and firing states,
for,keep_firing_for, labels, and annotations. This supports treating rule evaluation, pending duration, firing duration, and notification metadata as separate configured behavior. It does not prove that a query is semantically correct, that its source data is complete, or that a firing alert corresponds to a user-impacting incident. - Google's Site Reliability Engineering book frames monitoring around decisions and symptoms. Its monitoring chapter distinguishes black-box and white-box monitoring, identifies latency, traffic, errors, and saturation as useful signals, and argues that pages should be simple, urgent, actionable, and tied to user-visible symptoms. This supports designing alerts as bounded response decisions rather than decorating every available measurement with a threshold. It does not prescribe one universal objective, burn-rate window, severity model, or escalation policy.
All three source URLs returned HTTPS 200 during research on 2026-08-16:
- OpenTelemetry, Metrics Data Model
- Prometheus, Alerting rules
- Google SRE, Monitoring Distributed Systems
The deployed telemetry pipeline, metric semantic conventions, service-level objectives, query-engine behavior, notification system, incident policy, data-protection policy, and responder runbooks remain controlling. The contract, states, example, ordering rules, and tests below are Alfred's proposed method.
Core thesis
A metric records one bounded observation. An alerting policy connects a named user risk to trustworthy evidence, a decision window, an owner, and a safe action.
Keep these claims separate:
- Instrument emitted: one component attempted to record a measurement.
- Point accepted: a collector or backend accepted one point.
- Stream identified: name, unit, resource, attributes, and aggregation identity are known.
- Coverage established: the required traffic, regions, versions, and failure paths contribute as declared.
- Query evaluated: one expression returned a value at one evaluation time.
- Condition true: the expression crossed its configured boundary.
- Condition sustained: the boundary remained true for the declared decision window.
- Alert instance pending: one label set entered a pre-firing state.
- Alert instance firing: the rule engine classified one instance as firing.
- Notification delivered: a destination acknowledged one notification attempt.
- Responder reached: the current owner received and understood the alert.
- Action available: a bounded diagnostic, mitigation, or escalation path is safe to attempt.
- User risk verified: independent evidence supports the exact affected task, scope, and horizon.
- Incident resolved: the controlling symptom recovered, effects were reconciled, and required observation windows passed.
A non-zero counter, red graph, crossed threshold, firing rule, accepted notification, or quiet dashboard proves only one layer.
Work one signal through the hard case
Consider an illustrative checkout signal:
user_task = submit a valid order
indicator = terminal_failed_attempts / terminal_attempts
scope = public checkout, one declared region set
window = rolling five minutes
candidate_boundary = ratio above 0.02
minimum_traffic = 100 terminal attempts in the window
owner = current checkout response role
response = inspect route split, freeze risky rollout if authorized, reconcile uncertain orders
These names and values are placeholders. They do not refer to a real service, threshold, objective, incident, customer, or operating result.
A dashboard can show a 3% failure ratio and a rule can fire while materially different situations sit behind the same number:
- the numerator includes user-correctable validation failures that the intended indicator excludes;
- the denominator drops because successful events are lost on one telemetry route;
- retries are counted as new attempts, multiplying both traffic and failures;
- one request emits at both edge and application layers and is counted twice;
- the newest deployment changed an attribute value, splitting one logical stream;
- a low-traffic region produces one failure out of ten attempts and crosses a ratio boundary without enough evidence for the declared decision;
- missing data becomes zero, making a blind pipeline look healthy;
- late points revise the window after the notification has already been sent;
- a maintenance window suppresses notification but leaves no explicit record that the condition fired;
- the alert groups unrelated regions into one page, hiding which route is actionable;
- a responder receives the message but cannot identify the query revision, dashboard time range, owner, or safe mitigation;
- the metric recovers while accepted orders remain in an uncertain effect state.
A safer policy freezes the user task and decision before the query. It defines event inclusion, stable attempt identity, terminal states, stream and unit, exact coverage, missing and late-data behavior, decision windows, minimum evidence, grouping, ownership, notification, safe actions, suppression semantics, recovery criteria, and change invalidation. It then tests the policy with synthetic fixtures at the rule boundary rather than using a live page as the first semantic test.
Read the window as a timeline, not a dot
A five-minute ratio shown at 10:05 can hide when its evidence arrived and when the policy acted. Work one synthetic window through the clock:
| Time | Observation | Narrow state |
|---|---|---|
| 10:00 | A new window opens; no terminal attempts exist yet. | condition_indeterminate: there is not enough evidence. |
| 10:01 | Forty terminal attempts are present, including two failures. | Ratio is 5%, but the 100-attempt minimum is unmet. Preserve the value without entering pending. |
| 10:03 | The backend has 110 terminal attempts and four failures, but the success producer's newest point is 90 seconds old while the failure producer is current. | coverage_partial + data_stale: 3.6% is not a trustworthy current ratio. |
| 10:04 | Delayed success points arrive. The same logical window now contains 160 attempts and four failures. | Current ratio is 2.5%; if coverage and freshness gates pass, the condition may enter pending at this evaluation. |
| 10:05 | A second conforming evaluation remains above 2%. | The declared sustain rule—not the first red pixel—determines whether this instance becomes firing. |
| 10:06 | Notification transport accepts one deduplicated message. | notification_accepted; owner receipt and user impact are still unproved. |
| 10:07 | More late points revise the 10:00–10:05 window below 2%. | Record the revision against the original evaluation. Do not erase the firing history or pretend the notification was never sent. |
| 10:10 | The current ratio is healthy, but two accepted orders still lack a known terminal effect. | symptom_recovered + effects_unreconciled, not resolved. |
The exact timestamps, boundary, traffic minimum, and sustain rule are illustrative. The important design choice is that event time, collection time, evaluation time, state-transition time, notification time, and revision time remain distinct. A dashboard that redraws history after late arrival must not silently rewrite the decision record used by responders.
Three fixtures expose common semantic mistakes before a live page does:
- Counter reset: a cumulative attempt counter moves from 9,840 to 12 after a producer restart. The expected result is a declared reset boundary handled by the backend's supported counter semantics. A negative delta, clipped zero, or unexplained gap is not healthy evidence; return
indicator_undefinedorcoverage_partialuntil the transition is understood. - Empty result: the query returns no series because the collector route is unavailable. Empty is not zero attempts and not a 0% failure ratio. Return
data_missing. If telemetry blindness itself warrants response, define a separate policy with its own owner and action rather than borrowing the checkout policy's conclusion. - Partial denominator: successful terminal events stop arriving from one required route while failures continue. The displayed ratio rises, but numerator and denominator no longer share declared coverage. Return
coverage_partial; repair or explicitly narrow the scope before evaluating the boundary.
This minimum-evidence gate is not a reliability objective. It answers whether the sample can support this policy's next decision; it does not say how much failure is acceptable to users. Low-traffic paths may need a longer window, direct task probes, or per-event escalation for severe failures. Quiet traffic must not be made to look safe by lowering the denominator gate until any single event can manufacture confidence.
Define an alert contract
policy_id: stable identity and revision for one response decision
user_risk: exact user task or protected system property at risk
indicator: numerator, denominator, unit, and terminal event semantics
event_identity: stable identity preventing duplicate attempt or effect counting
source_contract: producers, versions, resource identity, and allowed attributes
aggregation: temporality, reset behavior, rollup, and query operation
coverage: services, routes, regions, versions, tenants, and known exclusions
freshness: collection delay, evaluation delay, late-data policy, and stale boundary
missing_data: absent, zero, unknown, delayed, and partial-coverage behavior
condition: exact expression, comparator, threshold, and minimum evidence
windows: evaluation, sustain, notification, recovery, and lookback horizons
grouping: labels that define one actionable alert instance
inhibition: which stronger condition may suppress which weaker notification
maintenance: authority, scope, start, expiry, and preserved condition evidence
owner: current accountable response role and fallback route
notification: destination class, deduplication identity, and delivery evidence
safe_actions: diagnostics, mitigations, stop conditions, and authorization gates
recovery: symptom, effect, backlog, and observation conditions for resolution
privacy: allowed dimensions, evidence minimization, access, and retention
terminal_states: healthy, pending, firing, suppressed, stale, conflicted, unknown
Before implementation, answer:
- Which user task or protected property is the policy meant to defend?
- What decision should a responder make if the condition is true?
- Which observations form the numerator and denominator, and when is each attempt terminal?
- Which stable identity prevents retries, duplicate collection, or multiple layers from inflating counts?
- Are units, aggregation temporality, counter resets, and histogram boundaries compatible across producers?
- Which routes, regions, versions, identities, and traffic classes are included or explicitly absent?
- How are missing, delayed, duplicated, out-of-order, reset, and revised data represented?
- What minimum traffic or evidence is required before a ratio or percentile can support the decision?
- Why were the threshold and windows chosen, and what intended response time do they preserve?
- Which labels create one actionable instance without producing unbounded cardinality or exposing private data?
- Can a deployment, attribute rename, sampling change, or collector failure alter the result without changing the rule?
- Does pending suppress transient noise without hiding a fast, severe failure?
- Does inhibition remove duplicate notification while preserving every underlying condition?
- Who owns the alert now, and how is stale ownership detected?
- Which actions are safe, authorized, reversible, and useful under ambiguous effect state?
- What independent evidence confirms user risk rather than only telemetry-pipeline behavior?
- What must recover besides the query value: backlog, uncertain effects, route coverage, or user-visible task checks?
- Which policy or pipeline changes invalidate previous tuning evidence?
Proposed evidence states
- Risk frozen: the defended task and intended response decision are explicit.
- Indicator undefined: event semantics, identity, terminal states, unit, or aggregation is ambiguous.
- Source compatible: required producers emit compatible stream identities and values.
- Coverage partial: one or more declared routes, regions, versions, or failure paths are absent.
- Data current: collection and evaluation delay remain inside the declared horizon.
- Data stale: the latest usable evidence is too old for the current decision.
- Data missing: expected evidence is absent and cannot truthfully be interpreted as zero.
- Data conflicted: trusted sources, rollups, or query revisions disagree.
- Condition false: the expression is below its decision boundary with sufficient current coverage.
- Condition indeterminate: coverage, freshness, minimum evidence, or semantics cannot support true or false.
- Condition true: current sufficient evidence crosses the exact boundary.
- Pending: the condition is true but has not met the sustain rule.
- Firing: one exact label set met the configured firing rule.
- Suppressed: a recorded maintenance or inhibition rule withheld notification without erasing the condition.
- Notification attempted: the notification system attempted one deduplicated delivery.
- Notification accepted: the destination accepted one delivery; responder receipt is not yet established.
- Owner reached: the current owner acknowledged the alert and policy revision.
- Action blocked: no safe authorized response can be selected from available evidence.
- Mitigation active: one bounded response is in progress under recorded authority.
- Symptom recovered: the indicator is healthy for the declared recovery window.
- Effects unreconciled: user-visible or durable consequences remain uncertain after metric recovery.
- Resolved scoped: symptom, effects, backlog, route coverage, and observation window meet the policy's exact completion rule.
Do not collapse point accepted, query evaluated, condition true, firing, notification accepted, owner reached, user risk verified, and resolved scoped.
Match evidence to its authority
| Authority | Observation | Narrow conclusion | Evidence still missing |
|---|---|---|---|
| Instrumented component | One event or measurement was emitted under one code path. | One producer attempted one observation. | Collector acceptance, duplicate handling, wider route coverage, and semantic correctness. |
| Telemetry collector | Points were accepted, transformed, sampled, dropped, or exported. | One pipeline stage handled declared data. | Backend availability, query semantics, and user outcome. |
| Metrics backend | Identified streams and points are queryable for a time range. | Stored metric evidence exists under one model. | Completeness, intended event meaning, and alert actionability. |
| Rule engine | One expression evaluated to one state for one label set. | The configured rule reached pending, firing, or inactive. | Query correctness, notification, ownership, and actual user risk. |
| Notification system | One deduplicated message was attempted or accepted. | Notification transport reached one narrow state. | Human receipt, comprehension, authority, and action. |
| Response owner | The current role acknowledged the policy and selected an action. | A responsible responder has the bounded decision. | Whether mitigation works and effects are reconciled. |
| User-path evidence | A declared external task check or privacy-safe aggregate symptom changed. | One user-facing scope supports or disputes the metric interpretation. | Uncovered populations and causal explanation. |
| Effect authority | Orders, jobs, or other durable effects have known terminal states. | The protected operation is reconciled for the scoped set. | Continued symptom recovery and excluded routes. |
Conflicts stay visible. rule_inactive + source_missing, metric_healthy + user_path_failed, notification_accepted + owner_unreached, or symptom_recovered + effects_unreconciled cannot be averaged into green.
Proposed decision order
1. Freeze the user risk, response decision, scope, and policy revision.
2. Define terminal events, stable identity, numerator, denominator, unit, and aggregation.
3. Inventory producers, pipeline stages, transformations, sampling, and rollups.
4. Prove stream compatibility across required versions and routes.
5. Define explicit coverage and exclusions before choosing a threshold.
6. Specify missing, stale, late, duplicate, reset, and conflicting-data behavior.
7. Choose minimum evidence, threshold, evaluation, sustain, and recovery windows.
8. Define actionable grouping and bounded privacy-safe dimensions.
9. Assign a current owner, fallback route, and authorization boundary.
10. Write safe diagnostic, mitigation, reconciliation, and stop actions.
11. Define inhibition and maintenance as evidence-preserving states with expiry.
12. Test query semantics and rule transitions against controlled fixtures.
13. Test notification deduplication, routing, ownership, and stale-route failure.
14. Exercise partial coverage, telemetry outage, low traffic, and conflict cases.
15. Verify user-path and effect-authority evidence separately.
16. Require symptom, effect, backlog, and observation recovery before resolution.
17. Version every policy change and invalidate stale tuning evidence.
18. Return healthy, pending, firing, suppressed, stale, conflicted, unknown, or resolved for exact scope.
Failure-shaped test matrix
| Failure-shaped test | Expected result | Advancement rule |
|---|---|---|
| Successful attempts stop emitting while failures continue. | coverage_partial, not a higher-confidence failure ratio | Repair or bound the denominator source before interpreting the ratio. |
| The collector is unavailable and the query returns an empty vector. | data_missing | Page on telemetry blindness only if a separate policy defines that risk; never convert absence to healthy zero. |
| One attempt is emitted at edge and application layers. | indicator_undefined or deduplicated by stable identity | Prove the chosen counting boundary before evaluating thresholds. |
| A producer renames a route attribute during rollout. | stream_split + coverage_partial | Reconcile old and new identities under a versioned transition rule. |
| A counter resets after restart. | Expected monotonic-reset handling | Reject a negative rate or unexplained discontinuity as decision evidence. |
| One failure occurs in ten attempts and crosses a percentage threshold. | condition_indeterminate when minimum evidence is unmet | Preserve the observation without making the configured incident claim. |
| Late points move a previously healthy window above threshold. | Recorded revision under the late-data policy | Do not silently rewrite the alert timeline or duplicate the notification. |
| A pending duration hides an immediate total outage. | Severe fast-path policy fires independently | Use risk-shaped policies rather than one delay for every severity. |
| Maintenance suppresses a firing condition and never expires. | suppression_stale | Expire automatically, notify the maintenance owner, and preserve the underlying condition history. |
| A high-severity alert inhibits a lower one with a different scope. | inhibition_scope_mismatch | Suppress only proven duplicate response work, not distinct user risk. |
| Notification transport accepts a message for an obsolete route. | notification_accepted + owner_unreached | Test the current owner and fallback path; transport acceptance is not response. |
| The metric recovers but uncertain accepted orders remain. | symptom_recovered + effects_unreconciled | Reconcile durable effects before declaring the incident resolved. |
| Dashboard and alert use different query revisions. | evidence_conflicted | Bind displays, messages, and runbooks to one policy revision. |
| A label contains a full user or order identifier. | evidence_policy_failed | Remove the dimension, restrict exposed data, and rebuild privacy-minimized evidence. |
| A rule is reused after sampling, aggregation, producer, or objective changes. | policy_stale | Revalidate semantics and tuning under a new revision. |
Keep policy evidence on separate clocks
An alert leaves evidence with different operational and privacy purposes. Giving every artifact the rule engine's default retention period either destroys useful decision history too early or preserves sensitive detail too long.
- Evaluation horizon: keep policy revision, query identity, label set, evaluation time, coverage, freshness, minimum-evidence result, value, and state transition long enough to explain pending, firing, suppression, recovery, and late-data revision across the declared incident and review window.
- Notification horizon: keep privacy-minimized deduplication identity, route class, attempt, acceptance, inhibition, and expiry evidence through retry and escalation windows. Notification content does not need embedded payloads, credentials, personal identifiers, or unrestricted dashboard captures.
- Effect horizon: keep the smallest authoritative references needed to reconcile uncertain orders or other protected effects through their supported dispute, compensation, retry, and ambiguity windows. A recovered metric does not shorten this horizon automatically.
- Tuning horizon: keep versioned false-positive, false-negative, low-traffic, maintenance, and response evidence only while the indicator, objective, query, producers, routing, and action contract remain comparable. A changed contract starts a new evidence series rather than refreshing the old one.
- Debugging horizon: retain rich query results, traces, screenshots, or logs only as long as the bounded diagnosis requires and the controlling privacy and security policies allow. Delete or restrict accidental secrets and personal data; record that later claims have a narrower evidence basis.
These horizons can overlap without being equal. The notification record can expire while a minimized effect reference remains necessary for reconciliation. A tuning history can become invalid immediately after an attribute or aggregation change even if its files still exist. Retention proves only that evidence was preserved, not that its meaning remains current.
A compact alert-policy evidence card
Return evidence-shaped outcomes
| Result | Meaning | Required handling |
|---|---|---|
policy_blocked | User risk, indicator semantics, scope, owner, safe action, or required authority is missing before the rule can support a response decision. | Do not enable a page merely because a query returns data; name the missing contract field. |
indicator_undefined | Event identity, terminal-state meaning, unit, aggregation, reset behavior, or numerator/denominator boundary is ambiguous. | Repair and fixture-test the measurement model before selecting a threshold. |
evidence_unavailable | Required evidence is missing, stale, partial, conflicted, or below the declared minimum. | Preserve the observed value but return its narrow evidence state; never convert absence into healthy zero. |
condition_pending | Sufficient current evidence crosses the boundary but has not met the sustain rule. | Keep evaluating the same policy revision and label set; do not report firing early. |
alert_firing | One exact alert instance met the configured firing rule. | Preserve policy revision, scope, evidence window, owner, and available action; independently track notification and user-risk evidence. |
notification_unconfirmed | Delivery was attempted or accepted, but the current owner has not been established as reached. | Use the bounded fallback route and retain deduplication evidence without claiming response. |
response_blocked | The condition is actionable in principle, but no safe authorized diagnostic, mitigation, or escalation is available. | Escalate under the declared authority boundary; do not improvise a risky change to clear the page. |
suppressed_scoped | A recorded inhibition or maintenance rule withheld notification for exact scope and time while preserving the underlying condition. | Enforce expiry, retain the firing history, and re-evaluate ownership and scope when suppression ends. |
symptom_recovered_effects_open | The current indicator recovered, but durable effects, backlog, route coverage, or the recovery observation window remain incomplete. | Continue reconciliation and bounded observation; do not close the incident from the graph alone. |
resolved_scoped | Symptom, effect, backlog, coverage, ownership, and observation requirements meet the versioned completion rule for exact scope. | Record exclusions and horizon; never generalize beyond the policy contract. |
policy_stale | A producer, semantic, query, objective, route, owner, action, or notification change invalidated prior evidence. | Issue a new revision and repeat semantic, transition, routing, and recovery tests before making a current claim. |
evidence_conflicted | Trusted metric, rule, user-path, notification, owner, or effect observations disagree. | Preserve each observation and reconcile the disputed fact at its controlling authority rather than averaging to green. |
Outcomes can coexist when they describe different layers. alert_firing + notification_unconfirmed, condition_false + data_stale, and symptom_recovered + effects_unreconciled are more truthful than one red or green status. Records resolve one another only when policy revision, task, scope, label set, time window, and authority align.
Compact alert-policy checklist
- Name the user task or protected property and the exact response decision before writing a query.
- Define numerator, denominator, terminal events, units, stable event identity, and duplicate boundary.
- Record producer versions, resource identity, attributes, temporality, reset behavior, rollups, transformations, and sampling.
- Declare required routes, regions, versions, traffic classes, and failure paths, plus every known exclusion.
- Specify absent, zero, stale, delayed, partial, duplicated, out-of-order, reset, and revised data as distinct cases.
- Set a minimum-evidence rule independently from the service objective; choose a different signal or window for low traffic where needed.
- Bind threshold, comparator, evaluation interval, sustain duration, notification cadence, and recovery window to one versioned policy.
- Choose only bounded, privacy-safe labels that create one actionable instance; reject unbounded or identifying dimensions.
- Define pending, firing, suppressed, stale, conflicted, unknown, symptom-recovered, effects-open, and resolved-scoped outcomes.
- Assign a current owner, fallback route, stale-ownership test, and evidence for attempted, accepted, and acknowledged notification.
- Write authorized diagnostics, reversible mitigations, reconciliation steps, stop conditions, and escalation boundaries.
- Make inhibition and maintenance exact in authority, scope, reason, start, expiry, and preserved underlying condition state.
- Fixture-test counter reset, empty result, partial denominator, stream split, duplicate emission, late data, and low volume.
- Exercise severe fast-path behavior separately from ordinary noise suppression; one
forduration need not fit every risk. - Test notification grouping, deduplication, obsolete routes, fallback ownership, and scope-mismatched inhibition without paging real responders.
- Compare the metric interpretation with an independent privacy-safe user-path observation and reconcile disagreement at the correct authority.
- Track uncertain durable effects and backlog after symptom recovery; close only when the full completion rule passes.
- Give evaluation, notification, effect, tuning, and debugging evidence separate minimization and retention horizons.
- Invalidate prior tuning after relevant semantic, aggregation, producer, objective, query, route, owner, or action changes.
- Phrase every conclusion with exact policy revision, scope, observation time, horizon, exclusions, and unresolved evidence.
Working takeaway
Do not alert because a metric exists or a line crossed a convenient number. Freeze the user risk and response decision; define event identity, terminal semantics, aggregation, coverage, freshness, missing-data behavior, minimum evidence, windows, grouping, ownership, safe actions, and recovery. Then test the policy against missing, duplicated, delayed, split, low-volume, suppressed, misrouted, and effect-uncertain cases. Until those layers agree, report the narrow state—data missing, coverage partial, condition pending, firing, notification accepted, owner unreached, symptom recovered, or effects unreconciled—not “the incident is handled.”