Skip to content

Commit a8d83d0

Browse files
committed
Add histogram metric type
1 parent 9ed1544 commit a8d83d0

File tree

8 files changed

+145
-19
lines changed

8 files changed

+145
-19
lines changed

include/triton/core/tritonserver.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ struct TRITONSERVER_MetricFamily;
9191
/// }
9292
///
9393
#define TRITONSERVER_API_VERSION_MAJOR 1
94-
#define TRITONSERVER_API_VERSION_MINOR 33
94+
#define TRITONSERVER_API_VERSION_MINOR 34
9595

9696
/// Get the TRITONBACKEND API version supported by the Triton shared
9797
/// library. This value can be compared against the
@@ -2615,7 +2615,8 @@ TRITONSERVER_DECLSPEC struct TRITONSERVER_Error* TRITONSERVER_ServerInferAsync(
26152615
///
26162616
typedef enum TRITONSERVER_metrickind_enum {
26172617
TRITONSERVER_METRIC_KIND_COUNTER,
2618-
TRITONSERVER_METRIC_KIND_GAUGE
2618+
TRITONSERVER_METRIC_KIND_GAUGE,
2619+
TRITONSERVER_METRIC_KIND_HISTOGRAM
26192620
} TRITONSERVER_MetricKind;
26202621

26212622
/// Create a new metric family object. The caller takes ownership of the
@@ -2655,11 +2656,14 @@ TRITONSERVER_MetricFamilyDelete(struct TRITONSERVER_MetricFamily* family);
26552656
/// \param family The metric family to add this new metric to.
26562657
/// \param labels The array of labels to associate with this new metric.
26572658
/// \param label_count The number of labels.
2659+
/// \param buckets Monotonically increasing values representing the
2660+
/// bucket boundaries. For histogram only.
26582661
/// \return a TRITONSERVER_Error indicating success or failure.
26592662
TRITONSERVER_DECLSPEC struct TRITONSERVER_Error* TRITONSERVER_MetricNew(
26602663
struct TRITONSERVER_Metric** metric,
26612664
struct TRITONSERVER_MetricFamily* family,
2662-
const struct TRITONSERVER_Parameter** labels, const uint64_t label_count);
2665+
const struct TRITONSERVER_Parameter** labels, const uint64_t label_count,
2666+
const void* buckets = nullptr);
26632667

26642668
/// Delete a metric object.
26652669
/// All TRITONSERVER_Metric* objects should be deleted BEFORE their
@@ -2672,9 +2676,10 @@ TRITONSERVER_DECLSPEC struct TRITONSERVER_Error* TRITONSERVER_MetricDelete(
26722676
struct TRITONSERVER_Metric* metric);
26732677

