@@ -69,6 +69,7 @@ pub struct KeeperMetrics {
69
69
pub balance : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
70
70
pub collected_fee : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
71
71
pub current_fee : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
72
+ pub target_provider_fee : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
72
73
pub total_gas_spent : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
73
74
pub total_gas_fee_spent : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
74
75
pub requests : Family < AccountLabel , Counter > ,
@@ -78,6 +79,10 @@ pub struct KeeperMetrics {
78
79
pub requests_reprocessed : Family < AccountLabel , Counter > ,
79
80
pub reveals : Family < AccountLabel , Counter > ,
80
81
pub request_duration_ms : Family < AccountLabel , Histogram > ,
82
+ pub retry_count : Family < AccountLabel , Histogram > ,
83
+ pub final_gas_multiplier : Family < AccountLabel , Histogram > ,
84
+ pub final_fee_multiplier : Family < AccountLabel , Histogram > ,
85
+ pub gas_price_estimate : Family < AccountLabel , Gauge < f64 , AtomicU64 > > ,
81
86
}
82
87
83
88
impl Default for KeeperMetrics {
@@ -88,6 +93,7 @@ impl Default for KeeperMetrics {
88
93
balance : Family :: default ( ) ,
89
94
collected_fee : Family :: default ( ) ,
90
95
current_fee : Family :: default ( ) ,
96
+ target_provider_fee : Family :: default ( ) ,
91
97
total_gas_spent : Family :: default ( ) ,
92
98
total_gas_fee_spent : Family :: default ( ) ,
93
99
requests : Family :: default ( ) ,
@@ -105,6 +111,18 @@ impl Default for KeeperMetrics {
105
111
. into_iter ( ) ,
106
112
)
107
113
} ) ,
114
+ retry_count : Family :: new_with_constructor ( || {
115
+ Histogram :: new ( vec ! [ 0.0 , 1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 10.0 , 15.0 , 20.0 ] . into_iter ( ) )
116
+ } ) ,
117
+ final_gas_multiplier : Family :: new_with_constructor ( || {
118
+ Histogram :: new (
119
+ vec ! [ 100.0 , 125.0 , 150.0 , 200.0 , 300.0 , 400.0 , 500.0 , 600.0 ] . into_iter ( ) ,
120
+ )
121
+ } ) ,
122
+ final_fee_multiplier : Family :: new_with_constructor ( || {
123
+ Histogram :: new ( vec ! [ 100.0 , 110.0 , 120.0 , 140.0 , 160.0 , 180.0 , 200.0 ] . into_iter ( ) )
124
+ } ) ,
125
+ gas_price_estimate : Family :: default ( ) ,
108
126
}
109
127
}
110
128
}
@@ -174,6 +192,12 @@ impl KeeperMetrics {
174
192
keeper_metrics. current_fee . clone ( ) ,
175
193
) ;
176
194
195
+ writable_registry. register (
196
+ "target_provider_fee" ,
197
+ "Target fee in ETH -- differs from current_fee in that this is the goal, and current_fee is the on-chain value." ,
198
+ keeper_metrics. target_provider_fee . clone ( ) ,
199
+ ) ;
200
+
177
201
writable_registry. register (
178
202
"total_gas_spent" ,
179
203
"Total gas spent revealing requests" ,
@@ -198,6 +222,30 @@ impl KeeperMetrics {
198
222
keeper_metrics. request_duration_ms . clone ( ) ,
199
223
) ;
200
224
225
+ writable_registry. register (
226
+ "retry_count" ,
227
+ "Number of retries for successful transactions" ,
228
+ keeper_metrics. retry_count . clone ( ) ,
229
+ ) ;
230
+
231
+ writable_registry. register (
232
+ "final_gas_multiplier" ,
233
+ "Final gas multiplier percentage for successful transactions" ,
234
+ keeper_metrics. final_gas_multiplier . clone ( ) ,
235
+ ) ;
236
+
237
+ writable_registry. register (
238
+ "final_fee_multiplier" ,
239
+ "Final fee multiplier percentage for successful transactions" ,
240
+ keeper_metrics. final_fee_multiplier . clone ( ) ,
241
+ ) ;
242
+
243
+ writable_registry. register (
244
+ "gas_price_estimate" ,
245
+ "Gas price estimate for the blockchain (in gwei)" ,
246
+ keeper_metrics. gas_price_estimate . clone ( ) ,
247
+ ) ;
248
+
201
249
keeper_metrics
202
250
}
203
251
}
@@ -327,6 +375,7 @@ pub async fn run_keeper_threads(
327
375
spawn (
328
376
adjust_fee_wrapper (
329
377
contract. clone ( ) ,
378
+ chain_state. clone ( ) ,
330
379
chain_state. provider_address ,
331
380
ADJUST_FEE_INTERVAL ,
332
381
chain_eth_config. legacy_tx ,
@@ -346,6 +395,7 @@ pub async fn run_keeper_threads(
346
395
u64:: try_from ( 100 + chain_eth_config. max_profit_pct )
347
396
. expect ( "max_profit_pct must be >= -100" ) ,
348
397
chain_eth_config. fee ,
398
+ metrics. clone ( ) ,
349
399
)
350
400
. in_current_span ( ) ,
351
401
) ;
@@ -479,6 +529,25 @@ pub async fn process_event_with_backoff(
479
529
. request_duration_ms
480
530
. get_or_create ( & account_label)
481
531
. observe ( duration. as_millis ( ) as f64 ) ;
532
+
533
+ // Track retry count, gas multiplier, and fee multiplier for successful transactions
534
+ let num_retries = num_retries. load ( std:: sync:: atomic:: Ordering :: Relaxed ) ;
535
+ metrics
536
+ . retry_count
537
+ . get_or_create ( & account_label)
538
+ . observe ( num_retries as f64 ) ;
539
+
540
+ let gas_multiplier = escalation_policy. get_gas_multiplier_pct ( num_retries) ;
541
+ metrics
542
+ . final_gas_multiplier
543
+ . get_or_create ( & account_label)
544
+ . observe ( gas_multiplier as f64 ) ;
545
+
546
+ let fee_multiplier = escalation_policy. get_fee_multiplier_pct ( num_retries) ;
547
+ metrics
548
+ . final_fee_multiplier
549
+ . get_or_create ( & account_label)
550
+ . observe ( fee_multiplier as f64 ) ;
482
551
}
483
552
Err ( e) => {
484
553
// In case the callback did not succeed, we double-check that the request is still on-chain.
@@ -1133,6 +1202,7 @@ pub async fn send_and_confirm(contract_call: PythContractCall) -> Result<()> {
1133
1202
#[ allow( clippy:: too_many_arguments) ]
1134
1203
pub async fn adjust_fee_wrapper (
1135
1204
contract : Arc < InstrumentedSignablePythContract > ,
1205
+ chain_state : BlockchainState ,
1136
1206
provider_address : Address ,
1137
1207
poll_interval : Duration ,
1138
1208
legacy_tx : bool ,
@@ -1141,6 +1211,7 @@ pub async fn adjust_fee_wrapper(
1141
1211
target_profit_pct : u64 ,
1142
1212
max_profit_pct : u64 ,
1143
1213
min_fee_wei : u128 ,
1214
+ metrics : Arc < KeeperMetrics > ,
1144
1215
) {
1145
1216
// The maximum balance of accrued fees + provider wallet balance. None if we haven't observed a value yet.
1146
1217
let mut high_water_pnl: Option < U256 > = None ;
@@ -1149,6 +1220,7 @@ pub async fn adjust_fee_wrapper(
1149
1220
loop {
1150
1221
if let Err ( e) = adjust_fee_if_necessary (
1151
1222
contract. clone ( ) ,
1223
+ chain_state. id . clone ( ) ,
1152
1224
provider_address,
1153
1225
legacy_tx,
1154
1226
gas_limit,
@@ -1158,6 +1230,7 @@ pub async fn adjust_fee_wrapper(
1158
1230
min_fee_wei,
1159
1231
& mut high_water_pnl,
1160
1232
& mut sequence_number_of_last_fee_update,
1233
+ metrics. clone ( ) ,
1161
1234
)
1162
1235
. in_current_span ( )
1163
1236
. await
@@ -1232,6 +1305,7 @@ pub async fn update_commitments_if_necessary(
1232
1305
#[ allow( clippy:: too_many_arguments) ]
1233
1306
pub async fn adjust_fee_if_necessary (
1234
1307
contract : Arc < InstrumentedSignablePythContract > ,
1308
+ chain_id : ChainId ,
1235
1309
provider_address : Address ,
1236
1310
legacy_tx : bool ,
1237
1311
gas_limit : u64 ,
@@ -1241,6 +1315,7 @@ pub async fn adjust_fee_if_necessary(
1241
1315
min_fee_wei : u128 ,
1242
1316
high_water_pnl : & mut Option < U256 > ,
1243
1317
sequence_number_of_last_fee_update : & mut Option < u64 > ,
1318
+ metrics : Arc < KeeperMetrics > ,
1244
1319
) -> Result < ( ) > {
1245
1320
let provider_info = contract
1246
1321
. get_provider_info ( provider_address)
@@ -1256,6 +1331,17 @@ pub async fn adjust_fee_if_necessary(
1256
1331
let max_callback_cost: u128 = estimate_tx_cost ( contract. clone ( ) , legacy_tx, gas_limit. into ( ) )
1257
1332
. await
1258
1333
. map_err ( |e| anyhow ! ( "Could not estimate transaction cost. error {:?}" , e) ) ?;
1334
+
1335
+ let account_label = AccountLabel {
1336
+ chain_id : chain_id. clone ( ) ,
1337
+ address : provider_address. to_string ( ) ,
1338
+ } ;
1339
+
1340
+ metrics
1341
+ . gas_price_estimate
1342
+ . get_or_create ( & account_label)
1343
+ . set ( ( max_callback_cost / u128:: from ( gas_limit) ) as f64 / 1e9 ) ;
1344
+
1259
1345
let target_fee_min = std:: cmp:: max (
1260
1346
( max_callback_cost * u128:: from ( min_profit_pct) ) / 100 ,
1261
1347
min_fee_wei,
@@ -1264,6 +1350,11 @@ pub async fn adjust_fee_if_necessary(
1264
1350
( max_callback_cost * u128:: from ( target_profit_pct) ) / 100 ,
1265
1351
min_fee_wei,
1266
1352
) ;
1353
+ metrics
1354
+ . target_provider_fee
1355
+ . get_or_create ( & account_label)
1356
+ . set ( ( ( max_callback_cost * u128:: from ( target_profit_pct) ) / 100 ) as f64 / 1e18 ) ;
1357
+
1267
1358
let target_fee_max = std:: cmp:: max (
1268
1359
( max_callback_cost * u128:: from ( max_profit_pct) ) / 100 ,
1269
1360
min_fee_wei,
0 commit comments