Skip to content

Commit 48bfa09

Browse files
committed
feat: update metrics tracking for price updates and errors, enhancing Grafana dashboard descriptions
1 parent 08ea7db commit 48bfa09

File tree

4 files changed

+92
-43
lines changed

4 files changed

+92
-43
lines changed

apps/price_pusher/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,11 +383,11 @@ The docker-compose setup includes a pre-configured Grafana dashboard (`grafana-d
383383
- **Active Price Feeds**: Displays the number of price feeds currently being actively monitored.
384384
- **Time Since Last Update**: Shows how long it's been since the last successful price update was published on-chain.
385385
- **Price Feeds List**: A table listing all configured price feeds with their details.
386-
- **Price Updates (Last Hour)**: Graph showing the number of price updates over the last hour with timeline.
386+
- **Successful Updates (Current Range)**: Graph showing the number of successful price updates over the current range with timeline.
387387
- **Update Conditions Distribution**: Pie chart showing the distribution of update conditions (YES/NO/EARLY) over the selected time range.
388388
- **Wallet Balance**: Current balance of your wallet in native token units.
389389
- **Wallet Balance Over Time**: Graph tracking your wallet balance over time to monitor consumption.
390-
- **Update Errors**: Tracks errors encountered during price update operations.
390+
- **Failed Updates (Current Range)**: Graph showing the number of failed price updates over the current range with timeline.
391391

392392
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.
393393

apps/price_pusher/grafana-dashboard.sample.json

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@
355355
"uid": "prometheus"
356356
},
357357
"editorMode": "code",
358-
"expr": "pyth_price_updates_total",
358+
"expr": "pyth_price_update_attempts_total{status=\"success\"}",
359359
"format": "table",
360360
"instant": true,
361361
"legendFormat": "__auto",
@@ -496,7 +496,23 @@
496496
},
497497
"unit": "none"
498498
},
499-
"overrides": []
499+
"overrides": [
500+
{
501+
"matcher": {
502+
"id": "byName",
503+
"options": "Updates"
504+
},
505+
"properties": [
506+
{
507+
"id": "color",
508+
"value": {
509+
"fixedColor": "green",
510+
"mode": "fixed"
511+
}
512+
}
513+
]
514+
}
515+
]
500516
},
501517
"gridPos": {
502518
"h": 8,
@@ -526,13 +542,13 @@
526542
"uid": "prometheus"
527543
},
528544
"editorMode": "code",
529-
"expr": "sum(increase(pyth_price_updates_total[$__range]))",
545+
"expr": "sum(increase(pyth_price_update_attempts_total{status=\"success\"}[$__range]))",
530546
"legendFormat": "Updates",
531547
"range": true,
532548
"refId": "A"
533549
}
534550
],
535-
"title": "Price Updates (Current Range)",
551+
"title": "Successful Updates (Current Range)",
536552
"type": "timeseries"
537553
},
538554
{
@@ -645,9 +661,9 @@
645661
"uid": "prometheus"
646662
},
647663
"editorMode": "code",
648-
"expr": "sum by (condition) (increase(pyth_update_conditions_total[$__range]))",
664+
"expr": "sum by (trigger) (increase(pyth_price_update_attempts_total[$__range]))",
649665
"instant": false,
650-
"legendFormat": "{{condition}}",
666+
"legendFormat": "{{trigger}}",
651667
"range": true,
652668
"refId": "A"
653669
}
@@ -909,13 +925,13 @@
909925
"uid": "prometheus"
910926
},
911927
"editorMode": "code",
912-
"expr": "sum(increase(pyth_price_update_errors_total[$__range]))",
928+
"expr": "sum(increase(pyth_price_update_attempts_total{status=\"error\"}[$__range]))",
913929
"legendFormat": "Errors",
914930
"range": true,
915931
"refId": "A"
916932
}
917933
],
918-
"title": "Update Errors",
934+
"title": "Failed Updates (Current Range)",
919935
"type": "timeseries"
920936
}
921937
],

apps/price_pusher/src/controller.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,21 @@ export class Controller {
109109
// Record successful updates
110110
if (this.metrics) {
111111
for (const config of pricesToPush) {
112-
this.metrics.recordPriceUpdate(config.id, config.alias);
112+
const triggerValue =
113+
shouldUpdate(
114+
config,
115+
this.sourcePriceListener.getLatestPriceInfo(config.id),
116+
this.targetPriceListener.getLatestPriceInfo(config.id),
117+
this.logger,
118+
) === UpdateCondition.YES
119+
? "yes"
120+
: "early";
121+
122+
this.metrics.recordPriceUpdate(
123+
config.id,
124+
config.alias,
125+
triggerValue,
126+
);
113127
}
114128
}
115129
} catch (error) {
@@ -121,7 +135,21 @@ export class Controller {
121135
// Record errors in metrics
122136
if (this.metrics) {
123137
for (const config of pricesToPush) {
124-
this.metrics.recordPriceUpdateError(config.id, config.alias);
138+
const triggerValue =
139+
shouldUpdate(
140+
config,
141+
this.sourcePriceListener.getLatestPriceInfo(config.id),
142+
this.targetPriceListener.getLatestPriceInfo(config.id),
143+
this.logger,
144+
) === UpdateCondition.YES
145+
? "yes"
146+
: "early";
147+
148+
this.metrics.recordPriceUpdateError(
149+
config.id,
150+
config.alias,
151+
triggerValue,
152+
);
125153
}
126154
}
127155
}

apps/price_pusher/src/metrics.ts

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@ export class PricePusherMetrics {
1212

1313
// Metrics for price feed updates
1414
public lastPublishedTime: Gauge<string>;
15-
public priceUpdatesTotal: Counter<string>;
15+
public priceUpdateAttempts: Counter<string>;
1616
public priceFeedsTotal: Gauge<string>;
17-
public priceUpdateErrors: Counter<string>;
18-
public updateConditionsTotal: Counter<string>;
1917
// Wallet metrics
2018
public walletBalance: Gauge<string>;
2119

@@ -35,10 +33,10 @@ export class PricePusherMetrics {
3533
registers: [this.registry],
3634
});
3735

38-
this.priceUpdatesTotal = new Counter({
39-
name: "pyth_price_updates_total",
40-
help: "Total number of price updates pushed to the chain",
41-
labelNames: ["price_id", "alias"],
36+
this.priceUpdateAttempts = new Counter({
37+
name: "pyth_price_update_attempts_total",
38+
help: "Total number of price update attempts with their trigger condition and status",
39+
labelNames: ["price_id", "alias", "trigger", "status"],
4240
registers: [this.registry],
4341
});
4442

@@ -48,20 +46,6 @@ export class PricePusherMetrics {
4846
registers: [this.registry],
4947
});
5048

51-
this.priceUpdateErrors = new Counter({
52-
name: "pyth_price_update_errors_total",
53-
help: "Total number of errors encountered during price updates",
54-
labelNames: ["price_id", "alias"],
55-
registers: [this.registry],
56-
});
57-
58-
this.updateConditionsTotal = new Counter({
59-
name: "pyth_update_conditions_total",
60-
help: "Total number of price update condition checks by status (YES/NO/EARLY)",
61-
labelNames: ["price_id", "alias", "condition"],
62-
registers: [this.registry],
63-
});
64-
6549
// Wallet balance metric
6650
this.walletBalance = new Gauge({
6751
name: "pyth_wallet_balance",
@@ -97,8 +81,17 @@ export class PricePusherMetrics {
9781
}
9882

9983
// Record a successful price update
100-
public recordPriceUpdate(priceId: string, alias: string): void {
101-
this.priceUpdatesTotal.inc({ price_id: priceId, alias });
84+
public recordPriceUpdate(
85+
priceId: string,
86+
alias: string,
87+
trigger: string = "yes",
88+
): void {
89+
this.priceUpdateAttempts.inc({
90+
price_id: priceId,
91+
alias,
92+
trigger: trigger.toLowerCase(),
93+
status: "success",
94+
});
10295
}
10396

10497
// Record update condition status (YES/NO/EARLY)
@@ -107,19 +100,31 @@ export class PricePusherMetrics {
107100
alias: string,
108101
condition: UpdateCondition,
109102
): void {
110-
const conditionLabel = UpdateCondition[condition];
111-
this.updateConditionsTotal.inc({
112-
price_id: priceId,
113-
alias,
114-
condition: conditionLabel,
115-
});
103+
const triggerLabel = UpdateCondition[condition].toLowerCase();
104+
// Only record as 'skipped' when the condition is NO
105+
if (condition === UpdateCondition.NO) {
106+
this.priceUpdateAttempts.inc({
107+
price_id: priceId,
108+
alias,
109+
trigger: triggerLabel,
110+
status: "skipped",
111+
});
112+
}
113+
// YES and EARLY don't increment the counter here - they'll be counted
114+
// when recordPriceUpdate or recordPriceUpdateError is called
116115
}
117116

118117
// Record a price update error
119-
public recordPriceUpdateError(priceId: string, alias: string): void {
120-
this.priceUpdateErrors.inc({
118+
public recordPriceUpdateError(
119+
priceId: string,
120+
alias: string,
121+
trigger: string = "yes",
122+
): void {
123+
this.priceUpdateAttempts.inc({
121124
price_id: priceId,
122125
alias,
126+
trigger: trigger.toLowerCase(),
127+
status: "error",
123128
});
124129
}
125130

0 commit comments

Comments
 (0)