@@ -17,6 +17,7 @@ use api::types::{
1717use std:: future:: Future ;
1818use std:: pin:: Pin ;
1919use std:: sync:: Arc ;
20+ use std:: time:: Duration ;
2021
2122use log:: { debug, trace} ;
2223
@@ -25,6 +26,7 @@ use crate::util::KeyValueVecKeyPrinter;
2526const MAXIMUM_REQUEST_BODY_SIZE : usize = 1024 * 1024 * 1024 ;
2627const PROTOCOL_VERSION_HEADER : & str = "vss-protocol-version" ;
2728const PROTOCOL_VERSION : & str = "0" ;
29+ const HEALTH_CHECK_TIMEOUT : Duration = Duration :: from_secs ( 2 ) ;
2830
2931#[ derive( Clone , Copy ) ]
3032pub ( crate ) struct VssServiceConfig {
@@ -80,14 +82,8 @@ impl Service<Request<Incoming>> for VssService {
8082
8183 Box :: pin ( async move {
8284 if path == "/metrics" {
83- let response = b"# HELP vss_service_up Is the vss service up?\n # TYPE vss_service_up gauge\n vss_service_up 1\n " ;
84- return Ok ( Response :: builder ( )
85- . status ( StatusCode :: OK )
86- . header ( "Content-Type" , "text/plain; version=0.0.4" )
87- . header ( PROTOCOL_VERSION_HEADER , PROTOCOL_VERSION . as_bytes ( ) )
88- . body ( Full :: new ( Bytes :: from_static ( response) ) )
89- // unwrap safety: body only errors when previous chained calls failed.
90- . unwrap ( ) ) ;
85+ let is_healthy = check_store_health ( & store) . await ;
86+ return Ok ( build_metrics_response ( is_healthy) ) ;
9187 }
9288
9389 let prefix_stripped_path = path. strip_prefix ( BASE_PATH_PREFIX ) . unwrap_or_default ( ) ;
@@ -257,6 +253,33 @@ fn build_response(status_code: StatusCode, body: Bytes) -> Response<Full<Bytes>>
257253 . unwrap ( )
258254}
259255
256+ async fn check_store_health ( store : & Arc < dyn KvStore > ) -> bool {
257+ match tokio:: time:: timeout ( HEALTH_CHECK_TIMEOUT , store. is_healthy ( ) ) . await {
258+ Ok ( is_healthy) => is_healthy,
259+ Err ( _) => false ,
260+ }
261+ }
262+
263+ fn build_metrics_response ( is_healthy : bool ) -> Response < Full < Bytes > > {
264+ let response = if is_healthy {
265+ Bytes :: from_static (
266+ b"# HELP vss_service_up Is the vss service up?\n # TYPE vss_service_up gauge\n vss_service_up 1\n " ,
267+ )
268+ } else {
269+ Bytes :: from_static (
270+ b"# HELP vss_service_up Is the vss service up?\n # TYPE vss_service_up gauge\n vss_service_up 0\n " ,
271+ )
272+ } ;
273+
274+ Response :: builder ( )
275+ . status ( StatusCode :: OK )
276+ . header ( "Content-Type" , "text/plain; version=0.0.4" )
277+ . header ( PROTOCOL_VERSION_HEADER , PROTOCOL_VERSION . as_bytes ( ) )
278+ . body ( Full :: new ( response) )
279+ // unwrap safety: body only errors when previous chained calls failed.
280+ . unwrap ( )
281+ }
282+
260283fn build_error_response ( e : VssError ) -> Response < Full < Bytes > > {
261284 let ( status_code, error_response) = match e {
262285 VssError :: NoSuchKeyError ( msg) => {
@@ -326,4 +349,36 @@ mod tests {
326349 PROTOCOL_VERSION ,
327350 ) ;
328351 }
352+
353+ #[ tokio:: test]
354+ async fn build_metrics_response_reports_healthy_store ( ) {
355+ let response = build_metrics_response ( true ) ;
356+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
357+ assert_eq ! (
358+ response. headers( ) . get( PROTOCOL_VERSION_HEADER ) . unwrap( ) . to_str( ) . unwrap( ) ,
359+ PROTOCOL_VERSION ,
360+ ) ;
361+
362+ let body = response. into_body ( ) . collect ( ) . await . unwrap ( ) . to_bytes ( ) ;
363+ assert_eq ! (
364+ body. as_ref( ) ,
365+ b"# HELP vss_service_up Is the vss service up?\n # TYPE vss_service_up gauge\n vss_service_up 1\n " ,
366+ ) ;
367+ }
368+
369+ #[ tokio:: test]
370+ async fn build_metrics_response_reports_unhealthy_store ( ) {
371+ let response = build_metrics_response ( false ) ;
372+ assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
373+ assert_eq ! (
374+ response. headers( ) . get( PROTOCOL_VERSION_HEADER ) . unwrap( ) . to_str( ) . unwrap( ) ,
375+ PROTOCOL_VERSION ,
376+ ) ;
377+
378+ let body = response. into_body ( ) . collect ( ) . await . unwrap ( ) . to_bytes ( ) ;
379+ assert_eq ! (
380+ body. as_ref( ) ,
381+ b"# HELP vss_service_up Is the vss service up?\n # TYPE vss_service_up gauge\n vss_service_up 0\n " ,
382+ ) ;
383+ }
329384}
0 commit comments