Monitors

Asura supports 19 monitor types: 17 active checks, heartbeat monitors for incoming pings, and manually controlled monitors. Probe types have their own interval, protocol settings and optional assertions.

On this page

Monitor Fields

Field Type Required Description
name string yes Display name, up to 255 UTF-8 bytes
description string   Optional description, rendered as markdown on the detail page (up to 5,000 UTF-8 bytes)
type string yes http http_multi tcp dns icmp tls websocket command docker heartbeat domain grpc mqtt smtp ssh redis postgresql udp manual
target string for active checks URL, host:port, domain or display target, up to 2,048 UTF-8 bytes; not required for heartbeat or manual monitors. Command executables come from settings.command
interval int   Seconds between checks, 5 to 86,400 (standard creation default: 60)
timeout int   Timeout in seconds, 1 to 300 (standard creation default: 10)
enabled bool   Enable monitoring (creation default: true)
tags string[]   Grouping tags
monitor_tags object[]   Managed tag assignments, e.g. [{"tag_id":1,"value":"production"}]; changes require monitors.assign and tags.read, and omission on update preserves assignments
group_id int   Monitor group ID (null if ungrouped)
proxy_id int   Proxy ID; supported protocol/type pairs are listed under Proxies. Proxy-routed checks run locally
notification_channel_ids int[]   Notification channels to route to (empty = all enabled channels whose event filter matches)
settings object   Protocol-specific (see below)
assertions object   Condition groups (see below)
track_changes bool   Enable content change detection
failure_threshold int   Consecutive non-up probes before opening an incident (standard creation default: 3)
success_threshold int   Consecutive up probes before recovery (standard creation default: 1)
upside_down bool   Inverted mode. “up” becomes “down” and vice versa
agent_enabled bool   Enable remote checks on explicitly assigned agents (API creation default: false). Empty assignments produce no remote jobs. Proxy assignments, typed authentication settings, mTLS material and server-only monitor types remain ineligible for delegation
agent_ids int[]   Existing trusted agent IDs. An omitted PUT field preserves current assignments; [] removes them. Changing delegation requires monitors.assign and agents.read. Newly enrolled agents receive no jobs until assigned
resend_interval int   Seconds between reminder notifications while an incident is open, 0 to 86,400 (0 disables reminders)
sla_target float   Scheduled-check SLA target percentage, from 0 to 100 (e.g. 99.9). Set to 0 to disable; unavailable for manual and heartbeat types

Creation defaults for interval, timeout and consecutive-check thresholds come from the server’s monitor configuration; the table lists its standard values. Existing monitor updates require a complete configuration, while omitted relationships preserve their current assignments; see the update example.

Agent assignment is a trust decision: eligible jobs include their target, custom request headers and bodies, which may contain credentials. Assign only agents you control. The server keeps proxy-routed checks, typed authentication and mTLS settings local. Upgrade the server and agents together; v2 jobs and results use a configuration revision to reject obsolete or revoked work. See the agent API.

Protocol Settings

HTTP

Field Type Description
method string HTTP method (default: GET)
headers map[string]string Custom request headers
body string Request body (for POST/PUT/PATCH)
body_encoding string Content-Type hint: json, xml, form, or empty for raw
auth_method string none, basic, bearer, or oauth2 (default: inferred)
basic_auth_user string Basic auth username
basic_auth_pass string Basic auth password
bearer_token string Bearer token
oauth2_token_url string OAuth2 token endpoint URL
oauth2_client_id string OAuth2 client ID
oauth2_client_secret string OAuth2 client secret
oauth2_scopes string OAuth2 scopes (space-separated)
oauth2_audience string OAuth2 audience (optional)
mtls_enabled bool Enable mutual TLS client authentication
mtls_client_cert string Client certificate (PEM)
mtls_client_key string Client private key (PEM)
mtls_ca_cert string Custom CA certificate (PEM, optional)
expected_status int Expected HTTP status code (0 = any 2xx/3xx)
follow_redirects bool Follow redirects (default: true)
max_redirects int Positive redirect limit, up to 100; overrides follow_redirects. Zero or omission uses follow_redirects, with a default limit of 10
skip_tls_verify bool Skip TLS certificate verification
cache_buster bool Append unique query param to bypass caches
{
  "method": "POST",
  "headers": {"X-Custom": "value"},
  "body": "{\"key\":\"value\"}",
  "body_encoding": "json",
  "auth_method": "bearer",
  "bearer_token": "eyJhbGci...",
  "expected_status": 200,
  "max_redirects": 5,
  "skip_tls_verify": false,
  "cache_buster": false
}