26742678
/// Get the current value of a metric object.
2675-
/// Supports metrics of kind TRITONSERVER_METRIC_KIND_COUNTER
2676-
/// and TRITONSERVER_METRIC_KIND_GAUGE, and returns
2677-
/// TRITONSERVER_ERROR_UNSUPPORTED for unsupported TRITONSERVER_MetricKind.
2679+
/// Supports metrics of kind TRITONSERVER_METRIC_KIND_COUNTER,
2680+
/// TRITONSERVER_METRIC_KIND_GAUGE, TRITONSERVER_METRIC_KIND_HISTOGRAM, and
2681+
/// returns TRITONSERVER_ERROR_UNSUPPORTED for unsupported
2682+
/// TRITONSERVER_MetricKind.
26782683
///
26792684
/// \param metric The metric object to query.
26802685
/// \param value Returns the current value of the metric object.
@@ -2705,6 +2710,16 @@ TRITONSERVER_DECLSPEC struct TRITONSERVER_Error* TRITONSERVER_MetricIncrement(
27052710
TRITONSERVER_DECLSPEC struct TRITONSERVER_Error* TRITONSERVER_MetricSet(
27062711
struct TRITONSERVER_Metric* metric, double value);
27072712

2713+
/// Observe the current value of metric to value.
2714+
/// Supports metrics of kind TRITONSERVER_METRIC_KIND_HISTOGRAM and returns
2715+
/// TRITONSERVER_ERROR_UNSUPPORTED for unsupported TRITONSERVER_MetricKind.
2716+
///
2717+
/// \param metric The metric object to update.
2718+
/// \param value The amount to observe metric's value to.
2719+
/// \return a TRITONSERVER_Error indicating success or failure.
2720+
TRITONSERVER_DECLSPEC struct TRITONSERVER_Error* TRITONSERVER_MetricObserve(
2721+
struct TRITONSERVER_Metric* metric, double value);
2722+
27082723
/// Get the TRITONSERVER_MetricKind of metric and its corresponding family.
27092724
///
27102725
/// \param metric The metric object to query.

python/tritonserver/_c/triton_bindings.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ class TRITONSERVER_Metric:
357357
) -> None: ...
358358
def increment(self, arg0: float) -> None: ...
359359
def set_value(self, arg0: float) -> None: ...
360+
def observe(self, arg0: float) -> None: ...
360361
@property
361362
def kind(self) -> TRITONSERVER_MetricKind: ...
362363
@property
@@ -384,6 +385,7 @@ class TRITONSERVER_MetricKind:
384385
__members__: ClassVar[dict] = ... # read-only
385386
COUNTER: ClassVar[TRITONSERVER_MetricKind] = ...
386387
GAUGE: ClassVar[TRITONSERVER_MetricKind] = ...
388+
HISTOGRAM: ClassVar[TRITONSERVER_MetricKind] = ...
387389
__entries: ClassVar[dict] = ...
388390
def __init__(self, value: int) -> None: ...
389391
def __eq__(self, other: object) -> bool: ...

python/tritonserver/_c/tritonserver_pybind.cc

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,14 +1672,16 @@ class PyMetric : public PyWrapper<struct TRITONSERVER_Metric> {
16721672
DESTRUCTOR_WITH_LOG(PyMetric, TRITONSERVER_MetricDelete);
16731673
PyMetric(
16741674
PyMetricFamily& family,
1675-
const std::vector<std::shared_ptr<PyParameter>>& labels)
1675+
const std::vector<std::shared_ptr<PyParameter>>& labels,
1676+
const std::vector<double>* buckets)
16761677
{
16771678
std::vector<const struct TRITONSERVER_Parameter*> params;
16781679
for (const auto& label : labels) {
16791680
params.emplace_back(label->Ptr());
16801681
}
16811682
ThrowIfError(TRITONSERVER_MetricNew(
1682-
&triton_object_, family.Ptr(), params.data(), params.size()));
1683+
&triton_object_, family.Ptr(), params.data(), params.size(),
1684+
reinterpret_cast<const void*>(buckets)));
16831685
owned_ = true;
16841686
}
16851687

@@ -1700,6 +1702,11 @@ class PyMetric : public PyWrapper<struct TRITONSERVER_Metric> {
17001702
ThrowIfError(TRITONSERVER_MetricSet(triton_object_, val));
17011703
}
17021704

