Skip to content

Commit e5718ac

Browse files
mc-nvyinggeh
andauthored
test: Add python backend tests for the new histogram metric (#7540) (#7545)
Co-authored-by: Yingge He <157551214+yinggeh@users.noreply.github.com>
1 parent 92bc457 commit e5718ac

File tree

1 file changed

+141
-3
lines changed

1 file changed

+141
-3
lines changed

qa/python_models/custom_metrics/model.py

Lines changed: 141 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# Copyright 2023-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
#
33
# Redistribution and use in source and binary forms, with or without
44
# modification, are permitted provided that the following conditions
@@ -74,6 +74,96 @@ def _metric_api_helper(self, metric, kind):
7474
self.assertEqual(metric.value(), value)
7575
logger.log_info("Set metric to : {}".format(metric.value()))
7676

77+
# Test observe value
78+
observe = 0.05
79+
# Counter and gauge do not support observe
80+
with self.assertRaises(pb_utils.TritonModelException):
81+
metric.observe(observe)
82+
83+
def _histogram_api_helper(self, metric, name, labels):
84+
def histogram_str_builder(name, type, labels, value, le=None):
85+
if type == "count" or type == "sum":
86+
return f"{name}_{type}{{{labels}}} {value}"
87+
elif type == "bucket":
88+
return f'{name}_bucket{{{labels},le="{le}"}} {value}'
89+
else:
90+
raise
91+
92+
# Adding logger to test if custom metrics and logging work together
93+
# as they use the same message queue.
94+
logger = pb_utils.Logger
95+
96+
# All values should be 0.0 before the test
97+
metrics = self._get_metrics()
98+
self.assertIn(histogram_str_builder(name, "count", labels, "0"), metrics)
99+
self.assertIn(histogram_str_builder(name, "sum", labels, "0"), metrics)
100+
self.assertIn(
101+
histogram_str_builder(name, "bucket", labels, "0", le="0.1"), metrics
102+
)
103+
self.assertIn(
104+
histogram_str_builder(name, "bucket", labels, "0", le="1"), metrics
105+
)
106+
self.assertIn(
107+
histogram_str_builder(name, "bucket", labels, "0", le="2.5"), metrics
108+
)
109+
self.assertIn(
110+
histogram_str_builder(name, "bucket", labels, "0", le="5"), metrics
111+
)
112+
self.assertIn(
113+
histogram_str_builder(name, "bucket", labels, "0", le="10"), metrics
114+
)
115+
self.assertIn(
116+
histogram_str_builder(name, "bucket", labels, "0", le="+Inf"), metrics
117+
)
118+
119+
# Histogram does not support value
120+
with self.assertRaises(pb_utils.TritonModelException):
121+
metric.value()
122+
123+
# Test increment value
124+
increment = 2023.0
125+
# Histogram does not support increment
126+
with self.assertRaises(pb_utils.TritonModelException):
127+
metric.increment(increment)
128+
129+
# Test set value
130+
value = 999.9
131+
# Histogram does not support set
132+
with self.assertRaises(pb_utils.TritonModelException):
133+
metric.set(value)
134+
135+
# Test observe value
136+
data = [0.05, 1.5, 6.0]
137+
for datum in data:
138+
metric.observe(datum)
139+
logger.log_info("Observe histogram metric with value : {}".format(datum))
140+
141+
metrics = self._get_metrics()
142+
self.assertIn(
143+
histogram_str_builder(name, "count", labels, str(len(data))), metrics
144+
)
145+
self.assertIn(
146+
histogram_str_builder(name, "sum", labels, str(sum(data))), metrics
147+
)
148+
self.assertIn(
149+
histogram_str_builder(name, "bucket", labels, "1", le="0.1"), metrics
150+
)
151+
self.assertIn(
152+
histogram_str_builder(name, "bucket", labels, "1", le="1"), metrics
153+
)
154+
self.assertIn(
155+
histogram_str_builder(name, "bucket", labels, "2", le="2.5"), metrics
156+
)
157+
self.assertIn(
158+
histogram_str_builder(name, "bucket", labels, "2", le="5"), metrics
159+
)
160+
self.assertIn(
161+
histogram_str_builder(name, "bucket", labels, "3", le="10"), metrics
162+
)
163+
self.assertIn(
164+
histogram_str_builder(name, "bucket", labels, "3", le="+Inf"), metrics
165+
)
166+
77167
def _dup_metric_helper(self, labels={}):
78168
# Adding logger to test if custom metrics and logging work together
79169
# as they use the same message queue.
@@ -128,14 +218,62 @@ def test_gauge_e2e(self):
128218
description="test metric gauge kind end to end",
129219
kind=pb_utils.MetricFamily.GAUGE,
130220
)
131-
labels = {"example1": "counter_label1", "example2": "counter_label2"}
221+
labels = {"example1": "gauge_label1", "example2": "gauge_label2"}
132222
metric = metric_family.Metric(labels=labels)
133223
self._metric_api_helper(metric, "gauge")
134224

