async def test_in_memory_exporter(serve_instance): exporter = MetricExporterActor.remote(InMemoryExporter) collector = MetricClient( exporter, push_interval=2, default_labels={"default": "label"}) counter = collector.new_counter(name="my_counter", label_names=("a", )) measure = collector.new_measure( name="my_measure", description="help", label_names=("ray", "lang")) measure = measure.labels(lang="C++") counter.labels(a="1").add() measure.labels(ray="").record(0) measure.labels(ray="").record(42) await collector._push_to_exporter_once() metric_stored = await exporter.inspect_metrics.remote() assert metric_stored == [{ "info": { "name": "my_counter", "type": "MetricType.COUNTER", "default": "label", "a": "1" }, "value": 1 }, { "info": { "name": "my_measure", "type": "MetricType.MEASURE", "default": "label", "lang": "C++", "ray": "" }, "value": 42 }]
async def test_prometheus_exporter(serve_instance): exporter = MetricExporterActor.remote(PrometheusExporter) collector = MetricClient( exporter, push_interval=2, default_labels={"default": "label"}) counter = collector.new_counter(name="my_counter", label_names=("a", )) measure = collector.new_measure( name="my_measure", description="help", label_names=("ray", "lang")) measure = measure.labels(lang="C++") counter.labels(a="1").add() measure.labels(ray="").record(0) measure.labels(ray="").record(42) await collector._push_to_exporter_once() metric_stored = await exporter.inspect_metrics.remote() metric_stored = metric_stored.decode() fragments = [ "# HELP my_counter_total", "# TYPE my_counter_total counter", 'my_counter_total{a="1",default="label"} 1.0', "# TYPE my_counter_created gauge", 'my_counter_created{a="1",default="label"}', "# HELP my_measure help", "# TYPE my_measure gauge", 'my_measure{default="label",lang="C++",ray=""} 42.0' ] for fragment in fragments: assert fragment in metric_stored
def _get_or_start_metric_exporter(self, metric_exporter_class): """Get the metric exporter belonging to this serve cluster. If the metric exporter does not already exist, it will be started. """ try: self.metric_exporter = ray.util.get_actor(SERVE_METRIC_SINK_NAME) except ValueError: logger.info("Starting metric exporter with name '{}'".format( SERVE_METRIC_SINK_NAME)) self.metric_exporter = MetricExporterActor.options( detached=True, name=SERVE_METRIC_SINK_NAME).remote(metric_exporter_class)
def _get_or_start_metric_exporter(self, metric_exporter_class): """Get the metric exporter belonging to this serve instance. If the metric exporter does not already exist, it will be started. """ metric_sink_name = format_actor_name(SERVE_METRIC_SINK_NAME, self.instance_name) try: self.metric_exporter = ray.get_actor(metric_sink_name) except ValueError: logger.info("Starting metric exporter with name '{}'".format( metric_sink_name)) self.metric_exporter = MetricExporterActor.options( name=metric_sink_name).remote(metric_exporter_class)
async def test_prometheus_conflicting_labels(serve_instance): exporter = MetricExporterActor.remote(PrometheusExporter) collector_a = MetricClient(exporter, push_interval=2, default_labels={"default": "a"}) collector_b = MetricClient(exporter, push_interval=2, default_labels={"default": "b"}) for collector in [collector_a, collector_b]: counter = collector.new_counter("num") counter.add() await collector._push_to_exporter_once() metric_stored = (await exporter.inspect_metrics.remote()).decode() fragments = ['num_total{default="a"}', 'num_total{default="b"}'] for fragment in fragments: assert fragment in metric_stored