This directory contains the alert rules for the Liquidity Provider Server (LPS) monitoring system.
alerts/node-eclipse-detection.json- Detects potential eclipse attacks on Bitcoin nodesalerts/pegin-out-of-liquidity.json- Alerts when PegIn operations run out of Bitcoin liquidityalerts/pegout-out-of-liquidity.json- Alerts when PegOut operations run out of BTC liquidityalerts/lps-penalization.json- Alerts when the LPS has been penalizedalerts/hot-wallet-low-liquidity-warning.json- Alerts when hot wallet liquidity drops below warning thresholdalerts/hot-wallet-low-liquidity-critical.json- Alerts when hot wallet liquidity is critically low
contact-points/low-liquidity.json- Custom email format for low liquidity alerts (used by both warning and critical alerts)
import-alerts.sh- Script to import alert rules, contact points, and notification policies into any Grafana instance
ALERT_RECIPIENT_EMAILenvironment variable must be set (e.g., viasource .env.regtest)- Grafana with unified alerting enabled
- Loki datasource configured (default UID:
loki-uid, customizable via script parameter) curlandpython3available
# From project root - basic usage (localhost:3000 with admin/test)
./docker-compose/monitoring/scripts/import-alerts.sh
# Custom Grafana instance
./docker-compose/monitoring/scripts/import-alerts.sh http://grafana.example.com:3000 admin password
# Different folder
./docker-compose/monitoring/scripts/import-alerts.sh http://localhost:3000 admin test ALERTS
# Custom datasource UID
./docker-compose/monitoring/scripts/import-alerts.sh http://localhost:3000 admin test LPS my-loki-uid
# Or run from the monitoring scripts directory
cd docker-compose/monitoring/scripts
./import-alerts.shgrafana_url- Grafana instance URL (default: http://localhost:3000)username- Grafana username (default: admin)password- Grafana password (default: test)folder_uid- Folder UID for alerts (default: LPS)datasource_uid- Loki datasource UID (default: loki-uid)
ALERT_RECIPIENT_EMAIL(required) - Recipient email for alert notifications. Read from the environment (set in.envfiles).
docker-compose/monitoring/scripts/
├── import-alerts.sh # Main import script
├── README.md # This documentation
├── alerts/
│ ├── node-eclipse-detection.json # Eclipse attack alert
│ ├── pegin-out-of-liquidity.json # PegIn liquidity alert
│ ├── pegout-out-of-liquidity.json # PegOut liquidity alert
│ ├── lps-penalization.json # LPS penalization alert
│ ├── hot-wallet-low-liquidity-warning.json # Hot wallet low liquidity warning (regex extraction)
│ └── hot-wallet-low-liquidity-critical.json # Hot wallet critical low liquidity (regex extraction)
└── contact-points/
└── low-liquidity.json # Custom email format for low liquidity alerts
- Trigger: When log contains "Alert! - Subject: Node Eclipse Detected"
- Purpose: Detects potential eclipse attacks on Bitcoin nodes
- Trigger: When log contains "Alert! - Subject: PegIn: Out of liquidity"
- Purpose: Alerts when insufficient liquidity for PegIn operations
- Trigger: When log contains "Alert! - Subject: PegOut: Out of liquidity"
- Purpose: Alerts when insufficient liquidity for PegOut operations
- Trigger: When log contains "Alert! - Subject: LPS has been penalized"
- Purpose: Alerts when the Liquidity Provider has been penalized for failing to fulfill quote commitments
- Trigger: When log contains "Alert! - Subject: Hot wallet: Low liquidity, refill recommended"
- Purpose: Alerts when the hot wallet liquidity is below the warning threshold
- Dynamic extraction: Uses LogQL
regexpto extractnetwork,current, andthresholdfrom the log body and includes them in the notification via{{ $labels.xxx }} - Custom contact point: Routed to
lps-email-low-liquidityvia__contact_point__for a tailored email format
- Trigger: When log contains "Alert! - Subject: Hot wallet: Critical low liquidity, refill required"
- Purpose: Alerts when the hot wallet liquidity is critically low and an immediate refill is required
- Dynamic extraction: Same as the warning alert -- extracts
network,current, andthresholdviaregexp - Custom contact point: Shares
lps-email-low-liquiditywith the warning alert via__contact_point__
All alert rules are configured with:
noDataState: OK- Prevents "DatasourceNoData" alerts when no logs matchexecErrState: OK- Prevents error alerts on query execution issuesfor: "0s"- Fires immediately when condition is met (no pending period)
The alert JSON files use "datasourceUid": "loki-uid" by default.
Key Differences:
- Alert Rules (API Import): Use concrete UIDs like
"loki-uid" - Dashboard Templates: Use template variables like
"${DS_LOKI}"
The import script automatically replaces the datasource UID if you specify a different one via the datasource_uid parameter, making it portable across different Grafana instances.
In Grafana, a contact point bundles together the delivery channel (email, Slack, etc.), the recipient address, and the message template (subject, body format). In our setup the recipient is always the same (ALERT_RECIPIENT_EMAIL), so custom contact points are used solely to provide different email formats per alert type -- not different recipients.
The import script automatically:
- Creates a default
lps-emailcontact point for all alerts, using theALERT_RECIPIENT_EMAILenvironment variable as the recipient - Imports custom contact points from the
contact-points/directory (e.g.,lps-email-low-liquiditywith a tailored subject/message format) - Builds child routes from alert rules that declare a
__contact_point__field, routing them to the named contact point - Configures the notification policy with:
- A root route that sends all alerts to
lps-email(default Grafana email format) - Child routes that match specific alerts to their custom contact points (matched by
alertname)
- A root route that sends all alerts to
- Sets notification timing:
group_wait: 10s,group_interval: 1m,repeat_interval: 5m
To give an alert a custom email format:
- Create a contact point JSON in
contact-points/with__ALERT_EMAIL__as a placeholder for the recipient address (or reuse an existing one) - In the alert rule JSON (in
alerts/), add a"__contact_point__": "<contact-point-name>"field referencing the contact point'sname - The script will strip
__contact_point__before sending to Grafana and automatically create a child route matching the alert to that contact point - Multiple alerts can share the same contact point by referencing the same name
- Rules are created in the specified folder (default: LPS)
- Script automatically creates the folder if it doesn't exist
- Duplicate rules and contact points are skipped (no error)
- Uses Grafana Provisioning API for reliable imports
- Script looks for JSON files in the
alerts/andcontact-points/subdirectories relative to its location - Rules created using this script cannot be edited in the Grafana UI
- Custom contact points have
disableResolveMessageset to prevent a second email when the alert resolves