Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b1f322d
alerting-first-rule-lj: add install-datasources milestone
BeverlyJaneJ Jul 26, 2026
9b3a886
alerting-first-rule-lj: replace "form" with "new alert rule page"
BeverlyJaneJ Jul 26, 2026
3bba6b1
alerting-first-rule-lj: rework query to watch QuickPizza 5xx errors
BeverlyJaneJ Jul 27, 2026
2feb7c2
alerting-first-rule-lj: simplify build-query intro
BeverlyJaneJ Jul 27, 2026
60672a1
alerting-first-rule-lj: collapse section intros and pre-fill alert name
BeverlyJaneJ Jul 27, 2026
9cffeeb
alerting-first-rule-lj: tighten alert-name step copy
BeverlyJaneJ Jul 27, 2026
5c85ce6
alerting-first-rule-lj: fix build-query selectors and step wording
BeverlyJaneJ Jul 27, 2026
82609fd
alerting-first-rule-lj: use stable Select value testid in build-query
BeverlyJaneJ Jul 27, 2026
2b70e75
alerting-first-rule-lj: rework set-condition milestone
BeverlyJaneJ Jul 27, 2026
fee7182
alerting-first-rule-lj: rework configure-labels-evaluation milestone
BeverlyJaneJ Jul 27, 2026
fb29d42
alerting-first-rule-lj: rework set-evaluation-behavior milestone
BeverlyJaneJ Jul 27, 2026
1090f17
alerting-first-rule-lj: rework configure-handling, select-contact-poi…
BeverlyJaneJ Jul 28, 2026
6728fa5
alerting-first-rule-lj: fix save-rule selector and tighten business-v…
BeverlyJaneJ Jul 28, 2026
0ce3ce8
alerting-first-rule-lj: add Keep firing for step to set-evaluation-be…
BeverlyJaneJ Jul 28, 2026
1e472aa
alerting-query-language-lj: initial learning path
BeverlyJaneJ Jul 28, 2026
80d5796
PR #482: add reviewer rationale notes
BeverlyJaneJ Jul 28, 2026
a5920ae
alerting-create-silence-lj: rework create-silence milestone
BeverlyJaneJ Jul 28, 2026
b3e10f2
PR #482: restructure and expand reviewer notes
BeverlyJaneJ Jul 28, 2026
20b5596
PR #482: remove reviewer notes
BeverlyJaneJ Jul 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions alerting-create-silence-lj/create-silence/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
"blocks": [
{
"type": "markdown",
"content": "You'll open the silence form, set a time window, add label matchers that select which alerts to suppress, verify the affected instances, and submit.\n\nIn this milestone, you create a silence from start to finish."
"content": "You'll open the **Silences** page, set a time window, add label matchers that select which alerts to suppress, verify the affected instances, and submit.\n\nIn this milestone, you create a silence from start to finish."
},
{
"type": "section",
"id": "open-silence-form",
"title": "Open the silence form",
"title": "Start a new silence",
"blocks": [
{
"type": "interactive",
Expand All @@ -22,8 +22,8 @@
{
"type": "interactive",
"action": "highlight",
"reftarget": "a[href*='/alerting/silence/new']",
"content": "Click **Add silence** to open the silence creation form.",
"reftarget": "a[href*='alerting/silence/new']",
"content": "Click **Create silence** to start a new silence.",
"requirements": ["on-page:/alerting/silences"],
"verify": "on-page:/alerting/silence/new"
}
Expand All @@ -35,18 +35,31 @@
"title": "Set the silence time window",
"requirements": ["section-completed:open-silence-form"],
"blocks": [
{
"type": "interactive",
"action": "highlight",
"reftarget": "label:contains('Silence start and end')",
"content": "The **Silence start and end** field shows two timestamps: when the silence starts and when it ends. By default, the start is now and the end is two hours from now, so the silence lasts two hours.",
"doIt": false,
"requirements": ["on-page:/alerting/silence/new"]
},
{
"type": "interactive",
"action": "noop",
"content": "In the **Silence start and end** picker, set when the silence begins and ends. For a maintenance window, set the start to now and the end to when the work finishes."
"content": "If you need custom times, click the field to open an **Absolute time range** menu, set **From** and **To**, then click **Apply time range**. Otherwise, skip to the **Duration** field."
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "#duration",
"content": "Alternatively, set the **Duration** field and Grafana calculates the end time for you.\n\nUse a duration that matches the work, for example, `2h` for a short maintenance window or `1d` for a longer migration. Valid units: `y`, `M`, `w`, `d`, `h`, `m`, `s`.",
"content": "Set the **Duration** field to how long you want the silence to last, and Grafana calculates the end time for you.",
"doIt": false,
"requirements": ["on-page:/alerting/silence/new"]
},
{
"type": "interactive",
"action": "noop",
"content": "The default `2h` works for a short deployment. Use `1d` for a longer migration. Valid units are years (y), months (M), weeks (w), days (d), hours (h), minutes (m), and seconds (s)."
}
]
},
Expand All @@ -60,23 +73,28 @@
"type": "interactive",
"action": "highlight",
"reftarget": "#matcher-0-label",
"content": "Under **Refine affected alerts**, enter the label name to match in the **Label** field, for example, `severity` or `team`.",
"content": "Under **Refine affected alerts**, enter a label that's on one of your alerts. If you followed the first-rule journey, copy `severity` and paste it into the **Label** field.",
"doIt": false,
"requirements": ["on-page:/alerting/silence/new"]
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "#matcher-0-value",
"content": "Enter the matching value in the **Value** field, for example, `warning` or `database`. The operator defaults to equals (`=`); change it if you need a regex or not-equals match.\n\nOnly alerts whose labels match every matcher you add are silenced. The more matchers you add, the narrower the silence.",
"content": "Copy `critical` and paste it into the **Value** field so the matcher becomes `severity=critical`. The operator defaults to equals (`=`). Change it if you need a regex or not-equals match.",
"doIt": false,
"requirements": ["on-page:/alerting/silence/new"]
},
{
"type": "interactive",
"action": "noop",
"content": "Only alerts whose labels match every matcher you add are silenced. The more matchers you add, the narrower the silence."
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "button:contains('Add matcher')",
"content": "Click **Add matcher** to add another label matcher if you need to narrow the silence further.",
"content": "Click **Add matcher** if you want to narrow the silence further, for example, adding `team=platform` alongside `severity=critical` silences only critical alerts owned by the platform team.",
"doIt": false,
"requirements": ["on-page:/alerting/silence/new"],
"skippable": true
Expand All @@ -92,13 +110,13 @@
{
"type": "interactive",
"action": "noop",
"content": "Review the **Affected alert instances** preview below the matchers. It lists the alert instances your matchers currently select.\n\nIf the preview is empty or includes alerts you didn't intend to silence, adjust your matchers before submitting."
"content": "Review the **Affected alert instances** preview below the matchers. It lists any alert instances currently firing that match your matchers.\n\nWith `severity=critical`, you should see the alerts you created in the previous sections. If the preview is empty, the silence still catches alerts that start firing during the window."
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "#comment",
"content": "Enter a **Comment** describing why you're creating the silence, for example, `Database upgrade maintenance window`. This helps your team understand the silence later.",
"content": "Replace the auto-populated text in the **Comment** field with a short reason, for example, `Database upgrade in progress`. Grafana records the creation time separately, so the timestamp isn't needed here.",
"doIt": false,
"requirements": ["on-page:/alerting/silence/new"]
},
Expand Down
129 changes: 76 additions & 53 deletions alerting-first-rule-lj/build-query/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"blocks": [
{
"type": "markdown",
"content": "The query defines what data Grafana monitors. You point the rule at a data source, choose a metric, filter it down to what matters, and apply operations that transform the raw data into something useful.\n\nThis milestone uses the **grafanacloud-play-prom** Prometheus data source from the QuickPizza tutorial data sources. You build the query in **Builder** mode, targeting a real HTTP request counter from the QuickPizza demo service."
"content": "You'll build an alert that watches the QuickPizza app for server errors. You'll use Builder mode instead of using a query language."
},
{
"type": "section",
Expand All @@ -15,20 +15,34 @@
"has-datasource:grafanacloud-play-prom"
],
"blocks": [
{
"type": "markdown",
"content": "You'll point the alert rule at the Prometheus data source that came with the QuickPizza tutorial data sources."
},
{
"type": "interactive",
"action": "formfill",
"reftarget": "input[data-testid='data-testid Select a data source']",
"targetvalue": "grafanacloud-play-prom",
"content": "In the **Define query and alert condition** section, open the data source picker and select **grafanacloud-play-prom**.",
"tooltip": "Pick the Prometheus data source from the QuickPizza tutorial data sources.",
"content": "Choose the data source that holds the metric you want to alert on. For this tutorial, `grafanacloud-play-prom` is filled in for you — it's the Prometheus data source from the QuickPizza tutorial data sources.",
"tooltip": "Prometheus data source from the QuickPizza tutorial data sources.",
"requirements": [
"on-page:/alerting/new/alerting"
]
}
]
},
{
"type": "section",
"id": "toggle-explain",
"title": "Turn on Explain (optional)",
"skippable": true,
"blocks": [
{
"type": "interactive",
"action": "highlight",
"reftarget": "[data-testid='data-testid prometheus explain switch wrapper']",
"content": "Toggle **Explain** on. Grafana narrates what each part of your query does in plain English — a fast way to learn what you're clicking without knowing PromQL syntax.",
"requirements": [
"on-page:/alerting/new/alerting"
],
"skippable": true,
"doIt": false
}
]
Expand All @@ -37,19 +51,12 @@
"type": "section",
"id": "use-builder-mode",
"title": "Confirm Builder mode",
"requirements": [
"section-completed:select-data-source"
],
"blocks": [
{
"type": "markdown",
"content": "The Prometheus query editor has two modes: **Builder** (visual, point-and-click) and **Code** (write PromQL by hand). Builder is the fastest way in when you're new to Prometheus, and it's the default for new queries."
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "div[data-testid='data-testid QueryEditorModeToggle']",
"content": "Above the query field, confirm **Builder** is selected. If you're on **Code**, click **Builder** to switch.",
"content": "Make sure **Builder** mode is selected. This mode lets you build the query without using PromQL.",
"requirements": [
"on-page:/alerting/new/alerting"
],
Expand All @@ -62,104 +69,120 @@
"type": "section",
"id": "choose-metric",
"title": "Choose the metric",
"requirements": [
"section-completed:use-builder-mode"
],
"blocks": [
{
"type": "markdown",
"content": "The **Metric** field is where you tell Prometheus which time series to query. QuickPizza exposes an HTTP request counter you can alert on."
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "button[aria-label='Open metrics explorer']",
"content": "Click the **Metric** drop-down and select `quickpizza_server_http_request_duration_seconds_count`.\n\nIf you can't find the Metric from the dropdown, Click the **Open metric explorer** button and search for the metric.\n\nThis is a counter that increments every time QuickPizza handles an HTTP request. It's exactly the kind of counter you'd alert on in production.",
"reftarget": "[data-testid='data-testid metric select']",
"content": "Copy `quickpizza_server_http_requests_total` from this step, paste it into the **Metric** drop-down, then select it from the list. This counter tracks every HTTP request QuickPizza's services handle, labeled with the response `status`. It's the raw material for the alert.",
"tooltip": "Paste the metric name here, then pick it from the list.",
"doIt": false,
"requirements": [
"on-page:/alerting/new/alerting"
],
"doIt": false
]
}
]
},
{
"type": "section",
"id": "add-label-filter",
"title": "Narrow down with a label filter",
"requirements": [
"section-completed:choose-metric"
],
"title": "Filter to server errors",
"blocks": [
{
"type": "markdown",
"content": "QuickPizza has multiple services. A label filter narrows the query to just the one you care about — the public API, which handles customer traffic."
"type": "interactive",
"action": "highlight",
"reftarget": "[data-testid='data-testid Select label']",
"content": "In the **Label filters** row, open the **Label** drop-down and select `status`. The raw metric covers *all* requests — the `status` label lets you narrow it down.",
"tooltip": "Pick status from the list.",
"requirements": [
"on-page:/alerting/new/alerting"
]
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "[data-testid='data-testid Select label']",
"content": "Below the metric picker, in the **Label filters** row, open the **Label** drop-down and select `service_name`.",
"reftarget": "[data-testid='data-testid Select match operator']",
"content": "Open the operator drop-down and change `=` to `=~`. The `=~` operator does a regex match, so one filter catches every 5xx code at once (500, 502, 503, and so on).",
"tooltip": "=~ is Prometheus regex-match; = is exact-match.",
"doIt": false,
"requirements": [
"on-page:/alerting/new/alerting"
],
"doIt": false
]
},
{
"type": "interactive",
"action": "highlight",
"reftarget": "[data-testid='data-testid Select value']",
"content": "In the value picker next to `service_name`, select `quickpizza-public-api`.\n\nYour query now returns only the HTTP request counter for QuickPizza's public API.",
"content": "In the **Select value** box, enter `5..`, then press Enter. That regex matches any three-digit status starting with 5, so the query now returns only server errors.",
"tooltip": "Enter 5.. and press Enter.",
"doIt": false,
"requirements": [
"on-page:/alerting/new/alerting"
],
"doIt": false
]
}
]
},
{
"type": "section",
"id": "add-rate-operation",
"title": "Convert the counter to a rate",
"requirements": [
"section-completed:add-label-filter"
],
"id": "add-increase-operation",
"title": "Add Increase (5m)",
"blocks": [
{
"type": "markdown",
"content": "Counters only ever go up, so the raw value isn't useful for alerting. Applying **Rate** turns the counter into a per-second rate — how many requests QuickPizza is currently serving. That's what you actually want to compare against a threshold."
"type": "interactive",
"action": "button",
"reftarget": "Operations",
"content": "The metric is a *counter* that only goes up, so its raw value doesn't tell you whether errors just happened. `increase()` fixes that. Click **+ Operations** to open the picker.",
"requirements": [
"on-page:/alerting/new/alerting"
]
},
{
"type": "interactive",
"action": "noop",
"content": "Select **Range functions**, then **Increase**. Set the range to `5m` — the query now counts new errors in the last 5 minutes."
}
]
},
{
"type": "section",
"id": "add-sum-operation",
"title": "Sum across services (optional)",
"skippable": true,
"blocks": [
{
"type": "interactive",
"action": "button",
"reftarget": "Operations",
"content": "Click **+ Operations** to add a function to your query. In the picker, select **Range > Rate** and `$__rate_interval`.\n\nGrafana wraps your query with `rate(...[$__rate_interval])` under the hood — but you never touched PromQL.",
"content": "Without `Sum`, you get one number per QuickPizza service — noisier, harder to read. Summing gives one total so the alert answers \"is QuickPizza having errors *anywhere*?\" Click **+ Operations** again to open the picker.",
"requirements": [
"on-page:/alerting/new/alerting"
],
"doIt": false
"skippable": true
},
{
"type": "interactive",
"action": "noop",
"content": "Select **Aggregations**, then **Sum**. Grafana wraps your `increase()` result in a single total across all services."
}
]
},
{
"type": "section",
"id": "preview-query",
"title": "Preview the query",
"requirements": [
"section-completed:add-rate-operation"
],
"blocks": [
{
"type": "interactive",
"action": "button",
"reftarget": "Run queries",
"content": "Click **Run queries** to preview the data your query returns.\n\nYou should see a line that fluctuates in the low single digits — the real-time HTTP request rate for QuickPizza's public API. If the preview is empty, double-check that you selected `grafanacloud-play-prom` and the metric name is correct.",
"content": "Click **Run queries** to preview the data. You should see `0` while QuickPizza is healthy, jumping above zero when 5xx errors happen in the last 5-minute window. If the preview is empty, double-check the data source, metric name, and label filter.",
"requirements": [
"on-page:/alerting/new/alerting"
]
},
{
"type": "markdown",
"content": "Your query now returns a real per-second request rate from QuickPizza. In the next milestone, you set the condition that decides when this rate is high enough to fire an alert."
"content": "Your query now counts QuickPizza's 5xx errors over the last 5 minutes. In the next milestone, you set the condition that fires the alert the moment that count goes above zero."
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion alerting-first-rule-lj/build-query/website.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ keywords:
- alerting
- query
weight: 400
step: 4
step: 5
layout: single-journey
cta:
type: continue
8 changes: 6 additions & 2 deletions alerting-first-rule-lj/business-value/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
"blocks": [
{
"type": "markdown",
"content": "An alert rule turns your telemetry into action. It watches a query, decides when something is wrong, and notifies the right people through the right channel — so you find out about problems before your users do.\n\nEvery alert rule is built from the same pieces: a query that defines what to watch, a condition that decides when to fire, labels and a folder that organize and route it, evaluation settings that control timing, and notification settings that decide who hears about it. In this path, you build all of them in order."
"content": "An alert rule watches your data, fires when something looks wrong, and notifies the right people. You hear about problems before your users do."
},
{
"type": "markdown",
"content": "This path uses the QuickPizza tutorial data sources, which you install as a prerequisite before you begin. In the next milestone, you open the alert rule form and give your rule a clear name."
"content": "In this path, you build every part of an alert rule in order:\n\n- A query that picks what to watch\n- A condition that decides when to fire\n- A folder and labels that organize and route it\n- Evaluation settings that control how often it runs and how long it must be wrong before firing\n- A contact point and message that decide who hears about it and what they see"
},
{
"type": "markdown",
"content": "You'll use the QuickPizza tutorial data sources. The next milestone installs them, then the one after opens the new alert rule page so you can name your rule."
}
]
}
2 changes: 1 addition & 1 deletion alerting-first-rule-lj/business-value/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"tier": "cloud"
},
"depends": [],
"recommends": ["alerting-first-rule-navigate-to-form"],
"recommends": ["alerting-first-rule-install-datasources"],
"suggests": [],
"provides": []
}
Loading
Loading