1705+
void Observe(double val) const
1706+
{
1707+
ThrowIfError(TRITONSERVER_MetricObserve(triton_object_, val));
1708+
}
1709+
17031710
TRITONSERVER_MetricKind Kind() const
17041711
{
17051712
TRITONSERVER_MetricKind val = TRITONSERVER_METRIC_KIND_COUNTER;
@@ -2140,7 +2147,8 @@ PYBIND11_MODULE(triton_bindings, m)
21402147
// TRITONSERVER_MetricKind
21412148
py::enum_<TRITONSERVER_MetricKind>(m, "TRITONSERVER_MetricKind")
21422149
.value("COUNTER", TRITONSERVER_METRIC_KIND_COUNTER)
2143-
.value("GAUGE", TRITONSERVER_METRIC_KIND_GAUGE);
2150+
.value("GAUGE", TRITONSERVER_METRIC_KIND_GAUGE)
2151+
.value("HISTOGRAM", TRITONSERVER_METRIC_KIND_HISTOGRAM);
21442152
// TRITONSERVER_MetricFamily
21452153
py::class_<PyMetricFamily>(m, "TRITONSERVER_MetricFamily")
21462154
.def(py::init<
@@ -2149,12 +2157,13 @@ PYBIND11_MODULE(triton_bindings, m)
21492157
py::class_<PyMetric>(m, "TRITONSERVER_Metric")
21502158
.def(
21512159
py::init<
2152-
PyMetricFamily&,
2153-
const std::vector<std::shared_ptr<PyParameter>>&>(),
2160+
PyMetricFamily&, const std::vector<std::shared_ptr<PyParameter>>&,
2161+
const std::vector<double>*>(),
21542162
py::keep_alive<1, 2>())
21552163
.def_property_readonly("value", &PyMetric::Value)
21562164
.def("increment", &PyMetric::Increment)
21572165
.def("set_value", &PyMetric::SetValue)
2166+
.def("observe", &PyMetric::Observe)
21582167
.def_property_readonly("kind", &PyMetric::Kind);
21592168
}
21602169

src/metric_family.cc

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ MetricFamily::MetricFamily(
5454
.Help(description)
5555
.Register(*registry));
5656
break;
57+
case TRITONSERVER_METRIC_KIND_HISTOGRAM:
58+
family_ = reinterpret_cast<void*>(&prometheus::BuildHistogram()
59+
.Name(name)
60+
.Help(description)
61+
.Register(*registry));
62+
break;
5763
default:
5864
throw std::invalid_argument(
5965
"Unsupported kind passed to MetricFamily constructor.");
@@ -63,7 +69,9 @@ MetricFamily::MetricFamily(
6369
}
6470

6571
void*
66-
MetricFamily::Add(std::map<std::string, std::string> label_map, Metric* metric)
72+
MetricFamily::Add(
73+
std::map<std::string, std::string> label_map, Metric* metric,
74+
const std::vector<double>* buckets)
6775
{
6876
void* prom_metric = nullptr;
6977
switch (kind_) {
@@ -81,6 +89,17 @@ MetricFamily::Add(std::map<std::string, std::string> label_map, Metric* metric)
8189
prom_metric = reinterpret_cast<void*>(gauge_ptr);
8290
break;
8391
}
92+
case TRITONSERVER_METRIC_KIND_HISTOGRAM: {
93+
if (buckets == nullptr) {
94+
throw std::invalid_argument(
95+
"Histogram must be constructed with bucket boundaries.");
96+
}
97+
auto histogram_family_ptr =
98+
reinterpret_cast<prometheus::Family<prometheus::Histogram>*>(family_);
99+
auto histogram_ptr = &histogram_family_ptr->Add(label_map, *buckets);
100+
prom_metric = reinterpret_cast<void*>(histogram_ptr);
101+
break;
102+
}
84103
default:
85104
throw std::invalid_argument(
86105
"Unsupported family kind passed to Metric constructor.");
@@ -134,6 +153,14 @@ MetricFamily::Remove(void* prom_metric, Metric* metric)
134153
gauge_family_ptr->Remove(gauge_ptr);
135154
break;
136155
}
156+
case TRITONSERVER_METRIC_KIND_HISTOGRAM: {
157+
auto histogram_family_ptr =
158+
reinterpret_cast<prometheus::Family<prometheus::Histogram>*>(family_);
159+
auto histogram_ptr =
160+
reinterpret_cast<prometheus::Histogram*>(prom_metric);
161+
histogram_family_ptr->Remove(histogram_ptr);
162+
break;
163+
}
137164
default:
138165
// Invalid kind should be caught in constructor
139166
LOG_ERROR << "Unsupported kind in Metric destructor.";
@@ -169,7 +196,8 @@ MetricFamily::~MetricFamily()
169196
//
170197
Metric::Metric(
171198
TRITONSERVER_MetricFamily* family,
172-
std::vector<const InferenceParameter*> labels)
199+
std::vector<const InferenceParameter*> labels,
200+
const std::vector<double>* buckets)
173201
{
174202
family_ = reinterpret_cast<MetricFamily*>(family);
175203
kind_ = family_->Kind();
@@ -188,7 +216,7 @@ Metric::Metric(
188216
std::string(reinterpret_cast<const char*>(param->ValuePointer()));
189217
}
190218

191-
metric_ = family_->Add(label_map, this);
219+
metric_ = family_->Add(label_map, this, buckets);
192220
}
193221

