Lab session
Prometheus Queries for an Operational Signal
Use PromQL to build and challenge a request-success signal from supplied service telemetry.
Overview¶
In this lab, you use PromQL to turn a service's request counter into an operational signal. You will inspect the available time series, write a query that reports the fraction of successful requests, and challenge that query with a worse traffic profile.
🎯 Learning Goals¶
After completing this lab, you should be able to:
- Read a Prometheus metric's type, labels, and samples
- Compose selectors, aggregation, and arithmetic into a PromQL signal
- Explain the difference between a cumulative counter and a recent rate
- Test whether a query responds to a meaningful change in traffic
Deliverables¶
By the end of the lab, your fork should contain a PromQL expression that reports the fraction of observed GET requests that succeeded and decreases when the supplied traffic profile degrades. You will submit the URL of the specific commit containing that query through Canvas.
Setup¶
Fork the starter repository to your own account and open it in the provided devcontainer. Do not push commits to the upstream course repository. Work entirely in your fork. Run every command in this lab from the repository root.
The devcontainer provides pinned dependencies and starts three services:
- A Node.js app on port 3000 with supplied OpenTelemetry instrumentation
- Prometheus on port 9090, configured to scrape the app every five seconds
- Grafana on port 3001, with Prometheus configured as its data source
The application, instrumentation, scrape configuration, and traffic profiles are complete.
Your work belongs in lab05/success-ratio.promql.
The repository also provides scripts/generate-traffic and scripts/check-lab.
Wait for the devcontainer setup to report Lab 5 is ready and list URLs for all three services.
If it does not, run ./scripts/start-lab from the repository root.
Confirm that the stack is healthy:
docker compose ps
curl --noproxy '*' --fail --silent http://localhost:3000/health
All three services should be healthy, and the second command should print lab05 healthy.
Run ./scripts/check-lab before changing anything.
It should stop after reporting that lab05/success-ratio.promql does not yet contain a query.
Tasks¶
Task 1: Inspect the Supplied Counter¶
Generate the baseline traffic profile:
./scripts/generate-traffic baseline
Open the Prometheus UI on port 9090 and enter the request counter's name in the expression browser:
lab05_requests_total
Use the Table view to inspect the returned series. Identify the labels that distinguish successful requests from not-found requests and compare their cumulative values. Predict what will happen to each series when another request is handled.
Three tools, three jobs
OpenTelemetry is the instrumentation API and SDK used by the application to produce telemetry.
Prometheus periodically scrapes the app's /metrics endpoint, stores the resulting time series, and evaluates PromQL queries.
Grafana can ask Prometheus for data and display the result, but it does not store these application metrics or evaluate the query itself.
Prometheus scrapes cumulative values
The application exposes its current metrics as text on /metrics; it does not push them to Prometheus.
A counter is cumulative since the process started, so its raw value is usually less useful than its rate of change.
Prometheus's rate() function calculates that change from multiple scrapes and also handles counter resets caused by an application restart.
Task 2: Build a Success-Ratio Query¶
Write one PromQL expression in lab05/success-ratio.promql that returns the fraction of observed GET requests whose status is 200.
The result must be one value between 0 and 1, not one value per status.
PromQL lets you select series with label matchers, combine series with an aggregation such as sum(), and apply arithmetic between the resulting vectors.
For example, this shape computes a recent rate for a selected set of series:
sum(rate(METRIC{LABEL="VALUE"}[WINDOW]))
You must determine the metric, label selection, aggregation, and division needed for the ratio. You may base the ratio on the cumulative counters you observed or on a recent range. If you use a range, two minutes includes the samples generated by the lab helper.
Paste the expression into the Prometheus expression browser.
With only the baseline traffic in a fresh stack, the result should be close to 0.8.
A ratio needs a numerator and a population
The successful series provide the numerator. All observed GET requests provide the denominator. Aggregate each side to one value before dividing so that label matching does not split the result or silently produce an empty vector.
Task 3: Challenge the Signal¶
Before generating more traffic, predict how your signal should change if most new requests fail. Then run the degraded profile:
./scripts/generate-traffic degraded
Evaluate your expression again. Its value should be lower than the baseline result. A cumulative ratio and a range-based ratio may move by different amounts because they answer slightly different questions.
Check your reasoning: Which signal reacts faster?
A cumulative ratio includes every request since the process started, so older healthy traffic continues to influence it. A ratio built from recent rates eventually excludes older samples and responds more directly to current behavior.
Run the checker when you are finished:
./scripts/check-lab
The checker starts a clean stack, runs both traffic profiles, and evaluates your submitted expression through the Prometheus API. It checks the signal's range and direction, not one exact PromQL spelling.
Additional Resources¶
- Prometheus querying basics: selectors, label matchers, and range vectors
- Prometheus operators: aggregation and arithmetic
- Prometheus
rate(): converting counter samples into a recent per-second rate
Submission¶
- Commit
lab05/success-ratio.promql, then push that commit to your fork. - Confirm that
git status --shortproduces no output, then run./scripts/check-labone last time. - Submit the URL of that exact commit—not a branch or pull request—using the Canvas link below.
This lab is graded pass/fail.