Choose an agent or push monitor
| Capability | Agent monitor | Push monitor | Private location |
|---|---|---|---|
| Execution model | OpenTelemetry Collector on the host pushes OTLP metrics | Caller sends heartbeat | Worker pulls queued active jobs |
| Host metrics | OS metrics via hostmetrics; any OTel metric a collector sends is stored | Arbitrary submitted key/value metrics | Worker process metrics only |
| Freshness state | Scheduler watchdog on the expected report interval | Expected heartbeat interval plus grace | Location heartbeat connection |
| Runs HTTP/DNS/etc. checks | No | No | Yes |
| Credential | Tenant API key plus agent ID | Monitor-specific push token | Location credential |
Agent monitors are served by probara-collector, a minimal OpenTelemetry Collector distribution that scrapes host metrics and pushes them to Probara's OTLP ingest endpoint. Because the wire protocol is standard OTLP/HTTP, a stock upstream collector build works too — see migrating and extending.
Agent monitor configuration
| Variable | Meaning |
|---|---|
agent_id | Stable generated identity matched against inbound reports |
expected_interval_seconds | Expected reporting interval, 10–86,400 seconds |
metric_rules | Optional array of up to 50 threshold rules; each breached rule opens host_metric alerts independently |
metric_rules[].metric_name | Any metric name the collector reports, for example system.cpu.utilization |
metric_rules[].attribute_filters | Optional attribute equality filters (for example mountpoint). A rule without filters fans out per matching series |
metric_rules[].operator | >= or <= |
metric_rules[].threshold | Threshold in the metric's native unit — *.utilization metrics are ratios, so 90% is 0.9, not 90 |
metric_rules[].for_duration_seconds | Optional sustained-for window: the alert opens only if every evaluated point breached for the whole window (Prometheus-style) |
The monitor receives availability success whenever an OTLP export is accepted. Metric rules are evaluated separately and open host-metric alerts rather than turning the availability result into failure.
Rule metric names must match what the host's scrapers actually emit. The generated collector config enables a per-OS scraper set:
| Platform | Enabled `hostmetrics` scrapers | Consequence |
|---|---|---|
| Linux | cpu, memory, paging, filesystem, network, disk, load, processes | All documented metrics, including system.processes.count |
| macOS | cpu, memory, paging, filesystem, network, disk, load | No processes scraper, so no process count |
| Windows | cpu, memory, paging, filesystem, network, disk | Neither load nor processes; no load averages or process count |
Install the collector
The authenticated agent endpoints generate per-OS install and uninstall instructions containing the monitor's agent ID, API origin, the rendered collector configuration, and a caller-provided API key.
- Create an agent monitor and choose its expected interval and optional metric rules.
- Create a tenant API key with
writescope. Read scope cannot submit metrics. - Open the monitor's agent install instructions and select the target platform.
- Run the generated script with the privileges required by that platform.
- Confirm the first report appears immediately, then verify periodic reports and current state.
| Platform | Service mechanism | Files and secrets |
|---|---|---|
| Linux | systemd system service probara-collector.service (root) | Config at /etc/probara-collector/config.yaml (0644, references ${env:…} only); EnvironmentFile=/etc/probara-collector/collector.env (0600) holds PROBARA_API_KEY and PROBARA_AGENT_ID |
| macOS | per-user launchd agent com.probara.collector | A runner script sources the environment file before starting the collector; install for the user account that should own the process |
| Windows | native service ProbaraCollector registered via sc.exe | Run from elevated PowerShell; secrets live in the service's registry Environment value, not in the config file |
Install scripts download the platform binary from GET /static/collector/probara-collector-{linux,darwin}-{amd64,arm64} (or -windows-amd64.exe), verify its SHA-256 against the published checksums.txt, and first remove any legacy probara-agent installation (systemd/launchd/NSSM service, binary, and config) before installing. Re-running the installer on a host is therefore also the migration path. Uninstall scripts clean up both generations.
GET /api/v1/monitors/{id}/agent/install returns the same material as JSON, including the rendered collector_config YAML and the collector_version. Configuration-management users can fetch the raw collector YAML directly from GET /api/v1/monitors/{id}/agent/config.yaml?platform=linux|darwin|windows and distribute it themselves.
Generated URLs depend on PUBLIC_BASE_URL, which must be an absolute http:// or https:// origin without user information, query, or fragment. The corresponding platform binary must exist in the API's static collector directory. See the public URL configuration for how this value is wired.
Run the collector manually
export PROBARA_API_KEY=<write-scope-api-key>
export PROBARA_AGENT_ID=<agent-id>
probara-collector --config /etc/probara-collector/config.yaml| Environment variable | Purpose |
|---|---|
PROBARA_API_KEY | Tenant write-scope API key sent as the Authorization: Bearer header |
PROBARA_AGENT_ID | Agent monitor identity sent as the X-Probara-Agent-Id header |
The generated configuration file contains no secrets: it references credentials exclusively through ${env:…} expansion, so the same file can be committed to configuration management while the environment file (or the Windows service registry value) carries the API key.
Reporting behavior
The collector scrapes host metrics on its configured interval and pushes them as OTLP/HTTP to POST /api/v1/otlp/v1/metrics (protobuf or JSON, gzip supported), authenticated with Authorization: Bearer <tenant API key>. Monitor identity comes from the X-Probara-Agent-Id header, or from a probara.agent.id resource attribute when a gateway collector multiplexes metrics for several hosts through one connection. Responses follow the OTLP specification, including partial_success when only some points were rejected.
Each accepted export doubles as one availability heartbeat: a success check result stamped with the server's receipt time, so collector clock skew can never affect state or history.
| Metric | Notes |
|---|---|
system.cpu.utilization{state=used} | A metricstransform processor aggregates per-CPU non-idle states into one used ratio |
system.memory.utilization / system.memory.usage | Memory ratio and bytes |
system.paging.* | Swap utilization and usage |
system.filesystem.utilization / system.filesystem.usage | Per-mountpoint ratio and bytes; every mountpoint is a separate series. Pseudo-filesystems (devfs, tmpfs, squashfs, overlay, …) are excluded at collection — they read 100% forever and carry no real capacity. On macOS the APFS boot/firmware system volumes (Preboot, Hardware, Update, VM, …) are excluded too; /System/Volumes/Data alone represents the disk, since APFS volumes share the container's free space |
system.network.io / system.disk.io | Cumulative byte counters; the platform derives rates from them. Per-interface system.network.packets/errors/dropped are disabled by default — they are the biggest series-cardinality driver; re-enable them in the config if you need them |
system.cpu.load_average.{1m,5m,15m} | Not available on Windows |
system.uptime | Host uptime |
system.cpu.logical.count | Logical core count |
system.processes.count | Linux only |
Metrics land in a generic metric store: a per-series registry, raw samples in daily partitions kept for METRIC_RAW_RETENTION_DAYS (default 30; a tenant's data_retention_days can tighten it further), and hourly rollups (min/max/avg/sum/first/last plus reset-aware increase for counters) pruned after 400 days. Any OTel metric a collector sends is stored, chartable in the UI's metric explorer, and usable in metric rules — not only the host metrics above. GET /api/v1/monitors/{id}/metrics/series discovers stored series and POST /api/v1/monitors/{id}/metrics/query runs batch range queries.
| Limit | Behavior |
|---|---|
| Gauges and sums only | Histograms and summaries are rejected in v1 |
| Request body 4 MiB (20 MiB decompressed), ≤10,000 data points | Oversized requests are refused |
Series cardinality per monitor: 2,000 (OTLP_MAX_SERIES_PER_MONITOR) | Overflow points are rejected via partial_success; accepted points still count |
Rate limit: 60 requests/min per monitor (OTLP_MONITOR_RATE_PER_MIN) | 429 with Retry-After |
| Unknown agent ID / disabled monitor / transient failure | 404 / 403 / 503 |
Agent freshness and recovery
A scheduler-side watchdog marks an agent monitor failed after no accepted report for three times the monitor interval, with a 90-second floor. The watchdog re-fires each window while the silence persists, so consecutive missed windows accumulate toward down exactly like consecutive failed checks. A later valid export creates a success result and recovers availability.
Stale transitions are recorded with result_source = monitor, so they affect current state and availability alerting and are included in standard uptime analytics. Only expired-job results use the platform source that analytics exclude.
Metric rules and host-metric alerts
When a metric rule is breached, Probara opens a separate host-metric alert. Alerts are keyed by the canonical series key, for example system.filesystem.utilization{device=/dev/sda1,mode=rw,mountpoint=/data,type=ext4}, so each series maintains its own independent lifecycle.
- A rule without attribute filters fans out per matching series: one filesystem rule opens one alert per breaching mountpoint, removing the old single-disk-path limitation.
for_duration_secondsrequires the breach to hold for the whole window before the alert opens.- Evaluation is freshness-bounded (interval×3, 90-second floor): a dead collector's stale readings can no longer keep metric alerts open — availability alerting covers the outage instead.
- A metric-rule breach does not mark agent availability down; a metric alert resolves when the series returns within the rule, and removing a rule resolves its conditions.
- Notification routing follows the monitor's default or custom channel assignments.
Uninstall (remote disable removed)
The legacy agent's opt-in remote-disable mechanism — a 410 Gone response triggering a local self-uninstall — is removed. The collector never executes removal actions on behalf of the backend. Deleting the monitor stops the backend from accepting its reports but leaves the collector service installed and exporting into rejections.
Legacy agents that were explicitly started with --allow-remote-disable still honor the old 410 self-uninstall during the deprecation window when their monitor is deleted; all others simply log and retry until manually uninstalled.
Migrating from the legacy agent
The custom probara-agent binary is replaced by the OpenTelemetry Collector. POST /api/v1/agent/metrics still accepts legacy agents through a deprecation window ending Wednesday, 18 November 2026; every response carries Deprecation, Sunset, and Link headers, and each legacy report is logged server-side so operators can find stragglers. After the window the endpoint becomes a 410 tombstone. Old agent binaries are no longer distributed.
- Re-run the install one-liner on each host: the installer removes the legacy agent (service, binary, config) and installs the collector in one pass.
- Verify the monitor keeps reporting; the same monitor, agent ID, and API key carry over unchanged.
- Check server logs (or the sunset headers in your agent's responses) to enumerate hosts still on the legacy path.
Air-gapped or mirror-constrained environments do not need the probara-collector binary at all: the generated configuration is a standard OpenTelemetry Collector config, and a stock otelcol-contrib build runs it unchanged. Fetch the YAML from GET /api/v1/monitors/{id}/agent/config.yaml and distribute upstream binaries from your own mirror.
The configuration is also an extension point: add more hostmetrics scrapers, or additional receivers entirely (with otelcol-contrib), pushing to the same OTLP endpoint. Any metric that arrives is stored, chartable, and alertable through metric rules — subject to the per-monitor series and rate limits.
Push monitor configuration
| Variable | Meaning |
|---|---|
push_token | Generated bearer-style credential embedded in the public heartbeat URL |
expected_interval_seconds | Expected time between pushes, 10–86,400 seconds |
grace_period_seconds | Additional non-negative delay before the heartbeat is considered stale |
Use a push monitor for cron jobs, backup jobs, queue consumers, or external systems that can call an HTTP URL but do not need host metrics. The endpoint accepts both GET and POST without an admin session because the token itself authorizes the report.
Send push heartbeats
curl -fsS 'https://monitoring.example.com/api/v1/push/<token>'curl -fsS -X POST \
-H 'Content-Type: application/json' \
-d '{"status":"down","error":"backup upload failed","files":182,"bytes":987654321}' \
'https://monitoring.example.com/api/v1/push/<token>'Reserved JSON keys are status and error; remaining keys are stored as metrics. Query-string values on GET are converted to integers, floating-point values, booleans, or strings when possible.
| Submitted `status` | Stored outcome |
|---|---|
up | Success |
down | Failure |
error | Error |
| Omitted or any other value | Success; validate client spelling instead of expecting rejection |
A disabled push monitor returns HTTP 403 and a missing/deleted token returns 404. A successful push updates freshness and can recover an existing stale/down availability condition.
Push freshness
A push monitor becomes stale after expected_interval_seconds + grace_period_seconds without an accepted report. While it remains stale, the platform limits repeated generated failures to avoid unbounded duplicate history. A new accepted heartbeat restores up state.