Metronome is a lightweight monitoring tool designed to perform periodic HTTP and TCP probes against specified targets. It exports metrics about probe status, latency, and TLS certificate expiration, allowing for easy integration with Prometheus and Grafana.
- Supports HTTP/HTTPS and TCP probes
- TLS certificate expiration as Prometheus metric
- Local file or remote URL configuration
- Automatic configuration reloading
- Customizable HTTP success criteria based on HTTP status codes, and keyword existence/non-existence in body content
- Prometheus metrics with custom labels
- Detailed HTTP latency tracking
Metronome is designed as a simpler, more lightweight alternative to the Prometheus Blackbox Exporter. While the Blackbox Exporter is highly versatile and supports many protocols (ICMP, DNS, gRPC, etc.), it can be complex to configure due to its module-based architecture.
- Unlike the Blackbox Exporter, which performs probes synchronously when scraped by Prometheus, Metronome runs probes independently and asynchronously according to its own schedule. This ensures consistent probe intervals and makes metrics immediately available without adding latency to Prometheus scrapes.
- Metronome uses a straightforward per-probe configuration model, avoiding the multi-level module/target system that makes the Blackbox Exporter's configuration complex.
- Metronome has a highly focused codebase (under 1,000 lines of core Go logic), making it significantly easier to audit, understand, and extend for specific needs compared to the much larger and more modular Blackbox Exporter.
To build Metronome from source, ensure you have Go 1.26 or later installed.
git clone https://github.com/rmrustem/metronome.git
cd metronome
go build -o metronomeMetronome is configured primarily through environment variables and a configuration file containing probe definitions. By default, Metronome reads config.yaml from the current directory, so you can just run:
./metronomeTo specify a different configuration file path, use the METRONOME_CONFIG_PATH environment variable:
METRONOME_CONFIG_PATH=/path/to/my-config.yaml ./metronomeBy default, Metronome exports metrics on :8080/metrics.
| Variable | Description | Default |
|---|---|---|
METRONOME_CONFIG_PATH |
Path to the local configuration file. | config.yaml |
METRONOME_CONFIG_URL |
URL to fetch the configuration from (overrides local file). | - |
METRONOME_CONFIG_URL_AUTH |
Value for the Authorization header when fetching remote config. |
- |
METRONOME_CONFIG_RELOAD_INTERVAL |
How often to check for configuration changes (in seconds). Set to 0 to disable. |
60 |
METRONOME_PROBE_INTERVAL |
Default interval between probes if not specified (in seconds). | 30 |
METRONOME_HTTP_USER_AGENT |
Custom User-Agent header for HTTP probes. | Metronome |
METRONOME_HTTP_BODY_READ_BYTES |
Maximum number of bytes to read from an HTTP response body (e.g. for contain checks). |
102400 |
METRONOME_WEB_LISTEN |
Address and port for the Prometheus metrics server to listen on. | :8080 |
Metronome uses a YAML configuration file (config.yaml) to define the probes.
probes:
- name: "godev_http"
proto: "http"
target: "https://go.dev"
timeout: 5s
labels:
service: "go"
region: "us-east-1"
- name: "godev_tcp"
proto: "tcp"
target: "go.dev:443"
tls: true| Parameter | Description |
|---|---|
name* |
Unique name for the probe. |
proto* |
Protocol to use (http or tcp). |
target* |
The URL or host:port to probe. |
timeout |
Probe timeout (e.g., 5s). |
labels |
Additional key-value pairs to add as Prometheus labels. |
success_codes |
Comma-separated list or ranges of HTTP status codes considered successful (e.g., 200-299,404). |
contain |
String that must be present in the HTTP response body. |
not_contain |
String that must NOT be present in the HTTP response body. |
insecure_skip_verify |
If true, TLS certificate verification is skipped. |
tls |
If true, perform TLS handshake (only for TCP probes, HTTP uses URL scheme). |
metronome_probe_status: 1 for success, 0 for failure.metronome_probe_latency_seconds: Total round-trip time in seconds.metronome_tls_expires: Unix timestamp of the server certificate expiration.metronome_http_latency_seconds: HTTP latency by phase (dns, connect, tls, wait_for_response).metronome_probe_requests_total: Total number of requests for each probe.metronome_probe_failure_reason: Reason code for probe failure (0 for success).
| Code | Description |
|---|---|
0 |
Probe was successful. |
1001 |
Failed to resolve the target hostname. |
1101 |
Network connection timed out. |
1102 |
Connection was refused by the target. |
1201 |
Generic TLS handshake failure (including SNI issues). |
1202 |
Target certificate has expired. |
1203 |
Certificate signed by an unknown CA. |
1204 |
Certificate does not match the target hostname. |
1205 |
Other certificate validation errors. |
1300 |
Could not construct the HTTP request. |
1301 |
Response status code did not match success criteria. |
1302 |
Failed to read the response body. |
1303 |
contain string was not found in the response body. |
1304 |
not_contain string was found in the response body. |
Below are examples of Prometheus alerting rules you can use with Metronome metrics.
groups:
- name: metronome_alerts
rules:
# Alert on probe failure
- alert: ProbeFailed
expr: metronome_probe_status == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Probe {{ $labels.name }} failed"
description: >
Probe {{ $labels.name }} against {{ $labels.target }} is failing.
Failure code: {{ query "metronome_probe_failure_reason{name='{{ $labels.name }}'}" }}.
# Alert on TLS certificate expiration (30 days)
- alert: TLSCertExpiringSoon
expr: metronome_tls_expires - time() < 30 * 24 * 3600
for: 1h
labels:
severity: warning
annotations:
summary: "TLS certificate for {{ $labels.name }} expiring soon"
description: "The TLS certificate for {{ $labels.target }} will expire in {{ $value | humanizeDuration }}."This project is licensed under the MIT License - see the LICENSE file for details.