OAuth2 Client Credentials

{
  "auth_method": "oauth2",
  "oauth2_token_url": "https://auth.example.com/oauth/token",
  "oauth2_client_id": "my-client-id",
  "oauth2_client_secret": "my-secret",
  "oauth2_scopes": "read write",
  "oauth2_audience": "https://api.example.com"
}

Asura fetches a token from the token URL using the client credentials grant and the monitor’s proxy, when configured. It caches the token in memory for at most one day and refreshes before expiry. Credential, recipient or proxy changes invalidate reuse. The token endpoint must respond directly; redirects are not followed with client credentials. An unreachable or invalid token endpoint makes the check fail without recording its response body.

Mutual TLS (mTLS)

{
  "mtls_enabled": true,
  "mtls_client_cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
  "mtls_client_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----",
  "mtls_ca_cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
}

mTLS is independent of the auth method and can be combined with any authentication type. The CA certificate is optional and used for custom trust stores (e.g., self-signed server certificates). Certificates are stored inline as PEM text.

TCP

{"send_data": "PING\r\n", "expect_data": "PONG"}

DNS

{"record_type": "A", "server": "8.8.8.8"}

TLS

{"warn_days_before": 30}

warn_days_before defaults to 30 when omitted or zero. Expiration uses the certificate’s exact timestamp. The displayed days remaining and the warning window do not postpone expiration until the next whole day.

WebSocket

{"headers": {"Authorization": "Bearer token"}, "send_message": "ping", "expect_reply": "pong"}

Command

{"command": "/usr/local/bin/check_health", "args": ["--host", "db.local"]}

Docker

Field Type Description
container_name string Container name or ID (overrides target if set)
socket_path string Docker socket path (default: /var/run/docker.sock)
check_health bool Use container health status instead of just running state
{"container_name": "nginx", "socket_path": "/var/run/docker.sock", "check_health": true}

Status mapping:

Setup. systemd (native install):

sudo usermod -aG docker asura
sudo systemctl restart asura

Setup. Docker: Mount the host socket:

volumes:
  - /var/run/docker.sock:/var/run/docker.sock

Domain (WHOIS)

Field Type Description
warn_days_before int Days before expiry to mark as degraded (default: 30)
{"warn_days_before": 30}

Target is a domain name (e.g. example.com). Asura queries the appropriate WHOIS server for the TLD and parses its expiry date. Expiration uses the exact available timestamp; rounded days are used for display and the warning window.

gRPC

Field Type Description
service_name string gRPC service to health-check (empty = all)
use_tls bool Use TLS (default: false)
skip_tls_verify bool Skip TLS certificate verification
{"service_name": "my.service.v1", "use_tls": true}

Uses the standard grpc.health.v1.Health/Check protocol. Default port: 50051 (plaintext), 443 (TLS).

MQTT

Field Type Description
client_id string MQTT client ID (auto-generated if empty)
username string Authentication username
password string Authentication password
topic string Subscription filter; supports + and #. Required with expect_message
expect_message string Optional literal, case-sensitive payload substring (maximum 64 KiB)
use_tls bool Use TLS (default: false)
{"topic": "health/status", "expect_message": "ready", "use_tls": true}

Connects using MQTT 3.1.1. Default port: 1883 (plaintext), 8883 (TLS). Without an expectation, it verifies the connection and any configured subscription. With expect_message, it requires an accepted QoS 0 subscription and a retained or live message whose payload contains that text before the monitor timeout. This is a literal match, not a regular expression.

Subscription reads are limited to 64 packets, 256 KiB per packet body and 1 MiB total including framing. A timeout, missing match, malformed packet or exceeded limit reports the monitor down. Errors never include the expected or received payload. On edits, a blank hidden expectation preserves its saved value; use Remove saved value or clear_secrets: ["expect_message"] to remove it.

Heartbeat Monitoring

Create a heartbeat monitor to track cron jobs, workers, or pipelines. If they stop pinging, Asura fires an incident.

# Create heartbeat monitor
curl -X POST https://example.com/asura/api/v1/monitors \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Nightly Backup","type":"heartbeat","interval":3600,"settings":{"grace":300}}'

The successful creation response includes the ping token once. Store it securely; later reads cannot recover it. The web creation form similarly shows a one-time ping URL.

{
  "monitor": { "id": 1, "name": "Nightly Backup", "type": "heartbeat", ... },
  "heartbeat": { "token": "a1b2c3d4e5f6...", "grace": 300, "status": "pending" }
}

