1
+ import type { RollupContract } from '@aztec/ethereum' ;
2
+ import type { EthAddress } from '@aztec/foundation/eth-address' ;
1
3
import { createLogger } from '@aztec/foundation/log' ;
2
4
import type { L1PublishProofStats , L1PublishStats } from '@aztec/stdlib/stats' ;
3
5
import {
4
6
Attributes ,
7
+ type BatchObservableResult ,
5
8
type Gauge ,
6
9
type Histogram ,
10
+ type Meter ,
7
11
Metrics ,
12
+ type ObservableGauge ,
8
13
type TelemetryClient ,
14
+ type Tracer ,
9
15
type UpDownCounter ,
10
16
ValueType ,
11
17
} from '@aztec/telemetry-client' ;
12
18
13
- import { formatEther } from 'viem' ;
19
+ import { formatEther , formatUnits } from 'viem' ;
14
20
15
- export class ProverNodeMetrics {
21
+ export class ProverNodeJobMetrics {
16
22
proverEpochExecutionDuration : Histogram ;
17
23
provingJobDuration : Histogram ;
18
24
provingJobBlocks : Gauge ;
19
25
provingJobTransactions : Gauge ;
20
26
21
- gasPrice : Histogram ;
22
- txCount : UpDownCounter ;
23
- txDuration : Histogram ;
24
- txGas : Histogram ;
25
- txCalldataSize : Histogram ;
26
- txCalldataGas : Histogram ;
27
- txBlobDataGasUsed : Histogram ;
28
- txBlobDataGasCost : Histogram ;
29
- txTotalFee : Histogram ;
30
-
31
- private senderBalance : Gauge ;
32
-
33
27
constructor (
34
- public readonly client : TelemetryClient ,
35
- name = 'ProverNode' ,
28
+ private meter : Meter ,
29
+ public readonly tracer : Tracer ,
36
30
private logger = createLogger ( 'prover-node:publisher:metrics' ) ,
37
31
) {
38
- const meter = client . getMeter ( name ) ;
39
- this . proverEpochExecutionDuration = meter . createHistogram ( Metrics . PROVER_NODE_EXECUTION_DURATION , {
32
+ this . proverEpochExecutionDuration = this . meter . createHistogram ( Metrics . PROVER_NODE_EXECUTION_DURATION , {
40
33
description : 'Duration of execution of an epoch by the prover' ,
41
34
unit : 'ms' ,
42
35
valueType : ValueType . INT ,
43
36
} ) ;
44
- this . provingJobDuration = meter . createHistogram ( Metrics . PROVER_NODE_JOB_DURATION , {
37
+ this . provingJobDuration = this . meter . createHistogram ( Metrics . PROVER_NODE_JOB_DURATION , {
45
38
description : 'Duration of proving job' ,
46
39
unit : 's' ,
47
40
valueType : ValueType . DOUBLE ,
48
41
} ) ;
49
- this . provingJobBlocks = meter . createGauge ( Metrics . PROVER_NODE_JOB_BLOCKS , {
42
+ this . provingJobBlocks = this . meter . createGauge ( Metrics . PROVER_NODE_JOB_BLOCKS , {
50
43
description : 'Number of blocks in a proven epoch' ,
51
44
valueType : ValueType . INT ,
52
45
} ) ;
53
- this . provingJobTransactions = meter . createGauge ( Metrics . PROVER_NODE_JOB_TRANSACTIONS , {
46
+ this . provingJobTransactions = this . meter . createGauge ( Metrics . PROVER_NODE_JOB_TRANSACTIONS , {
54
47
description : 'Number of transactions in a proven epoch' ,
55
48
valueType : ValueType . INT ,
56
49
} ) ;
50
+ }
51
+
52
+ public recordProvingJob ( executionTimeMs : number , totalTimeMs : number , numBlocks : number , numTxs : number ) {
53
+ this . proverEpochExecutionDuration . record ( Math . ceil ( executionTimeMs ) ) ;
54
+ this . provingJobDuration . record ( totalTimeMs / 1000 ) ;
55
+ this . provingJobBlocks . record ( Math . floor ( numBlocks ) ) ;
56
+ this . provingJobTransactions . record ( Math . floor ( numTxs ) ) ;
57
+ }
58
+ }
59
+
60
+ export class ProverNodeRewardsMetrics {
61
+ private rewards : ObservableGauge ;
62
+ private accumulatedRewards : UpDownCounter ;
63
+ private prevEpoch = - 1n ;
64
+ private proofSubmissionWindow = 0n ;
65
+
66
+ constructor (
67
+ private meter : Meter ,
68
+ private coinbase : EthAddress ,
69
+ private rollup : RollupContract ,
70
+ private logger = createLogger ( 'prover-node:publisher:metrics' ) ,
71
+ ) {
72
+ this . rewards = this . meter . createObservableGauge ( Metrics . PROVER_NODE_REWARDS_PER_EPOCH , {
73
+ valueType : ValueType . DOUBLE ,
74
+ description : 'The rewards earned' ,
75
+ } ) ;
76
+
77
+ this . accumulatedRewards = this . meter . createUpDownCounter ( Metrics . PROVER_NODE_REWARDS_TOTAL , {
78
+ valueType : ValueType . DOUBLE ,
79
+ description : 'The rewards earned (total)' ,
80
+ } ) ;
81
+ }
82
+
83
+ public async start ( ) {
84
+ this . proofSubmissionWindow = await this . rollup . getProofSubmissionWindow ( ) ;
85
+ this . meter . addBatchObservableCallback ( this . observe , [ this . rewards ] ) ;
86
+ }
87
+
88
+ public stop ( ) {
89
+ this . meter . removeBatchObservableCallback ( this . observe , [ this . rewards ] ) ;
90
+ }
91
+
92
+ private observe = async ( observer : BatchObservableResult ) : Promise < void > => {
93
+ const slot = await this . rollup . getSlotNumber ( ) ;
94
+
95
+ // look at the prev epoch so that we get an accurate value, after proof submission window has closed
96
+ if ( slot > this . proofSubmissionWindow ) {
97
+ const closedEpoch = await this . rollup . getEpochNumberForSlotNumber ( slot - this . proofSubmissionWindow ) ;
98
+ const rewards = await this . rollup . getSpecificProverRewardsForEpoch ( closedEpoch , this . coinbase ) ;
99
+
100
+ const fmt = parseFloat ( formatUnits ( rewards , 18 ) ) ;
101
+
102
+ observer . observe ( this . rewards , fmt , {
103
+ [ Attributes . COINBASE ] : this . coinbase . toString ( ) ,
104
+ } ) ;
105
+
106
+ // only accumulate once per epoch
107
+ if ( closedEpoch > this . prevEpoch ) {
108
+ this . prevEpoch = closedEpoch ;
109
+ this . accumulatedRewards . add ( fmt , {
110
+ [ Attributes . COINBASE ] : this . coinbase . toString ( ) ,
111
+ } ) ;
112
+ }
113
+ }
114
+ } ;
115
+ }
57
116
58
- this . gasPrice = meter . createHistogram ( Metrics . L1_PUBLISHER_GAS_PRICE , {
117
+ export class ProverNodePublisherMetrics {
118
+ gasPrice : Histogram ;
119
+ txCount : UpDownCounter ;
120
+ txDuration : Histogram ;
121
+ txGas : Histogram ;
122
+ txCalldataSize : Histogram ;
123
+ txCalldataGas : Histogram ;
124
+ txBlobDataGasUsed : Histogram ;
125
+ txBlobDataGasCost : Histogram ;
126
+ txTotalFee : Histogram ;
127
+
128
+ private senderBalance : Gauge ;
129
+ private meter : Meter ;
130
+
131
+ constructor (
132
+ public readonly client : TelemetryClient ,
133
+ name = 'ProverNode' ,
134
+ private logger = createLogger ( 'prover-node:publisher:metrics' ) ,
135
+ ) {
136
+ this . meter = client . getMeter ( name ) ;
137
+
138
+ this . gasPrice = this . meter . createHistogram ( Metrics . L1_PUBLISHER_GAS_PRICE , {
59
139
description : 'The gas price used for transactions' ,
60
140
unit : 'gwei' ,
61
141
valueType : ValueType . DOUBLE ,
62
142
} ) ;
63
143
64
- this . txCount = meter . createUpDownCounter ( Metrics . L1_PUBLISHER_TX_COUNT , {
144
+ this . txCount = this . meter . createUpDownCounter ( Metrics . L1_PUBLISHER_TX_COUNT , {
65
145
description : 'The number of transactions processed' ,
66
146
} ) ;
67
147
68
- this . txDuration = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_DURATION , {
148
+ this . txDuration = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_DURATION , {
69
149
description : 'The duration of transaction processing' ,
70
150
unit : 'ms' ,
71
151
valueType : ValueType . INT ,
72
152
} ) ;
73
153
74
- this . txGas = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_GAS , {
154
+ this . txGas = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_GAS , {
75
155
description : 'The gas consumed by transactions' ,
76
156
unit : 'gas' ,
77
157
valueType : ValueType . INT ,
78
158
} ) ;
79
159
80
- this . txCalldataSize = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_CALLDATA_SIZE , {
160
+ this . txCalldataSize = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_CALLDATA_SIZE , {
81
161
description : 'The size of the calldata in transactions' ,
82
162
unit : 'By' ,
83
163
valueType : ValueType . INT ,
84
164
} ) ;
85
165
86
- this . txCalldataGas = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_CALLDATA_GAS , {
166
+ this . txCalldataGas = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_CALLDATA_GAS , {
87
167
description : 'The gas consumed by the calldata in transactions' ,
88
168
unit : 'gas' ,
89
169
valueType : ValueType . INT ,
90
170
} ) ;
91
171
92
- this . txBlobDataGasUsed = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_BLOBDATA_GAS_USED , {
172
+ this . txBlobDataGasUsed = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_BLOBDATA_GAS_USED , {
93
173
description : 'The amount of blob gas used in transactions' ,
94
174
unit : 'gas' ,
95
175
valueType : ValueType . INT ,
96
176
} ) ;
97
177
98
- this . txBlobDataGasCost = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_BLOBDATA_GAS_COST , {
178
+ this . txBlobDataGasCost = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_BLOBDATA_GAS_COST , {
99
179
description : 'The gas cost of blobs in transactions' ,
100
180
unit : 'gwei' ,
101
181
valueType : ValueType . INT ,
102
182
} ) ;
103
183
104
- this . txTotalFee = meter . createHistogram ( Metrics . L1_PUBLISHER_TX_TOTAL_FEE , {
184
+ this . txTotalFee = this . meter . createHistogram ( Metrics . L1_PUBLISHER_TX_TOTAL_FEE , {
105
185
description : 'How much L1 tx costs' ,
106
186
unit : 'gwei' ,
107
187
valueType : ValueType . DOUBLE ,
@@ -112,7 +192,7 @@ export class ProverNodeMetrics {
112
192
} ,
113
193
} ) ;
114
194
115
- this . senderBalance = meter . createGauge ( Metrics . L1_PUBLISHER_BALANCE , {
195
+ this . senderBalance = this . meter . createGauge ( Metrics . L1_PUBLISHER_BALANCE , {
116
196
unit : 'eth' ,
117
197
description : 'The balance of the sender address' ,
118
198
valueType : ValueType . DOUBLE ,
@@ -130,13 +210,6 @@ export class ProverNodeMetrics {
130
210
this . recordTx ( durationMs , stats ) ;
131
211
}
132
212
133
- public recordProvingJob ( executionTimeMs : number , totalTimeMs : number , numBlocks : number , numTxs : number ) {
134
- this . proverEpochExecutionDuration . record ( Math . ceil ( executionTimeMs ) ) ;
135
- this . provingJobDuration . record ( totalTimeMs / 1000 ) ;
136
- this . provingJobBlocks . record ( Math . floor ( numBlocks ) ) ;
137
- this . provingJobTransactions . record ( Math . floor ( numTxs ) ) ;
138
- }
139
-
140
213
public recordSenderBalance ( wei : bigint , senderAddress : string ) {
141
214
const eth = parseFloat ( formatEther ( wei , 'wei' ) ) ;
142
215
this . senderBalance . record ( eth , {
0 commit comments