194222
Metric::~Metric()
@@ -235,6 +263,11 @@ Metric::Value(double* value)
235263
*value = gauge_ptr->Value();
236264
break;
237265
}
266+
case TRITONSERVER_METRIC_KIND_HISTOGRAM: {
267+
return TRITONSERVER_ErrorNew(
268+
TRITONSERVER_ERROR_UNSUPPORTED,
269+
"TRITONSERVER_METRIC_KIND_HISTOGRAM does not support Value");
270+
}
238271
default:
239272
return TRITONSERVER_ErrorNew(
240273
TRITONSERVER_ERROR_UNSUPPORTED,
@@ -279,6 +312,11 @@ Metric::Increment(double value)
279312
}
280313
break;
281314
}
315+
case TRITONSERVER_METRIC_KIND_HISTOGRAM: {
316+
return TRITONSERVER_ErrorNew(
317+
TRITONSERVER_ERROR_UNSUPPORTED,
318+
"TRITONSERVER_METRIC_KIND_HISTOGRAM does not support Increment");
319+
}
282320
default:
283321
return TRITONSERVER_ErrorNew(
284322
TRITONSERVER_ERROR_UNSUPPORTED,
@@ -308,6 +346,45 @@ Metric::Set(double value)
308346
gauge_ptr->Set(value);
309347
break;
310348
}
349+
case TRITONSERVER_METRIC_KIND_HISTOGRAM: {
350+
return TRITONSERVER_ErrorNew(
351+
TRITONSERVER_ERROR_UNSUPPORTED,
352+
"TRITONSERVER_METRIC_KIND_HISTOGRAM does not support Set");
353+
}
354+
default:
355+
return TRITONSERVER_ErrorNew(
356+
TRITONSERVER_ERROR_UNSUPPORTED,
357+
"Unsupported TRITONSERVER_MetricKind");
358+
}
359+
360+
return nullptr; // Success
361+
}
362+
363+
TRITONSERVER_Error*
364+
Metric::Observe(double value)
365+
{
366+
if (metric_ == nullptr) {
367+
return TRITONSERVER_ErrorNew(
368+
TRITONSERVER_ERROR_INTERNAL,
369+
"Could not set metric value. Metric has been invalidated.");
370+
}
371+
372+
switch (kind_) {
373+
case TRITONSERVER_METRIC_KIND_COUNTER: {
374+
return TRITONSERVER_ErrorNew(
375+
TRITONSERVER_ERROR_UNSUPPORTED,
376+
"TRITONSERVER_METRIC_KIND_COUNTER does not support Observe");
377+
}
378+
case TRITONSERVER_METRIC_KIND_GAUGE: {
379+
return TRITONSERVER_ErrorNew(
380+
TRITONSERVER_ERROR_UNSUPPORTED,
381+
"TRITONSERVER_METRIC_KIND_GAUGE does not support Observe");
382+
}
383+
case TRITONSERVER_METRIC_KIND_HISTOGRAM: {
384+
auto histogram_ptr = reinterpret_cast<prometheus::Histogram*>(metric_);
385+
histogram_ptr->Observe(value);
386+
break;
387+
}
311388
default:
312389
return TRITONSERVER_ErrorNew(
313390
TRITONSERVER_ERROR_UNSUPPORTED,

src/metric_family.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ class MetricFamily {
5050
void* Family() const { return family_; }
5151
TRITONSERVER_MetricKind Kind() const { return kind_; }
5252

53-
void* Add(std::map<std::string, std::string> label_map, Metric* metric);
53+
void* Add(
54+
std::map<std::string, std::string> label_map, Metric* metric,
55+
const std::vector<double>* buckets = nullptr);
5456
void Remove(void* prom_metric, Metric* metric);
5557

5658
int NumMetrics()
@@ -86,7 +88,8 @@ class Metric {
8688
public:
8789
Metric(
8890
TRITONSERVER_MetricFamily* family,
89-
std::vector<const InferenceParameter*> labels);
91+
std::vector<const InferenceParameter*> labels,
92+
const std::vector<double>* buckets = nullptr);
9093
~Metric();
9194

9295
MetricFamily* Family() const { return family_; }
@@ -95,6 +98,7 @@ class Metric {
9598
TRITONSERVER_Error* Value(double* value);
9699
TRITONSERVER_Error* Increment(double value);
97100
TRITONSERVER_Error* Set(double value);
101+
TRITONSERVER_Error* Observe(double value);
98102

99103
// If a MetricFamily is deleted before its dependent Metric, we want to
100104
// invalidate the references so we don't access invalid memory.

src/metrics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
#include "prometheus/counter.h"
3737
#include "prometheus/gauge.h"
38+
#include "prometheus/histogram.h"
3839
#include "prometheus/registry.h"
3940
#include "prometheus/serializer.h"
4041
#include "prometheus/summary.h"

src/tritonserver.cc

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3371,7 +3371,8 @@ TRITONSERVER_MetricFamilyDelete(TRITONSERVER_MetricFamily* family)
33713371
TRITONSERVER_Error*
33723372
TRITONSERVER_MetricNew(
33733373
TRITONSERVER_Metric** metric, TRITONSERVER_MetricFamily* family,
3374-
const TRITONSERVER_Parameter** labels, const uint64_t label_count)
3374+
const TRITONSERVER_Parameter** labels, const uint64_t label_count,
3375+
const void* buckets)
33753376
{
33763377
#ifdef TRITON_ENABLE_METRICS
33773378
std::vector<const tc::InferenceParameter*> labels_vec;
@@ -3381,8 +3382,9 @@ TRITONSERVER_MetricNew(
33813382
}
33823383

33833384
try {
3384-
*metric = reinterpret_cast<TRITONSERVER_Metric*>(
3385-
new tc::Metric(family, labels_vec));
3385+
*metric = reinterpret_cast<TRITONSERVER_Metric*>(new tc::Metric(
3386+
family, labels_vec,
3387+
reinterpret_cast<const std::vector<double>*>(buckets)));
33863388
}
33873389
catch (std::invalid_argument const& ex) {
33883390
// Catch invalid kinds passed to constructor
@@ -3450,6 +3452,17 @@ TRITONSERVER_MetricSet(TRITONSERVER_Metric* metric, double value)
34503452
#endif // TRITON_ENABLE_METRICS
34513453
}
34523454

3455+
TRITONSERVER_Error*
3456+
TRITONSERVER_MetricObserve(TRITONSERVER_Metric* metric, double value)
3457+
{
3458+
#ifdef TRITON_ENABLE_METRICS
3459+
return reinterpret_cast<tc::Metric*>(metric)->Observe(value);
3460+
#else
3461+
return TRITONSERVER_ErrorNew(
3462+
TRITONSERVER_ERROR_UNSUPPORTED, "metrics not supported");
3463+
#endif // TRITON_ENABLE_METRICS
3464+
}
3465+
34533466
TRITONSERVER_Error*
34543467
TRITONSERVER_GetMetricKind(
34553468
TRITONSERVER_Metric* metric, TRITONSERVER_MetricKind* kind)

src/tritonserver_stub.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,11 @@ TRITONSERVER_MetricSet()
11001100
{
11011101
}
11021102

1103+
TRITONAPI_DECLSPEC void
1104+
TRITONSERVER_MetricObserve()
1105+
{
1106+
}
1107+
11031108
TRITONAPI_DECLSPEC void
11041109
TRITONSERVER_GetMetricKind()
11051110
{

0 commit comments

Comments
 (0)