Ping from your script (no auth needed):

curl -X POST https://example.com/asura/api/v1/heartbeat/a1b2c3d4e5f6...

After the first ping, if no further ping arrives within interval + grace seconds, heartbeat evaluation marks the monitor down and opens an incident. Explicit heartbeat transitions bypass consecutive-check thresholds. Heartbeat monitors have no measured network response time.

Manual Monitoring

Manual monitors let you control status for manual processes, third-party dependencies or business-hour services. Asura does not probe a remote target: you set the status through the web UI or API.

# Create manual monitor
curl -X POST https://example.com/asura/api/v1/monitors \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Third-Party Payment Gateway","type":"manual"}'

Set status via API:

# Set to down with a message
curl -X POST https://example.com/asura/api/v1/monitors/1/status \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"down","message":"Vendor reported outage"}'

# Set back to up
curl -X POST https://example.com/asura/api/v1/monitors/1/status \
  -H "X-API-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"up","message":"Vendor confirmed recovery"}'

Valid statuses are up, down and degraded. An authorized status change records a check and updates the state immediately; down or degraded opens or updates an incident, and up resolves it. Maintenance can defer incident notifications. The detail page offers status controls to principals with monitors.status authority on that monitor.

Inspecting private diagnostics

Ordinary monitor reads show status and measured timing while keeping response headers, bodies, errors, content hashes and diffs private. Inspecting those stored details requires monitors.read together with diagnostics.read for the same monitor. Raw incident causes and timeline text use incidents.read plus diagnostics.read. Viewer and operator roles do not include diagnostic access by default.

Assertion definitions and multi-step extraction regex/JSON expressions may contain private literals, so ordinary editor views hide them too. An unrelated edit with those fields left blank preserves the current stored definitions. Supply new nonempty definitions to replace them, or explicitly remove them with the saved-value control or API clear_secrets paths. Saved request credentials, bodies, command arguments and full URLs remain hidden even with diagnostic access. See API diagnostic fields for exact fields and removal paths.

A multi-step edit that retains private inputs must preserve the ordered request flow, including destinations, extraction rules and references in later requests. Unchanged independent requests may be reordered only without extraction or interpolation. Changing the flow requires replacing or clearing borrowed private inputs, or super administrator authority. This prevents a new step from forwarding an authenticated response elsewhere.

Assertions

Assertions are evaluated for scheduled probe results. A failed assertion marks a monitor down or, if degraded is set, degraded instead. Saved assertions on manual and heartbeat monitors remain inactive.

Conditions are organized into groups. Each group has its own and/or operator, and the top-level operator controls how the groups themselves are combined. The web UI lets you build this visually. API consumers send the structured object directly.

Condition Types

Type Description Operators
status_code HTTP status code eq, neq, gt, lt, gte, lte
body_contains Body text search contains, not_contains
body_regex Body regex match matches, not_matches
json_path JSON value at dot-path eq, neq, gt, lt, contains, exists
header Response header value eq, neq, contains, exists
response_time Response time (ms) lt, lte, gt, gte
cert_expiry Days until cert expires gt, gte, lt, lte
dns_record DNS record value contains, eq

Structure

{
  "assertions": {
    "operator": "and",
    "groups": [
      {
        "operator": "or",
        "conditions": [
          {"type": "status_code", "operator": "eq", "value": "200"},
          {"type": "status_code", "operator": "eq", "value": "201"}
        ]
      },
      {
        "operator": "and",
        "conditions": [
          {"type": "response_time", "operator": "lt", "value": "5000"},
          {"type": "json_path", "target": "status", "operator": "eq", "value": "ok"}
        ]
      },
      {
        "operator": "and",
        "conditions": [
          {"type": "response_time", "operator": "lt", "value": "2000", "degraded": true}
        ]
      }
    ]
  }
}

With a 200 or 201 status and a JSON status field of ok, this example is up below 2 seconds, degraded from 2 seconds to below 5 seconds, and down at 5 seconds or longer. A failed hard condition dominates failed degraded conditions, regardless of their order. A passing alternative still satisfies an or group.

Additional Monitor Types

SMTP

Checks mail server availability through a plaintext greeting and EHLO handshake, with optional STARTTLS. The port is configurable and defaults to 25. If an expected banner is configured, the greeting must contain it. Greeting lines are limited to 512 bytes and the complete greeting to 64 KiB; total incoming traffic, including STARTTLS records and later replies, is limited to 1 MiB per check. Exceeding a limit fails the check.

