05

Prometheus as the Local Metrics Engine

Source: “Building an Observability Platform: From Prometheus to Mimir, Loki, Tempo, and Grafana” — Chapter 5, “Metrics: Prometheus as the Local Metrics Engine”

The enterprise problem and today’s slice

Enterprise problem: Operators need low-latency rates, ratios, distributions, and alert conditions from changing targets, but raw events are too expensive to scan for every operational decision.

Whole-course context: The collector topology and signal contract are incoming; today builds the local metrics path from discovery and scraping through storage, PromQL, rules, dashboards, and alert production.

Today’s slice: Operate one autonomous Prometheus for a bounded environment, design metrics and labels, write reviewable PromQL, and validate recording and alerting rules.

End-of-day evidence: A scrape-and-query packet containing target health, four PromQL results, evaluated rule states, and a synthetic symptom tied to a release.

Still unsolved: Notification routing, cardinality governance at fleet scale, multi-cluster querying, durable long retention, and distributed ingestion remain deferred.

Customer use cases

Metrics become useful only when they answer an operational question with controlled dimensions. These cases cover service health and capacity decisions.

Use case IDActorCustomer jobSuccess outcomeDenial or recovery evidence
D05-UC-01Service operatorDetect a sustained checkout error or latency regression and identify its scopePromQL shows impact by service, region, and release and an alert enters pending then firing stateMissing targets, absent labels, or insufficient traffic produces explicit no-data evidence rather than a false healthy result
D05-UC-02Capacity engineerMeasure CPU saturation and request demand before changing capacityComparable rate and saturation windows support a documented scaling decisionA scrape gap or counter reset is identified and excluded or handled in the query

Actor-centred user stories

Dashboard presence is not acceptance, so these stories require query results and their failure semantics.

Story IDUse case IDsUser storyObservable acceptance conditions
D05-US-01D05-UC-01As a service operator, I want error ratio and p99 latency by bounded service dimensions, so that I can distinguish a release regression from a regional dependency failureQueries return labelled series, target health is visible, and a synthetic symptom changes the matching rule state
D05-US-02D05-UC-02As a capacity engineer, I want request rate and CPU saturation over matched windows, so that I can scale from observed demand rather than snapshotsQuery packet records range, step, target coverage, counter-reset handling, and before-and-after capacity decision

End-to-end product flows

A Prometheus result can be wrong while still looking plausible, so the flows include discovery, scrape health, query semantics, and terminal evidence.

Flow IDUse case IDsPathTriggerNumbered stepsTerminal evidence
D05-FLOW-01D05-UC-01HappyOperator opens a checkout symptom panel1. Confirm target discovery and up.<br>2. Query request rate.<br>3. Compute error ratio.<br>4. Compute p99 from histogram buckets.<br>5. Group by bounded scope.<br>6. Inspect rule state.Actor, environment, query strings, time range, series count, target health, values, rule state, release, and immutable packet ID
D05-FLOW-02D05-UC-01, D05-UC-02RecoveryA target disappears or restarts during analysis1. Detect up == 0 or missing series.<br>2. Inspect scrape error.<br>3. Preserve counter-reset-safe rate.<br>4. Separate no-data from zero.<br>5. Restore target.<br>6. Re-run queries.Scrape error, outage window, query treatment, recovered target, unaffected target control, and packet ID
D05-FLOW-03D05-UC-02HappyCapacity review starts for checkout1. Select matched traffic windows.<br>2. Query request rate.<br>3. Query CPU non-idle ratio.<br>4. Compare saturation and latency.<br>5. Record capacity action and threshold.Matched-window queries, target coverage, observed saturation, decision owner, expected result, and review ID

System design derived from the flows

Treating Prometheus as only a database hides the acquisition and evaluation stages that determine correctness. The system owns discovery, scrape scheduling, local time-series storage, PromQL, and rule evaluation as one bounded metrics engine.

Use case IDEntry pointResponsible servicesAuthoritative storeFailure evidence
D05-UC-01Grafana panel or Prometheus query APIService discovery, scraper, local TSDB, PromQL engine, rule managerPrometheus local TSDB and rule-state memory; rule definitions in version controlTarget down, scrape error, no data, query error, stale series, or non-firing synthetic symptom
D05-UC-02Capacity review query packetScraper, TSDB, PromQL engine, capacity evidence servicePrometheus TSDB for samples; capacity evidence store for reviewed decisionsIncomplete target coverage, unmatched windows, resets mishandled, or query packet missing

Data model and ownership

Metrics are identified by complete label sets, so ownership must cover both series identity and the reviewed artifacts derived from it. Application records are never copied into this model.

Generated-application database: Not created in this slice — Prometheus owns time-series samples and the platform stores rule/query evidence; business data remains source-owned.

