@@ -293,3 +293,328 @@ func WritePrometheusMatrixToCSVFile(fileName string, value model.Value) error {
293
293
294
294
return nil
295
295
}
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