Files
monlet/agent/README.md
2026-05-27 10:01:59 +04:00

79 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Monlet Agent
Go agent (Stage 2 MVP). Reads `agent.toml`, runs configured commands on schedule, captures status/output, pushes contract-valid `heartbeat` and `events` batches to the Monlet server with Bearer auth, and survives outages via a local on-disk spool.
## Build and run
```sh
cd agent
GOTOOLCHAIN=local GOMODCACHE=$(pwd)/../.cache/go/pkg/mod GOCACHE=$(pwd)/../.cache/go/build GOBIN=$(pwd)/../.cache/go/bin go test ./...
GOTOOLCHAIN=local GOMODCACHE=$(pwd)/../.cache/go/pkg/mod GOCACHE=$(pwd)/../.cache/go/build GOBIN=$(pwd)/../.cache/go/bin go run ./cmd/monlet-agent -config config.example.toml
```
Do not use `go install` or `go env -w`. Module cache, build cache, and tool binaries stay under repo `.cache/`.
## Configuration
See `config.example.toml`. Required fields: top-level `state_dir`, at least one `[[checks]]` (`id`, `command`, `interval`, `timeout`), and at least one output enabled: `server.enabled = true` or `metrics.enabled = true`. `agent_id` is optional; if omitted, it defaults to `hostname`.
| Key | Default | Notes |
|---|---|---|
| `server.enabled` | `false` | Enables heartbeat/event push. Requires `server.url` and `server.token` when true. |
| `metrics.enabled` | `false` | Enables `/metrics`. |
| `labels` | `{}` | Optional heartbeat labels. Max 31 custom labels because `monlet_agent_version` is generated by the agent. Secret-like keys are rejected. |
| `server.heartbeat_interval` | `30s` | ADR-0005 |
| `server.batch_interval` | `10s` | events flush cadence |
| `metrics.listen` | `127.0.0.1:9465` | low-cardinality only |
| `checks[].command` | required | Shell string executed as `/bin/sh -c`; TOML multi-line strings are supported. |
| `checks[].notifications_enabled` | `true` | Set `false` for checks that must not create server notifications. |
Example:
```toml
[[checks]]
id = "disk_root"
command = '''
set -eu
/usr/local/lib/monlet/check_disk_root.sh
'''
interval = "60s"
timeout = "10s"
```
## Behaviour
- Per-check scheduler with no-overlap: a tick is skipped if the previous run is still in flight (`monlet_agent_check_skipped_total`).
- Check commands run through `/bin/sh -c`; the old argv-array form is intentionally unsupported.
- Timeout via `exec.CommandContext` with `Setpgid` so the process group is killed on expiry; timeout → `unknown`.
- Exit code mapping: 0=ok, 1=warning, 2=critical, 3+=unknown (ADR-0005).
- `output` (stdout+stderr) is truncated by **UTF-8 byte length** to 8 KiB with marker `...[truncated N bytes]`.
- `event_id` is UUIDv7 generated on check completion and preserved across spool replay (ADR-0006 idempotency).
- Spool: per-event JSON files in `state_dir/spool/`, FIFO, limits 10 000 events / 50 MiB, drop oldest on overflow (ADR-0005).
- Retry backoff for heartbeat and events: 1s → 30s, exp ×2, jitter ±20%. 4xx are dropped (not retried) to avoid hot loop.
- Bearer auth header on both endpoints (ADR-0007).
- Heartbeats include configured labels plus reserved `monlet_agent_version=<binary version>`.
- Heartbeats include explicit feature flags: `push` from `server.enabled`, `metrics` from `metrics.enabled`.
## Prometheus metrics
Exposed on `metrics.listen` at `/metrics`. Labels are static (`check_id`, `status`, `kind`):
- `monlet_agent_check_runs_total{check_id,status}`
- `monlet_agent_check_skipped_total{check_id}`
- `monlet_agent_check_duration_seconds{check_id}` (histogram)
- `monlet_agent_check_status{check_id}` (0=ok, 1=warning, 2=critical, 3=unknown)
- `monlet_agent_check_exit_code{check_id}`
- `monlet_agent_check_last_run_timestamp_seconds{check_id}`
- `monlet_agent_check_last_success_timestamp_seconds{check_id}`
- `monlet_agent_check_interval_seconds{check_id}`
- `monlet_agent_checks_configured`
- `monlet_agent_spool_events`, `monlet_agent_spool_bytes`
- `monlet_agent_send_attempts_total{kind}`, `monlet_agent_send_failures_total{kind}` (`kind``heartbeat`, `events`)
- `monlet_agent_events_accepted_total`, `monlet_agent_events_deduplicated_total`
- `monlet_agent_last_heartbeat_timestamp_seconds`
- `monlet_agent_build_info{version,push,metrics}` (constant 1)
## systemd
See `systemd/monlet-agent.service.example`.