Record or entityStore and ownerPrimary keyForeign key or opaque referenceTenant keyMaterial constraintLifecycle and deletionUse case IDs
ScrapeTargetPrometheus service-discovery state, metrics platformtarget_fingerprintOpaque workload and discovery referencesorganization_idAddress plus final label set is unique within PrometheusAppears and disappears with discovery; historical samples follow retentionD05-UC-01, D05-UC-02
TimeSeriesPrometheus local TSDB, metrics platformseries_fingerprintOpaque metric-family referenceorganization_idMetric name plus complete label set uniquely identifies a seriesSamples compacted into blocks and deleted by configured retentionD05-UC-01, D05-UC-02
RuleRevisionVersion control and rule catalogue, service ownerrule_revision_idOpaque repository commitorganization_idExpression, duration, labels, annotations, and owner are immutable by revisionVersioned permanently; deployment status expires by policyD05-UC-01
QueryPacketOperational evidence store, reliability engineeringquery_packet_idOpaque Prometheus, rule, incident, and release referencesorganization_idQuery, range, step, target coverage, and result digest are requiredRetained through review; source samples expire independentlyD05-UC-01, D05-UC-02

Prometheus in one process

Metrics operations fail when teams assume collection, storage, and alerting are separate services but configure only one of them. Prometheus combines target discovery, HTTP scraping, a local time-series database, PromQL query execution, recording-rule evaluation, and alert production.

Pull-based scraping lets Prometheus control interval and expose collection health. Targets come from static configuration or service discovery, and every scrape creates samples carrying timestamps and the final label set. The up metric makes reachability visible, but a healthy scrape does not prove the application metric is semantically correct.

Metric model and types

Unbounded event detail makes aggregate analysis uneconomical, so a Prometheus series is identified by metric name plus the complete set of labels. A new label value creates a new series.

  • A counter increases until process restart; apply rate() over a window.
  • A gauge rises or falls, such as queue depth or active connections.
  • A histogram counts observations in buckets and supports aggregation across instances.
  • A summary calculates client-side streaming statistics; configured quantiles generally cannot be aggregated meaningfully across instances.

Prefer histograms for fleet latency. Ensure the selected bucket boundaries cover the service-level objective and keep the le label when aggregating classic histogram buckets.

PromQL from symptoms to scope

Raw series are not operational conclusions, so PromQL selects, transforms, and aggregates them. Record the query window and grouping because both change meaning.

Request rate:

sum by (service) (
  rate(http_server_requests_total[5m])
)

Error ratio:

sum by (service) (
  rate(http_server_requests_total{status_code=~"5.."}[5m])
)
/
sum by (service) (
  rate(http_server_requests_total[5m])
)

p99 latency from classic histogram buckets:

histogram_quantile(
  0.99,
  sum by (service, le) (
    rate(http_server_request_duration_seconds_bucket[5m])
  )
)

CPU non-idle ratio:

1 - avg by (instance) (
  rate(node_cpu_seconds_total{mode="idle"}[5m])
)

Instant queries evaluate at one time; range queries evaluate repeatedly across an interval. A graph’s step controls evaluation density, not raw scrape frequency.

Recording and alerting rules

Repeated expensive expressions slow dashboards and duplicate logic, so recording rules precompute a named series at evaluation time.

groups:
  - name: service-rates
    interval: 30s
    rules:
      - record: service:http_requests:rate5m
        expr: |
          sum by (service) (
            rate(http_server_requests_total[5m])
          )

Alerting rules turn a symptom expression into alert state. The for duration avoids paging on a short blip; labels route responsibility, while annotations explain impact and the next action.

groups:
  - name: checkout-alerts
    rules:
      - alert: CheckoutHighErrorRatio
        expr: |
          sum(rate(http_server_requests_total{service="checkout",status_code=~"5.."}[5m]))
          /
          sum(rate(http_server_requests_total{service="checkout"}[5m]))
          > 0.05
        for: 10m
        labels:
          severity: page
          team: commerce
        annotations:
          summary: Checkout error ratio is above 5 percent
          runbook_url: https://runbooks.example.com/checkout-errors

Prometheus determines whether the alert is active. Notification grouping, suppression, routing, and delivery belong to Alertmanager.

Practical metrics checks

A query that returns a number may still omit targets or mishandle absence, so validate the whole path.

  1. Inspect discovered targets and scrape errors.
  2. Compare expected workload replicas with up series.
  3. Restart a target and prove rate() handles the counter reset.
  4. Stop traffic and distinguish a zero rate from missing data.
  5. Generate bounded errors long enough to exercise pending and firing states.
  6. Confirm the alert carries owner, severity, service, environment, and runbook.

Key takeaways

Prometheus is an autonomous local metrics engine, not merely a storage component.

  • Discovery and scraping determine which samples exist.
  • Metric name plus complete label set defines a time series.
  • Counters need rates; fleet latency usually needs aggregatable histograms.
  • PromQL semantics depend on windows, grouping, and missing-data treatment.
  • Recording rules precompute queries; alerting rules produce alert state, not notifications.

Checklist

Use this checklist before depending on a local Prometheus for operational decisions.

  • [ ] Discovery covers every expected target and exposes scrape failures.
  • [ ] Metric names, units, types, and bounded labels are documented.
  • [ ] PromQL handles resets, missing data, and aggregation correctly.
  • [ ] Histograms have useful buckets and preserve le during aggregation.
  • [ ] Rules are versioned, tested, owned, and linked to action.
  • [ ] Synthetic symptoms exercise pending, firing, and resolved states.

Sources