135-
pattern = 'test_gauge_e2e{example1="counter_label1",example2="counter_label2"}'
225+
pattern = 'test_gauge_e2e{example1="gauge_label1",example2="gauge_label2"}'
136226
metrics = self._get_metrics()
137227
self.assertIn(pattern, metrics)
138228

229+
def test_histogram_e2e(self):
230+
name = "test_histogram_e2e"
231+
metric_family = pb_utils.MetricFamily(
232+
name=name,
233+
description="test metric histogram kind end to end",
234+
kind=pb_utils.MetricFamily.HISTOGRAM,
235+
)
236+
237+
labels = {"example1": "histogram_label1", "example2": "histogram_label2"}
238+
buckets = [0.1, 1.0, 2.5, 5.0, 10.0]
239+
metric = metric_family.Metric(labels=labels, buckets=buckets)
240+
241+
labels_str = 'example1="histogram_label1",example2="histogram_label2"'
242+
self._histogram_api_helper(metric, name, labels_str)
243+
244+
metrics = self._get_metrics()
245+
count_pattern = f"{name}_count{{{labels_str}}}"
246+
sum_pattern = f"{name}_sum{{{labels_str}}}"
247+
bucket_pattern = f"{name}_bucket{{{labels_str}"
248+
self.assertEqual(metrics.count(count_pattern), 1)
249+
self.assertEqual(metrics.count(sum_pattern), 1)
250+
self.assertEqual(metrics.count(bucket_pattern), len(buckets) + 1)
251+
252+
def test_histogram_args(self):
253+
name = "test_histogram_args"
254+
metric_family = pb_utils.MetricFamily(
255+
name=name,
256+
description="test metric histogram args",
257+
kind=pb_utils.MetricFamily.HISTOGRAM,
258+
)
259+
260+
# Test "None" value buckets
261+
with self.assertRaises(pb_utils.TritonModelException):
262+
metric_family.Metric(labels={})
263+
with self.assertRaises(pb_utils.TritonModelException):
264+
metric_family.Metric(labels={}, buckets=None)
265+
266+
# Test non-ascending order buckets
267+
with self.assertRaises(pb_utils.TritonModelException):
268+
metric_family.Metric(labels={}, buckets=[2.5, 0.1, 1.0, 10.0, 5.0])
269+
270+
# Test duplicate value buckets
271+
with self.assertRaises(pb_utils.TritonModelException):
272+
metric_family.Metric(labels={}, buckets=[1, 1, 2, 5, 5])
273+
274+
# Test empty list bucket
275+
metric_family.Metric(labels={}, buckets=[])
276+
139277
def test_dup_metric_family_diff_kind(self):
140278
# Test that a duplicate metric family can't be added with a conflicting type/kind
141279
metric_family1 = pb_utils.MetricFamily(

0 commit comments

Comments
 (0)