@@ -18,6 +18,7 @@ pub struct SubgraphInstanceMetrics {
1818 pub firehose_connection_errors : Counter ,
1919 pub stopwatch : StopwatchMetrics ,
2020 pub deployment_status : DeploymentStatusMetric ,
21+ pub deployment_synced : DeploymentSyncedMetric ,
2122
2223 trigger_processing_duration : Box < Histogram > ,
2324 blocks_processed_secs : Box < Counter > ,
@@ -91,13 +92,16 @@ impl SubgraphInstanceMetrics {
9192 )
9293 . expect ( "failed to create blocks_processed_count counter" ) ;
9394
95+ let deployment_synced = DeploymentSyncedMetric :: register ( & registry, subgraph_hash) ;
96+
9497 Self {
9598 block_trigger_count,
9699 block_processing_duration,
97100 block_ops_transaction_duration,
98101 firehose_connection_errors,
99102 stopwatch,
100103 deployment_status,
104+ deployment_synced,
101105 trigger_processing_duration,
102106 blocks_processed_secs,
103107 blocks_processed_count,
@@ -120,6 +124,7 @@ impl SubgraphInstanceMetrics {
120124 registry. unregister ( self . block_trigger_count . clone ( ) ) ;
121125 registry. unregister ( self . trigger_processing_duration . clone ( ) ) ;
122126 registry. unregister ( self . block_ops_transaction_duration . clone ( ) ) ;
127+ registry. unregister ( Box :: new ( self . deployment_synced . inner . clone ( ) ) ) ;
123128 }
124129}
125130
@@ -213,3 +218,52 @@ impl DeploymentStatusMetric {
213218 self . inner . set ( Self :: STATUS_FAILED ) ;
214219 }
215220}
221+
222+ /// Indicates whether a deployment has reached the chain head since it was deployed.
223+ pub struct DeploymentSyncedMetric {
224+ inner : IntGauge ,
225+
226+ // If, for some reason, a deployment reports that it is synced, and then reports that it is not
227+ // synced during an execution, this prevents the metric from reverting to the not synced state.
228+ previously_synced : std:: sync:: OnceLock < ( ) > ,
229+ }
230+
231+ impl DeploymentSyncedMetric {
232+ const NOT_SYNCED : i64 = 0 ;
233+ const SYNCED : i64 = 1 ;
234+
235+ /// Registers the metric.
236+ pub fn register ( registry : & MetricsRegistry , deployment_hash : & str ) -> Self {
237+ let metric = registry
238+ . new_int_gauge (
239+ "deployment_synced" ,
240+ "Indicates whether a deployment has reached the chain head since it was deployed.\n \
241+ Possible values:\n \
242+ 0 - deployment is not synced;\n \
243+ 1 - deployment is synced;",
244+ [ ( "deployment" , deployment_hash) ] ,
245+ )
246+ . expect ( "failed to register `deployment_synced` gauge" ) ;
247+
248+ Self {
249+ inner : metric,
250+ previously_synced : std:: sync:: OnceLock :: new ( ) ,
251+ }
252+ }
253+
254+ /// Records the current sync status of the deployment.
255+ /// Will ignore all values after the first `true` is received.
256+ pub fn record ( & self , synced : bool ) {
257+ if self . previously_synced . get ( ) . is_some ( ) {
258+ return ;
259+ }
260+
261+ if synced {
262+ self . inner . set ( Self :: SYNCED ) ;
263+ let _ = self . previously_synced . set ( ( ) ) ;
264+ return ;
265+ }
266+
267+ self . inner . set ( Self :: NOT_SYNCED ) ;
268+ }
269+ }
0 commit comments