@@ -232,6 +232,32 @@ MetricAPIHelper(TRITONSERVER_Metric* metric, TRITONSERVER_MetricKind kind)
232232 TRITONSERVER_ErrorDelete (err);
233233}
234234
235+ void
236+ HistogramAPIHelper (TRITONSERVER_Metric* metric)
237+ {
238+ // Observe
239+ std::vector<double > data{0.05 , 1.5 , 6.0 };
240+ std::vector<std::uint64_t > cumulative_counts = {1 , 1 , 2 , 2 , 3 , 3 };
241+ double sum = 0.0 ;
242+ for (auto datum : data) {
243+ FAIL_TEST_IF_ERR (
244+ TRITONSERVER_MetricObserve (metric, datum), " observe metric value" );
245+ sum += datum;
246+ }
247+
248+ // Collect
249+ prometheus::ClientMetric value;
250+ FAIL_TEST_IF_ERR (
251+ TRITONSERVER_MetricCollect (metric, &value),
252+ " query metric value after observe" );
253+ auto hist = value.histogram ;
254+ ASSERT_EQ (hist.sample_count , data.size ());
255+ ASSERT_EQ (hist.sample_sum , sum);
256+ ASSERT_EQ (hist.bucket .size (), cumulative_counts.size ());
257+ for (uint64_t i = 0 ; i < hist.bucket .size (); ++i) {
258+ ASSERT_EQ (hist.bucket [i].cumulative_count , cumulative_counts[i]);
259+ }
260+ }
235261
236262// Test Fixture
237263class MetricsApiTest : public ::testing::Test {
@@ -364,6 +390,52 @@ TEST_F(MetricsApiTest, TestGaugeEndToEnd)
364390 ASSERT_EQ (NumMetricMatches (server_, description), 0 );
365391}
366392
393+ // Test end-to-end flow of Generic Metrics API for Histogram metric
394+ TEST_F (MetricsApiTest, TestHistogramEndToEnd)
395+ {
396+ // Create metric family
397+ TRITONSERVER_MetricFamily* family;
398+ TRITONSERVER_MetricKind kind = TRITONSERVER_METRIC_KIND_HISTOGRAM;
399+ const char * name = " custom_histogram_example" ;
400+ const char * description =
401+ " this is an example histogram metric added via API." ;
402+ FAIL_TEST_IF_ERR (
403+ TRITONSERVER_MetricFamilyNew (&family, kind, name, description),
404+ " Creating new metric family" );
405+
406+ // Create metric
407+ TRITONSERVER_Metric* metric;
408+ std::vector<const TRITONSERVER_Parameter*> labels;
409+ labels.emplace_back (TRITONSERVER_ParameterNew (
410+ " example1" , TRITONSERVER_PARAMETER_STRING, " histogram_label1" ));
411+ labels.emplace_back (TRITONSERVER_ParameterNew (
412+ " example2" , TRITONSERVER_PARAMETER_STRING, " histogram_label2" ));
413+ std::vector<double > buckets = {0.1 , 1.0 , 2.5 , 5.0 , 10.0 };
414+ FAIL_TEST_IF_ERR (
415+ TRITONSERVER_MetricNew (
416+ &metric, family, labels.data (), labels.size (),
417+ reinterpret_cast <void *>(&buckets)),
418+ " Creating new metric" );
419+ for (const auto label : labels) {
420+ TRITONSERVER_ParameterDelete (const_cast <TRITONSERVER_Parameter*>(label));
421+ }
422+
423+ // Run through metric APIs and assert correctness
424+ HistogramAPIHelper (metric);
425+
426+ // Assert custom metric is reported and found in output
427+ ASSERT_EQ (NumMetricMatches (server_, description), 1 );
428+
429+ // Cleanup
430+ FAIL_TEST_IF_ERR (TRITONSERVER_MetricDelete (metric), " delete metric" );
431+ FAIL_TEST_IF_ERR (
432+ TRITONSERVER_MetricFamilyDelete (family), " delete metric family" );
433+
434+ // Assert custom metric/family is unregistered and no longer in output
435+ ASSERT_EQ (NumMetricMatches (server_, description), 0 );
436+ }
437+
438+
367439// Test that a duplicate metric family can't be added
368440// with a conflicting type/kind
369441TEST_F (MetricsApiTest, TestDupeMetricFamilyDiffKind)
0 commit comments