Skip to content

Commit e97caed

Browse files
authored
Merge pull request #2491 from pyth-network/price-pusher-metrics
feat(apps/price_pusher): add prom metrics
2 parents d61dca2 + 19ebf18 commit e97caed

18 files changed

+2207
-321
lines changed

apps/price_pusher/README.md

+114
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,117 @@ pushed twice and you won't pay additional costs most of the time.** However, the
259259
conditions in the RPCs because they are often behind a load balancer which can sometimes cause rejected
260260
transactions to land on-chain. You can reduce the chances of additional cost overhead by reducing the
261261
pushing frequency.
262+
263+
## Prometheus Metrics
264+
265+
The price_pusher now supports Prometheus metrics to monitor the health and performance of the price update service. Metrics are exposed via an HTTP endpoint that can be scraped by Prometheus.
266+
267+
### Available Metrics
268+
269+
The following metrics are available:
270+
271+
- **pyth_price_last_published_time** (Gauge): The last published time of a price feed in unix timestamp, labeled by price_id and alias
272+
- **pyth_price_update_attempts_total** (Counter): Total number of price update attempts with their trigger condition and status, labeled by price_id, alias, trigger, and status
273+
- **pyth_price_feeds_total** (Gauge): Total number of price feeds being monitored
274+
- **pyth_wallet_balance** (Gauge): Current wallet balance of the price pusher in native token units, labeled by wallet_address and network
275+
276+
### Configuration
277+
278+
Metrics are enabled by default and can be configured using the following command-line options:
279+
280+
- `--enable-metrics`: Enable or disable the Prometheus metrics server (default: true)
281+
- `--metrics-port`: Port for the Prometheus metrics server (default: 9090)
282+
283+
Example:
284+
285+
```bash
286+
pnpm run dev evm --config config.evm.mainnet.json --metrics-port 9091
287+
```
288+
289+
### Running Locally with Docker
290+
291+
You can run the monitoring stack (Prometheus and Grafana) using the provided docker-compose configuration:
292+
293+
1. Use the sample docker-compose file for metrics:
294+
295+
```bash
296+
docker-compose -f docker-compose.metrics.sample.yaml up
297+
```
298+
299+
This will start:
300+
- Prometheus server on port 9090 with the alerts configured in alerts.sample.yml
301+
- Grafana server on port 3000 with default credentials (admin/admin)
302+
303+
The docker-compose.metrics.sample.yaml file includes a pre-configured Grafana dashboard (see the [Dashboard](#dashboard) section below) that displays all the metrics mentioned above. This dashboard provides monitoring of your price pusher operations with panels for configured feeds, active feeds, wallet balance, update statistics, and error tracking. The dashboard is automatically provisioned when you start the stack with docker-compose.
304+
305+
### Example Grafana Queries
306+
307+
Here are some example Grafana queries to monitor your price feeds:
308+
309+
1. Last published time for each price feed:
310+
311+
```
312+
pyth_price_last_published_time
313+
```
314+
315+
2. Number of price updates in the last hour:
316+
317+
```
318+
sum(increase(pyth_price_update_attempts_total{status="success"}[1h]))
319+
```
320+
321+
3. Price feeds not updated in the last hour:
322+
323+
```
324+
time() - pyth_price_last_published_time > 3600
325+
```
326+
327+
4. Distribution of update conditions:
328+
329+
```
330+
sum by (condition) (increase(pyth_update_conditions_total[$__range]))
331+
```
332+
333+
5. Monitor wallet balances:
334+
335+
```
336+
pyth_wallet_balance
337+
```
338+
339+
6. Detect low wallet balances (below 0.1 tokens):
340+
341+
```
342+
pyth_wallet_balance < 0.1
343+
```
344+
345+
### Dashboard
346+
347+
The docker-compose setup includes a pre-configured Grafana dashboard (`grafana-dashboard.sample.json`) that provides monitoring of your price pusher operations. The dashboard includes the following panels:
348+
349+
- **Configured Price Feeds**: Shows the number of price feeds configured in your price-config file.
350+
- **Active Price Feeds**: Displays the number of price feeds currently being actively monitored.
351+
- **Time Since Last Update**: Shows how long it's been since the last successful price update was published on-chain.
352+
- **Price Feeds List**: A table listing all configured price feeds with their details.
353+
- **Successful Updates (Current Range)**: Graph showing the number of successful price updates over the current range with timeline.
354+
- **Update Conditions Distribution**: Pie chart showing the distribution of update conditions (YES/NO/EARLY) over the selected time range.
355+
- **Wallet Balance**: Current balance of your wallet in native token units.
356+
- **Wallet Balance Over Time**: Graph tracking your wallet balance over time to monitor consumption.
357+
- **Failed Updates (Current Range)**: Graph showing the number of failed price updates over the current range with timeline.
358+
359+
When you first start the monitoring stack, the dashboard may show "No data" in the panels until the price pusher has been running for some time and has collected sufficient metrics.
360+
361+
This dashboard is automatically provisioned when you start the docker-compose stack and provides visibility into the health and performance of your price pusher deployment.
362+
363+
### Alerting
364+
365+
The price pusher includes pre-configured Prometheus alerting rules in the `alerts.sample.yml` file. These rules monitor various aspects of the price pusher's operation, including:
366+
367+
- Price feeds not being updated for an extended period (>1 hour)
368+
- High error rates in price update attempts
369+
- No successful price updates across all feeds in the last 30 minutes
370+
- Service availability monitoring
371+
- Low wallet balances with two severity levels:
372+
- Warning: Balance below 0.1 native tokens
373+
- Critical: Balance below 0.01 native tokens (transactions may fail soon)
374+
375+
When using the docker-compose setup, these alerts are automatically loaded into Prometheus and can be viewed in the Alerting section of Grafana after setting up the Prometheus data source.

apps/price_pusher/alerts.sample.yml

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
groups:
2+
- name: price_pusher_alerts
3+
rules:
4+
- alert: PriceFeedNotUpdated
5+
expr: time() - pyth_price_last_published_time > 3600
6+
for: 5m
7+
labels:
8+
severity: warning
9+
annotations:
10+
summary: "Price feed not updated"
11+
description: "Price feed {{ $labels.alias }} has not been updated for more than 1 hour"
12+
13+
- alert: HighErrorRate
14+
expr: sum(increase(pyth_price_update_attempts_total{status="error"}[15m])) > 5
15+
for: 5m
16+
labels:
17+
severity: warning
18+
annotations:
19+
summary: "High error rate in price updates"
20+
description: "There have been more than 5 errors in the last 15 minutes"
21+
22+
- alert: NoRecentPriceUpdates
23+
expr: sum(increase(pyth_price_update_attempts_total{status="success"}[30m])) == 0
24+
for: 5m
25+
labels:
26+
severity: critical
27+
annotations:
28+
summary: "No recent price updates"
29+
description: "No price updates have been pushed in the last 30 minutes"
30+
31+
- alert: PricePusherDown
32+
expr: up{job=~"price_pusher.*"} == 0
33+
for: 1m
34+
labels:
35+
severity: critical
36+
annotations:
37+
summary: "Price pusher service is down"
38+
description: "The price pusher service {{ $labels.instance }} is down"
39+
40+
- alert: WalletBalanceLow
41+
expr: pyth_wallet_balance < 0.1
42+
for: 5m
43+
labels:
44+
severity: warning
45+
annotations:
46+
summary: "Wallet balance is getting low"
47+
description: "Wallet {{ $labels.wallet_address }} on network {{ $labels.network }} has balance below 0.1 native tokens"
48+
49+
- alert: WalletBalanceCritical
50+
expr: pyth_wallet_balance < 0.01
51+
for: 2m
52+
labels:
53+
severity: critical
54+
annotations:
55+
summary: "Wallet balance critically low"
56+
description: "Wallet {{ $labels.wallet_address }} on network {{ $labels.network }} has balance below 0.01 native tokens. Transactions may fail soon!"
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: 1
2+
3+
providers:
4+
- name: 'Pyth Price Pusher'
5+
orgId: 1
6+
folder: ''
7+
type: file
8+
disableDeletion: false
9+
editable: true
10+
options:
11+
path: /var/lib/grafana/dashboards
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: 1
2+
3+
datasources:
4+
- name: Prometheus
5+
type: prometheus
6+
access: proxy
7+
url: http://prometheus:9090
8+
isDefault: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
version: "3"
2+
3+
services:
4+
prometheus:
5+
image: prom/prometheus:latest
6+
container_name: prometheus
7+
ports:
8+
- "9090:9090"
9+
volumes:
10+
- ./prometheus.sample.yml:/etc/prometheus/prometheus.yml
11+
- ./alerts.sample.yml:/etc/prometheus/alerts.yml
12+
command:
13+
- "--config.file=/etc/prometheus/prometheus.yml"
14+
- "--storage.tsdb.path=/prometheus"
15+
- "--web.console.libraries=/usr/share/prometheus/console_libraries"
16+
- "--web.console.templates=/usr/share/prometheus/consoles"
17+
networks:
18+
- monitoring
19+
20+
grafana:
21+
image: grafana/grafana:latest
22+
container_name: grafana
23+
ports:
24+
- "3000:3000"
25+
volumes:
26+
- grafana-storage:/var/lib/grafana
27+
- ./grafana-dashboard.sample.json:/var/lib/grafana/dashboards/pyth-price-pusher-dashboard.json
28+
- ./dashboard.sample.yml:/etc/grafana/provisioning/dashboards/dashboard.yml
29+
- ./datasource.sample.yml:/etc/grafana/provisioning/datasources/datasource.yml
30+
environment:
31+
- GF_SECURITY_ADMIN_USER=admin
32+
- GF_SECURITY_ADMIN_PASSWORD=admin
33+
- GF_USERS_ALLOW_SIGN_UP=false
34+
depends_on:
35+
- prometheus
36+
networks:
37+
- monitoring
38+
39+
networks:
40+
monitoring:
41+
driver: bridge
42+
43+
volumes:
44+
grafana-storage:

0 commit comments

Comments
 (0)