@@ -293,3 +293,328 @@ func WritePrometheusMatrixToCSVFile(fileName string, value model.Value) error {
293293
294294 return nil
295295}
296+
297+ // Bucket represents a data point of a Histogram Bucket.
298+ type Bucket struct {
299+ // Le is the interval Less than or Equal which represents the Bucket's bin. i.e. "500ms".
300+ Le string
301+ // Val is the value for how many instances fall in the Bucket.
302+ Val int
303+ }
304+
305+ // GetReloadCount gets the total number of nginx reloads.
306+ func GetReloadCount (promInstance PrometheusInstance , ngfPodName string ) (float64 , error ) {
307+ return getFirstValueOfVector (
308+ fmt .Sprintf (
309+ `nginx_gateway_fabric_nginx_reloads_total{pod="%[1]s"}` ,
310+ ngfPodName ,
311+ ),
312+ promInstance ,
313+ )
314+ }
315+
316+ // GetReloadCountWithStartTime gets the total number of nginx reloads from a start time to the current time.
317+ func GetReloadCountWithStartTime (
318+ promInstance PrometheusInstance ,
319+ ngfPodName string ,
320+ startTime time.Time ,
321+ ) (float64 , error ) {
322+ return getFirstValueOfVector (
323+ fmt .Sprintf (
324+ `nginx_gateway_fabric_nginx_reloads_total{pod="%[1]s"}` +
325+ ` - ` +
326+ `nginx_gateway_fabric_nginx_reloads_total{pod="%[1]s"} @ %d` ,
327+ ngfPodName ,
328+ startTime .Unix (),
329+ ),
330+ promInstance ,
331+ )
332+ }
333+
334+ // GetReloadErrsCountWithStartTime gets the total number of nginx reload errors from a start time to the current time.
335+ func GetReloadErrsCountWithStartTime (
336+ promInstance PrometheusInstance ,
337+ ngfPodName string ,
338+ startTime time.Time ,
339+ ) (float64 , error ) {
340+ return getFirstValueOfVector (
341+ fmt .Sprintf (
342+ `nginx_gateway_fabric_nginx_reload_errors_total{pod="%[1]s"}` +
343+ ` - ` +
344+ `nginx_gateway_fabric_nginx_reload_errors_total{pod="%[1]s"} @ %d` ,
345+ ngfPodName ,
346+ startTime .Unix (),
347+ ),
348+ promInstance ,
349+ )
350+ }
351+
352+ // GetReloadAvgTime gets the average time in milliseconds for nginx to reload.
353+ func GetReloadAvgTime (promInstance PrometheusInstance , ngfPodName string ) (float64 , error ) {
354+ return getFirstValueOfVector (
355+ fmt .Sprintf (
356+ `nginx_gateway_fabric_nginx_reloads_milliseconds_sum{pod="%[1]s"}` +
357+ ` / ` +
358+ `nginx_gateway_fabric_nginx_reloads_total{pod="%[1]s"}` ,
359+ ngfPodName ,
360+ ),
361+ promInstance ,
362+ )
363+ }
364+
365+ // GetReloadAvgTimeWithStartTime gets the average time in milliseconds for nginx to reload using a start time
366+ // to the current time to calculate.
367+ func GetReloadAvgTimeWithStartTime (
368+ promInstance PrometheusInstance ,
369+ ngfPodName string ,
370+ startTime time.Time ,
371+ ) (float64 , error ) {
372+ return getFirstValueOfVector (
373+ fmt .Sprintf (
374+ `(nginx_gateway_fabric_nginx_reloads_milliseconds_sum{pod="%[1]s"}` +
375+ ` - ` +
376+ `nginx_gateway_fabric_nginx_reloads_milliseconds_sum{pod="%[1]s"} @ %[2]d)` +
377+ ` / ` +
378+ `(nginx_gateway_fabric_nginx_reloads_total{pod="%[1]s"}` +
379+ ` - ` +
380+ `nginx_gateway_fabric_nginx_reloads_total{pod="%[1]s"} @ %[2]d)` ,
381+ ngfPodName ,
382+ startTime .Unix (),
383+ ),
384+ promInstance ,
385+ )
386+ }
387+
388+ // GetReloadBuckets gets the Buckets in millisecond intervals for nginx reloads.
389+ func GetReloadBuckets (promInstance PrometheusInstance , ngfPodName string ) ([]Bucket , error ) {
390+ return getBuckets (
391+ fmt .Sprintf (
392+ `nginx_gateway_fabric_nginx_reloads_milliseconds_bucket{pod="%[1]s"}` ,
393+ ngfPodName ,
394+ ),
395+ promInstance ,
396+ )
397+ }
398+
399+ // GetReloadBucketsWithStartTime gets the Buckets in millisecond intervals for nginx reloads from a start time
400+ // to the current time.
401+ func GetReloadBucketsWithStartTime (
402+ promInstance PrometheusInstance ,
403+ ngfPodName string ,
404+ startTime time.Time ,
405+ ) ([]Bucket , error ) {
406+ return getBuckets (
407+ fmt .Sprintf (
408+ `nginx_gateway_fabric_nginx_reloads_milliseconds_bucket{pod="%[1]s"}` +
409+ ` - ` +
410+ `nginx_gateway_fabric_nginx_reloads_milliseconds_bucket{pod="%[1]s"} @ %d` ,
411+ ngfPodName ,
412+ startTime .Unix (),
413+ ),
414+ promInstance ,
415+ )
416+ }
417+
418+ // GetEventsCount gets the NGF event batch processing count.
419+ func GetEventsCount (promInstance PrometheusInstance , ngfPodName string ) (float64 , error ) {
420+ return getFirstValueOfVector (
421+ fmt .Sprintf (
422+ `nginx_gateway_fabric_event_batch_processing_milliseconds_count{pod="%[1]s"}` ,
423+ ngfPodName ,
424+ ),
425+ promInstance ,
426+ )
427+ }
428+
429+ // GetEventsCountWithStartTime gets the NGF event batch processing count from a start time to the current time.
430+ func GetEventsCountWithStartTime (
431+ promInstance PrometheusInstance ,
432+ ngfPodName string ,
433+ startTime time.Time ,
434+ ) (float64 , error ) {
435+ return getFirstValueOfVector (
436+ fmt .Sprintf (
437+ `nginx_gateway_fabric_event_batch_processing_milliseconds_count{pod="%[1]s"}` +
438+ ` - ` +
439+ `nginx_gateway_fabric_event_batch_processing_milliseconds_count{pod="%[1]s"} @ %d` ,
440+ ngfPodName ,
441+ startTime .Unix (),
442+ ),
443+ promInstance ,
444+ )
445+ }
446+
447+ // GetEventsAvgTime gets the average time in milliseconds it takes for NGF to process a single event batch.
448+ func GetEventsAvgTime (promInstance PrometheusInstance , ngfPodName string ) (float64 , error ) {
449+ return getFirstValueOfVector (
450+ fmt .Sprintf (
451+ `nginx_gateway_fabric_event_batch_processing_milliseconds_sum{pod="%[1]s"}` +
452+ ` / ` +
453+ `nginx_gateway_fabric_event_batch_processing_milliseconds_count{pod="%[1]s"}` ,
454+ ngfPodName ,
455+ ),
456+ promInstance ,
457+ )
458+ }
459+
460+ // GetEventsAvgTimeWithStartTime gets the average time in milliseconds it takes for NGF to process a single event
461+ // batch using a start time to the current time to calculate.
462+ func GetEventsAvgTimeWithStartTime (
463+ promInstance PrometheusInstance ,
464+ ngfPodName string ,
465+ startTime time.Time ,
466+ ) (float64 , error ) {
467+ return getFirstValueOfVector (
468+ fmt .Sprintf (
469+ `(nginx_gateway_fabric_event_batch_processing_milliseconds_sum{pod="%[1]s"}` +
470+ ` - ` +
471+ `nginx_gateway_fabric_event_batch_processing_milliseconds_sum{pod="%[1]s"} @ %[2]d)` +
472+ ` / ` +
473+ `(nginx_gateway_fabric_event_batch_processing_milliseconds_count{pod="%[1]s"}` +
474+ ` - ` +
475+ `nginx_gateway_fabric_event_batch_processing_milliseconds_count{pod="%[1]s"} @ %[2]d)` ,
476+ ngfPodName ,
477+ startTime .Unix (),
478+ ),
479+ promInstance ,
480+ )
481+ }
482+
483+ // GetEventsBuckets gets the Buckets in millisecond intervals for NGF event batch processing.
484+ func GetEventsBuckets (promInstance PrometheusInstance , ngfPodName string ) ([]Bucket , error ) {
485+ return getBuckets (
486+ fmt .Sprintf (
487+ `nginx_gateway_fabric_event_batch_processing_milliseconds_bucket{pod="%[1]s"}` ,
488+ ngfPodName ,
489+ ),
490+ promInstance ,
491+ )
492+ }
493+
494+ // GetEventsBucketsWithStartTime gets the Buckets in millisecond intervals for NGF event batch processing from a start
495+ // time to the current time.
496+ func GetEventsBucketsWithStartTime (
497+ promInstance PrometheusInstance ,
498+ ngfPodName string ,
499+ startTime time.Time ,
500+ ) ([]Bucket , error ) {
501+ return getBuckets (
502+ fmt .Sprintf (
503+ `nginx_gateway_fabric_event_batch_processing_milliseconds_bucket{pod="%[1]s"}` +
504+ ` - ` +
505+ `nginx_gateway_fabric_event_batch_processing_milliseconds_bucket{pod="%[1]s"} @ %d` ,
506+ ngfPodName ,
507+ startTime .Unix (),
508+ ),
509+ promInstance ,
510+ )
511+ }
512+
513+ // CreateMetricExistChecker returns a function that will query Prometheus at a specific timestamp
514+ // and adjust that timestamp if there is no result found.
515+ func CreateMetricExistChecker (
516+ promInstance PrometheusInstance ,
517+ query string ,
518+ getTime func () time.Time ,
519+ modifyTime func (),
520+ ) func () error {
521+ return func () error {
522+ queryWithTimestamp := fmt .Sprintf ("%s @ %d" , query , getTime ().Unix ())
523+
524+ result , err := promInstance .Query (queryWithTimestamp )
525+ if err != nil {
526+ return fmt .Errorf ("failed to query Prometheus: %w" , err )
527+ }
528+
529+ if result .String () == "" {
530+ modifyTime ()
531+ return errors .New ("empty result" )
532+ }
533+
534+ return nil
535+ }
536+ }
537+
538+ // CreateEndTimeFinder returns a function that will range query Prometheus given a specific startTime and endTime
539+ // and adjust the endTime if there is no result found.
540+ func CreateEndTimeFinder (
541+ promInstance PrometheusInstance ,
542+ query string ,
543+ startTime time.Time ,
544+ endTime * time.Time ,
545+ queryRangeStep time.Duration ,
546+ ) func () error {
547+ return func () error {
548+ result , err := promInstance .QueryRange (query , v1.Range {
549+ Start : startTime ,
550+ End : * endTime ,
551+ Step : queryRangeStep ,
552+ })
553+ if err != nil {
554+ return fmt .Errorf ("failed to query Prometheus: %w" , err )
555+ }
556+
557+ if result .String () == "" {
558+ * endTime = time .Now ()
559+ return errors .New ("empty result" )
560+ }
561+
562+ return nil
563+ }
564+ }
565+
566+ // CreateResponseChecker returns a function that checks if there is a successful response from a url.
567+ func CreateResponseChecker (url , address string , requestTimeout time.Duration ) func () error {
568+ return func () error {
569+ status , _ , err := Get (url , address , requestTimeout )
570+ if err != nil {
571+ return fmt .Errorf ("bad response: %w" , err )
572+ }
573+
574+ if status != 200 {
575+ return fmt .Errorf ("unexpected status code: %d" , status )
576+ }
577+
578+ return nil
579+ }
580+ }
581+
582+ func getFirstValueOfVector (query string , promInstance PrometheusInstance ) (float64 , error ) {
583+ result , err := promInstance .Query (query )
584+ if err != nil {
585+ return 0 , err
586+ }
587+
588+ val , err := GetFirstValueOfPrometheusVector (result )
589+ if err != nil {
590+ return 0 , err
591+ }
592+
593+ return val , nil
594+ }
595+
596+ func getBuckets (query string , promInstance PrometheusInstance ) ([]Bucket , error ) {
597+ result , err := promInstance .Query (query )
598+ if err != nil {
599+ return nil , err
600+ }
601+
602+ res , ok := result .(model.Vector )
603+ if ! ok {
604+ return nil , errors .New ("could not convert result to vector" )
605+ }
606+
607+ buckets := make ([]Bucket , 0 , len (res ))
608+
609+ for _ , sample := range res {
610+ le := sample .Metric ["le" ]
611+ val := float64 (sample .Value )
612+ bucket := Bucket {
613+ Le : string (le ),
614+ Val : int (val ),
615+ }
616+ buckets = append (buckets , bucket )
617+ }
618+
619+ return buckets , nil
620+ }
0 commit comments