{% extends "base.html" %} {% from "_macros.html" import crumbs, page_header, stat_tile %} {# One monitor: its state and for how long, latency and uptime against Settings → Thresholds (latency against its own normal once it has one, with its anomalies), its response time over the last day, its last checks, the failures behind them and how it is set up. #} {% block title %}{{ monitor.name }} — Monitors — Steward{% endblock %} {% block breadcrumb %}{{ crumbs([("Monitors", "/monitors/"), (monitor.name, "")]) }}{% endblock %} {% block content %} {% set can_edit = session.user_role in ['operator', 'admin'] %} {% call page_header(monitor.name, (monitor.type|monitor_type) ~ " · " ~ monitor.target) %} {% if can_edit %} Edit
{{ csrf_field() }}
{{ csrf_field() }}
{% endif %} {% endcall %}
{% set since_hint = ((("for at least " if since_at_least else "for ") ~ (since|ago|striptags|replace(" ago", ""))) if since and state in ("up", "down", "degraded") else none) %} {{ stat_tile("State", status_info(state)[1], state=state, hint=since_hint) }} {% if latest and latest.response_ms is not none %} {{ stat_tile("Latency", "%.0f ms"|format(latest.response_ms), state=latency[0], hint=latency[1]) }} {% endif %} {% for window in ("24h", "7d", "30d") %} {% set pct = uptime.get(window) %} {{ stat_tile("Uptime " ~ window, "%.2f%%"|format(pct) if pct is not none else "—", state=status_class(pct, "uptime")) }} {% endfor %} {% if tls_days is not none %} {{ stat_tile("TLS certificate", "expired" if tls_days < 0 else (tls_days|round|int) ~ " days", state="crit" if tls_days < 0 else status_class(tls_days, "tls_days")) }} {% endif %}
{% with back="/monitors/" ~ monitor.id, base_resource=monitor.name %}{% include "_anomaly_card.html" %}{% endwith %} {% set timed = history | selectattr("ms", "ne", none) | list %} {% if timed|length > 1 %}

Response time · last 24h

Average per {{ ((24 * 60) // 96) }} minutes, your local time. Red bars mark failed checks.

{% endif %}

Last 30 checks

{% if heartbeat %}
{% for _ in range([30 - heartbeat|length, 0]|max) %}{% endfor %} {% for h in heartbeat %}{% endfor %}

Newest on the right; hover one for its result.{% if latest %} Last checked {{ latest.checked_at|ago }}.{% endif %}

{% else %}

{{ "Not checked yet. The first check runs on the next scheduler tick." if monitor.enabled else "Paused, and never checked." }}

{% endif %}

Recent failures

{% if failures %} {% if monitor.type == "http" %}{% endif %} {% for f in failures %} {% if monitor.type == "http" %}{% endif %} {% endfor %}
WhenErrorStatus
{{ f.checked_at|ago }} {{ f.error_msg or "Down" }}{{ f.status_code or "—" }}
{% else %}

No failed checks on record.

{% endif %}

Settings

Type
{{ monitor.type|monitor_type }}
Target
{{ monitor.target }}
Checked every
{% if monitor.check_interval_seconds %}{{ monitor.check_interval_seconds|duration }}{% else %}{{ poll_interval|duration }} (the global interval, Settings){% endif %}
{% if host %}
Host
{{ host.name }}
{% endif %} {% for key, value in monitor.config.items() %} {% if value not in (none, "", {}) %}
{{ field_label(key) }}
{{ value|join(", ") if value is mapping else ("yes" if value is sameas true else ("no" if value is sameas false else value)) }}
{% endif %} {% endfor %} {% if monitor.type == "dns" and not monitor.config.get("resolver") %}
Resolver
the container's own (its resolv.conf)
{% endif %}
{% endblock %}