When a check runs, a simple pass or fail tells you the outcome but not the context, severity, or next steps. To make a check result genuinely useful, include the check name, timestamp, actual vs. expected values, units, a severity level, a unique identifier, and a link to logs or evidence. This article explains each component, why it matters, and how to structure results for humans and automated systems.
Why Pass/Fail Is Not Enough
A binary result is the minimum viable output. It answers “did it work?” but leaves out “how close was it?” and “what do I do now?” For example, a disk space check that fails at 95% usage is different from one that fails at 99.9%, but both show “fail” without extra data. Including metrics lets you prioritize: a 95% failure might wait until business hours, while a 99.9% failure warrants an immediate page. Without context, every failure looks the same, leading to alert fatigue or missed emergencies.
Core Components of a Useful Check Result
Every check result should carry a standard set of fields so that any consumer (dashboard, alerting system, or human) can interpret it without guessing. At minimum, include:
- Check name and ID – a stable identifier like
disk_usage_prod_dbso you can track history. - Timestamp – when the check ran, in UTC or with a timezone offset.
- Status – pass, fail, or an intermediate state like “warning” or “unknown”.
- Measured value – the actual number the check observed, e.g., 78.4% disk usage.
- Expected or threshold value – the limit, e.g., 80% warning, 90% critical.
- Units – percent, milliseconds, bytes, count, etc. Without units, a value is meaningless.
- Severity or priority – info, warning, critical, so responders can triage.
- Source or host – which server, service, or component the check ran on.
- Output or message – a short human-readable description like “Disk usage exceeded 90% threshold”.
- Link to evidence – a URL to logs, metrics, or a trace that shows why the check failed.
These fields form the backbone of a result. Without them, you have a flag with no context.
How to Structure the Result for Machines and Humans
A well-structured result is both parseable by software and readable by people. Use a standard format like JSON for machine consumption, and include a plain-text summary for humans. For example:
{
"id": "disk_usage_prod_db",
"timestamp": "2025-04-01T14:30:00Z",
"status": "fail",
"value": 94.2,
"unit": "%",
"threshold": 90,
"severity": "critical",
"host": "db-01.example.com",
"message": "Disk usage exceeded critical threshold",
"evidence_url": "https://metrics.example.com/db-01/disk"
}
This structure allows alerting systems to filter by severity, dashboards to graph values over time, and humans to click through to logs. A good rule: if a new engineer can look at the result and know what to do, it has enough context.
Adding Context: Thresholds, History, and Comparisons
A single result is a snapshot. To make it actionable, include historical context or a comparison to previous runs. For example, if a latency check fails at 500ms, knowing that the median for the past hour was 200ms tells you this is a spike, not a baseline. Many monitoring systems include a “previous value” or “trend” field. Similarly, include the threshold type (absolute, relative, or dynamic) so the reader knows whether the limit is fixed or based on a baseline. If you use dynamic thresholds, state the window (e.g., “compared to same time last week”).
Common Mistakes and How to Avoid Them
Even with the right fields, results can be misleading. Common pitfalls include:
- Missing units – a value of 2048 could be bytes, kilobytes, or something else. Always specify.
- Ignoring timezone – timestamps without timezone cause confusion across teams. Use UTC.
- Overloading the message – a message that says “check failed” adds no value. Instead, say “HTTP 503 from /health on web-02”.
- Not including the threshold – without it, you can’t tell if the failure was marginal or severe.
- Using vague severity levels – define what “warning” and “critical” mean in your context, e.g., “warning = actionable within 24h”.
Avoiding these mistakes makes results self-explanatory.
Severity Levels and When to Use Them
Severity levels help route alerts to the right people. Common levels are:
- Info – the check ran and passed, or a non-actionable event occurred.
- Warning – something is approaching a threshold but hasn’t breached it. Example: disk at 85% when critical is 90%.
- Critical – a threshold was breached and immediate action is needed.
- Unknown – the check could not determine a result, e.g., a timeout or missing data.
Use severity to drive alerting rules: critical pages on-call, warning goes to a chat channel, info is logged. This prevents alert fatigue while ensuring nothing slips through.
How to Choose What to Include (and What to Leave Out)
Not every check needs every possible field. The key is to include enough for a responder to act without opening the logs. Ask: “What would I need to know to fix this?” If the check is for a cron job, include the job name and exit code. If it’s an API endpoint check, include the response time and status code. If it’s a data quality check, include the number of rows affected. Avoid dumping raw stack traces into the result; link to them instead. A good rule of thumb: the result should be readable in 10 seconds and give a clear next step.
Frequently Asked Questions
Should I include a unique ID for every check result?
Yes. A unique ID (like a UUID or a sequential number) lets you reference a specific result in logs, tickets, or discussions. Without it, you can’t easily correlate a failure with a particular run.
What’s the difference between status and severity?
Status is the outcome (pass/fail/warning/unknown). Severity is the impact level (info/warning/critical). A check can fail with low severity (e.g., a non-critical backup) or pass with high severity (e.g., a security scan that passed but is still important). They serve different purposes: status tells you what happened, severity tells you how much to care.
How do I handle checks that return multiple metrics?
Include each metric as a separate field or as a nested object. For example, an HTTP check might have status_code, response_time_ms, and content_length. The overall status can be derived from the most critical metric, but keep all values in the result for analysis.
Should I include the output of the command or script?
Include a short summary, but not the full output. A full log can be thousands of lines and will be ignored. Put the full output in a linked file or log aggregator, and include only the key lines in the result.
How do I make results consistent across different teams?
Define a standard schema (like the JSON example above) and enforce it with a shared library or template. Document the meaning of each field and severity level. This ensures that a result from a database team looks the same as one from a frontend team.
What if my check doesn’t have a numeric value?
Some checks are boolean, like “is service running?” In that case, set value to 1 or 0, or use a string like “running”/”stopped”. Still include a message and timestamp. The key is to be explicit about what was checked and what was found.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Valheim Server Not Showing in Community List Fixes
- DisplayPort vs HDMI: Which Cable Should You Use?
- Soundbar vs 2.1 Speaker System: Which Is Better?
- Survive Lava for Brainrot Tier List170 points
- MySQL Dump Import: Fix Common Errors
- Mouse Moving on Its Own? Causes & Fixes