SSH

Connects to an SSH server and requires a complete, syntactically valid identification line after a bounded number of pre-banner lines. A bare SSH- prefix is insufficient. An optional fingerprint compares the SHA-256 hash of the identification banner. This checks the banner rather than the host key and does not provide cryptographic host identity or MITM protection.

Redis

Sends PING via the RESP protocol and requires the complete +PONG reply. Optional password authentication requires the complete +OK reply. Both use CRLF line endings and a 4 KiB reply limit. The default port is 6379.

PostgreSQL

Sends a PostgreSQL protocol v3 startup message and validates the bounded authentication or error response. This verifies that a PostgreSQL server answers, including an authentication or database-access error; it does not authenticate or run a query. Username and database are configurable, and no database driver is required for the check.

UDP

Sends send_data (a newline when empty). With expect_data, it waits for one reply of up to 4 KiB and requires that text to be present. Without expect_data, a successful send is enough: it does not wait for a reply or prove that the remote application is healthy.

HTTP Multi-Step

Executes a sequence of up to 5 HTTP requests. Variables extracted from one step (via regex or JSON dot-path) can be interpolated into subsequent steps using {{var}} syntax. A transport error or a step status that differs from its positive expected_status fails the check. Unlike a single HTTP monitor, a step with expected_status: 0 accepts any HTTP status. Response time is the sum of all steps.

Interpolation runs once: extracted text is treated as data, even when it contains placeholder syntax. Unknown or unclosed placeholders in bodies and headers remain literal; URL placeholders must refer to variables defined by earlier steps. Each resolved request is limited to an 8 KiB URL, a 1 MiB body, and 64 KiB of combined header names and values. If expansion exceeds a limit, the check fails before sending that request. Settings remain limited to 1 MiB, and extraction reads at most 1 MiB of each response body.

{
  "steps": [
    {
      "name": "Login",
      "url": "https://api.example.com/auth",
      "method": "POST",
      "headers": {"Content-Type": "application/json"},
      "body": "{\"user\":\"test\",\"pass\":\"secret\"}",
      "expected_status": 200,
      "extract_var": "token",
      "extract_json": "data.access_token"
    },
    {
      "name": "Get profile",
      "url": "https://api.example.com/me",
      "method": "GET",
      "headers": {"Authorization": "Bearer {{token}}"},
      "expected_status": 200
    }
  ]
}

Anomaly Detection

Per-monitor anomaly sensitivity detects response time spikes by comparing against a 7-day rolling baseline. When a check exceeds the configured threshold, the monitor is marked degraded instead of up.

Sensitivity Threshold
Off Disabled
Low 3 standard deviations above baseline
Medium 2 standard deviations
High 1.5 standard deviations

Baselines recalculate every 6 hours. At least 30 successful probe samples and a nonzero baseline deviation are needed for detection. Set via the anomaly_sensitivity field or the monitor form.

Incident Severity

Incidents are auto-assigned a severity when created: critical for down monitors, warning for degraded. Severity can be manually overridden via POST /api/v1/incidents/{id}/severity with {"severity": "major"}. Four levels: critical, major, minor, warning.

Uptime Heatmap

Scheduled monitors show a 365-day uptime calendar with neutral and blue shading. Its legend distinguishes at least 99.9%, 99% to below 99.9%, and below 99%; days without samples stay separate. Hover for a daily value or open the native daily-data table for exact percentages and check counts using a keyboard or touch. No samples are shown as an em dash, not as measured 100% uptime.

Manual and heartbeat monitors report state, not sampled uptime or latency. Their detail pages show the latest reported state and update; heartbeat details also show the last ping and grace period. State history remains available, but response charts, sampled uptime, heatmaps and SLA budgets are unavailable. Uptime and response badges show n/a, and public JSON uptime is null.

History records its source independently of the monitor’s current type. Scheduled server and agent results are probes; manual state changes remain manual observations. Heartbeat pings update state without adding scheduled-check samples. Changing a monitor’s type preserves history and never turns manual state into uptime or latency samples. Pre-schema-41 records have an unknown source and are excluded from verified sample metrics. Genuine probe history remains available after later type changes, including a measured response time of 0 ms. See the upgrade note before migrating an existing database.

Legacy SLA targets on passive monitors remain stored and inactive. An unrelated edit preserves that value; clear it explicitly to remove it. When changing a scheduled monitor to a passive type, clear any active SLA target to 0 first. Custom targets, including 100, are preserved by the form.