Files
ray/python/ray/includes/metric.pxi
T
SangBin Cho 109481afd9 [Metric] custom metrics refinement (#10861)
* In progress

* In Progress.

* Addressed code review.

* Add unit tests.

* Add a simple doc.

* Fixed test failure.

* Fix all test failures from serve.

* Addressed code review.
2020-09-25 09:10:28 -07:00

224 lines
6.1 KiB
Cython

from ray.includes.metric cimport (
CCount,
CGauge,
CHistogram,
CTagKey,
CSum,
CMetric,
)
from libcpp.memory cimport unique_ptr
from libcpp.string cimport string as c_string
from libcpp.unordered_map cimport unordered_map
from libcpp.vector cimport vector as c_vector
cdef class TagKey:
"""Cython wrapper class of C++ `opencensus::stats::TagKey`."""
cdef c_string name
def __init__(self, name):
self.name = name.encode("ascii")
CTagKey.Register(self.name)
def name(self):
return self.name
cdef class Metric:
"""Cython wrapper class of C++ `ray::stats::Metric`.
It's an abstract class of all metric types.
"""
cdef:
unique_ptr[CMetric] metric
c_vector[CTagKey] c_tag_keys
def __init__(self, tag_keys):
for tag_key in tag_keys:
self.c_tag_keys.push_back(
CTagKey.Register(tag_key.encode("ascii")))
def record(self, value, tags=None):
"""Record a measurement of metric.
Flush a metric raw point to stats module with a key-value dict tags.
Args:
value (double): metric name.
tags (dict): default none.
"""
cdef unordered_map[c_string, c_string] c_tags
cdef double c_value
# Default tags will be exported if it's empty map.
if tags:
for tag_k, tag_v in tags.items():
if tag_v is not None:
c_tags[tag_k.encode("ascii")] = tag_v.encode("ascii")
c_value = value
with nogil:
self.metric.get().Record(c_value, c_tags)
def get_name(self):
return self.metric.get().GetName()
cdef class Gauge(Metric):
"""Cython wrapper class of C++ `ray::stats::Gauge`.
Gauge: Keeps the last recorded value, drops everything before.
Example:
>>> gauge = Gauge(
"ray.worker.metric",
"description",
"unit",
["tagk1", "tagk2"]).
value = 5
key1= "key1"
key2 = "key2"
gauge.record(value, {"tagk1": key1, "tagk2": key2})
"""
def __init__(self, name, description, unit, tag_keys):
"""Create a gauge metric
Args:
name (string): metric name.
description (string): description of this metric.
unit (string): measure unit of this metric.
tag_keys (list): a list of tay keys in string format.
"""
super().__init__(tag_keys)
self.metric.reset(
new CGauge(
name.encode("ascii"),
description.encode("ascii"),
unit.encode("ascii"),
self.c_tag_keys
)
)
cdef class Count(Metric):
"""Cython wrapper class of C++ `ray::stats::Count`.
Example:
>>> count = Count(
"ray.worker.metric",
"description",
"unit",
["tagk1", "tagk2"]).
value = 5
key1= "key1"
key2 = "key2"
count.record(value, {"tagk1": key1, "tagk2": key2})
Count: The count of the number of metric points.
"""
def __init__(self, name, description, unit, tag_keys):
"""Create a count metric
Args:
name (string): metric name.
description (string): description of this metric.
unit (string): measure unit of this metric.
tag_keys (list): a list of tay keys in string format.
"""
super().__init__(tag_keys)
self.metric.reset(
new CCount(
name.encode("ascii"),
description.encode("ascii"),
unit.encode("ascii"),
self.c_tag_keys
)
)
cdef class Sum(Metric):
"""Cython wrapper class of C++ `ray::stats::Sum`.
Example:
>>> metric_sum = Sum(
"ray.worker.metric",
"description",
"unit",
["tagk1", "tagk2"]).
value = 5
key1= "key1"
key2 = "key2"
metric_sum.record(value, {"tagk1": key1, "tagk2": key2})
Sum: A sum up of the metric points.
"""
def __init__(self, name, description, unit, tag_keys):
"""Create a sum metric
Args:
name (string): metric name.
description (string): description of this metric.
unit (string): measure unit of this metric.
tag_keys (list): a list of tay keys in string format.
"""
super().__init__(tag_keys)
self.metric.reset(
new CSum(
name.encode("ascii"),
description.encode("ascii"),
unit.encode("ascii"),
self.c_tag_keys
)
)
cdef class Histogram(Metric):
"""Cython wrapper class of C++ `ray::stats::Histogram`.
Example:
>>> histogram = Histogram(
"ray.worker.histogram1",
"desciprtion",
"unit",
[1.0, 2.0], # boundaries.
["tagk1"])
value = 5
key1= "key1"
histogram.record(value, {"tagk1": key1})
Histogram: Histogram distribution of metric points.
"""
def __init__(self, name, description, unit, boundaries, tag_keys):
"""Create a sum metric
Args:
name (string): metric name.
description (string): description of this metric.
unit (string): measure unit of this metric.
boundaries (list): a double type list boundaries of histogram.
tag_keys (list): a list of tay key in string format.
"""
super().__init__(tag_keys)
cdef c_vector[double] c_boundaries
for value in boundaries:
c_boundaries.push_back(value)
self.metric.reset(
new CHistogram(
name.encode("ascii"),
description.encode("ascii"),
unit.encode("ascii"),
c_boundaries,
self.c_tag_keys
)
)