@@ -44,6 +44,13 @@ pub struct GetQueueBacklogAnalyticsQuery;
4444) ]
4545pub struct GetQueueOperationsAnalyticsQuery ;
4646
47+ #[ derive( GraphQLQuery ) ]
48+ #[ graphql(
49+ schema_path = "gql/schema.graphql" ,
50+ query_path = "gql/zone_http_requests_query.graphql"
51+ ) ]
52+ pub struct GetZoneHttpRequestsQuery ;
53+
4754#[ allow( non_camel_case_types) ]
4855type float32 = f32 ;
4956
@@ -62,6 +69,9 @@ type uint32 = u32;
6269#[ allow( non_camel_case_types) ]
6370type float64 = f64 ;
6471
72+ #[ allow( non_camel_case_types) ]
73+ type uint16 = u16 ;
74+
6575pub async fn do_get_workers_analytics_query ( cloudflare_api_url : & String , cloudflare_api_key : & String , variables : get_workers_analytics_query:: Variables ) -> Result < Vec < Metric > , Box < dyn Error > > {
6676 let request_body = GetWorkersAnalyticsQuery :: build_query ( variables) ;
6777 //console_log!("request_body: {:?}", request_body);
@@ -411,6 +421,53 @@ pub async fn do_get_queue_operations_analytics_query(cloudflare_api_url: &String
411421 Ok ( prometheus_registry_to_opentelemetry_metrics ( registry, timestamp_nanos) )
412422}
413423
424+ pub async fn do_get_zone_http_requests_query ( cloudflare_api_url : & String , cloudflare_api_key : & String , variables : get_zone_http_requests_query:: Variables ) -> Result < Vec < Metric > , Box < dyn Error > > {
425+ let request_body = GetZoneHttpRequestsQuery :: build_query ( variables) ;
426+ let client = reqwest:: Client :: new ( ) ;
427+ let res = client. post ( cloudflare_api_url)
428+ . bearer_auth ( cloudflare_api_key)
429+ . json ( & request_body) . send ( ) . await ?;
430+
431+ if !res. status ( ) . is_success ( ) {
432+ console_log ! ( "GraphQL query failed: {:?}" , res. status( ) ) ;
433+ return Err ( Box :: new ( res. error_for_status ( ) . unwrap_err ( ) ) ) ;
434+ }
435+
436+ let response_body: Response < get_zone_http_requests_query:: ResponseData > = res. json ( ) . await ?;
437+ if response_body. errors . is_some ( ) {
438+ console_log ! ( "GraphQL query failed: {:?}" , response_body. errors) ;
439+ return Err ( Box :: new ( worker:: Error :: JsError ( "graphql" . parse ( ) . unwrap ( ) ) ) ) ;
440+ }
441+ let response_data: get_zone_http_requests_query:: ResponseData = response_body. data . expect ( "missing response data" ) ;
442+
443+ let registry = Registry :: new ( ) ;
444+ let zone_requests_status_host_opts = Opts :: new ( "cloudflare_zone_requests_status_host" , "Count of requests per edge HTTP status per host" ) ;
445+ let zone_requests_status_host = CounterVec :: new ( zone_requests_status_host_opts, & [ "zone" , "status" , "host" ] ) . unwrap ( ) ;
446+ registry. register ( Box :: new ( zone_requests_status_host. clone ( ) ) ) . unwrap ( ) ;
447+
448+ let last_datetime: Option < Time > = None ;
449+ for zone in response_data. viewer . unwrap ( ) . zones . iter ( ) {
450+ let zone_tag = zone. zone_tag . clone ( ) ;
451+ for group in zone. http_requests_adaptive_groups . iter ( ) {
452+ let dimensions = group. dimensions . as_ref ( ) . unwrap ( ) ;
453+ let status = dimensions. edge_response_status . to_string ( ) ;
454+ let host = dimensions. client_request_http_host . clone ( ) ;
455+ let count = group. count ;
456+
457+ zone_requests_status_host. with_label_values ( & [ zone_tag. as_str ( ) , status. as_str ( ) , host. as_str ( ) ] ) . inc_by ( count as f64 ) ;
458+ }
459+ }
460+
461+ let timestamp_nanos: u64 = last_datetime. map ( |datetime| {
462+ let datetime: NaiveDateTime = NaiveDateTime :: parse_from_str ( & datetime, "%+" ) . unwrap ( ) ;
463+ datetime. and_utc ( ) . timestamp_nanos_opt ( ) . unwrap_or ( 0 ) as u64
464+ } ) . unwrap_or_else ( || {
465+ systemtime_to_nanos ( SystemTime :: now ( ) )
466+ } ) ;
467+
468+ Ok ( prometheus_registry_to_opentelemetry_metrics ( registry, timestamp_nanos) )
469+ }
470+
414471fn systemtime_to_nanos ( time : web_time:: SystemTime ) -> u64 {
415472 let duration = time. duration_since ( web_time:: SystemTime :: UNIX_EPOCH ) . unwrap ( ) ;
416473 duration. as_nanos ( ) as u64
0 commit comments