From 80aaebb7610ccaafdd65a44bf0aad897baaff304 Mon Sep 17 00:00:00 2001 From: Anton Tolchanov <1687799+knyar@users.noreply.github.com> Date: Mon, 26 Jul 2021 19:52:30 +0100 Subject: [PATCH] Rename Prometheus metrics to conform with naming guidelines (#50156) --- .../components/prometheus/__init__.py | 22 ++++++---- tests/components/prometheus/test_init.py | 44 +++++++++++++++---- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/prometheus/__init__.py b/homeassistant/components/prometheus/__init__.py index c74caa745f3..f158d2506d1 100644 --- a/homeassistant/components/prometheus/__init__.py +++ b/homeassistant/components/prometheus/__init__.py @@ -54,12 +54,14 @@ COMPONENT_CONFIG_SCHEMA_ENTRY = vol.Schema( {vol.Optional(CONF_OVERRIDE_METRIC): cv.string} ) +DEFAULT_NAMESPACE = "homeassistant" + CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.All( { vol.Optional(CONF_FILTER, default={}): entityfilter.FILTER_SCHEMA, - vol.Optional(CONF_PROM_NAMESPACE): cv.string, + vol.Optional(CONF_PROM_NAMESPACE, default=DEFAULT_NAMESPACE): cv.string, vol.Optional(CONF_DEFAULT_METRIC): cv.string, vol.Optional(CONF_OVERRIDE_METRIC): cv.string, vol.Optional(CONF_COMPONENT_CONFIG, default={}): vol.Schema( @@ -291,7 +293,9 @@ class PrometheusMetrics: def _handle_light(self, state): metric = self._metric( - "light_state", self.prometheus_cli.Gauge, "Load level of a light (0..1)" + "light_brightness_percent", + self.prometheus_cli.Gauge, + "Light brightness percentage (0..100)", ) try: @@ -317,9 +321,9 @@ class PrometheusMetrics: if self._climate_units == TEMP_FAHRENHEIT: temp = fahrenheit_to_celsius(temp) metric = self._metric( - "temperature_c", + "climate_target_temperature_celsius", self.prometheus_cli.Gauge, - "Temperature in degrees Celsius", + "Target temperature in degrees Celsius", ) metric.labels(**self._labels(state)).set(temp) @@ -328,9 +332,9 @@ class PrometheusMetrics: if self._climate_units == TEMP_FAHRENHEIT: current_temp = fahrenheit_to_celsius(current_temp) metric = self._metric( - "current_temperature_c", + "climate_current_temperature_celsius", self.prometheus_cli.Gauge, - "Current Temperature in degrees Celsius", + "Current temperature in degrees Celsius", ) metric.labels(**self._labels(state)).set(current_temp) @@ -414,7 +418,7 @@ class PrometheusMetrics: """Get metric based on device class attribute.""" metric = state.attributes.get(ATTR_DEVICE_CLASS) if metric is not None: - return f"{metric}_{unit}" + return f"sensor_{metric}_{unit}" return None def _sensor_override_metric(self, state, unit): @@ -442,8 +446,8 @@ class PrometheusMetrics: return units = { - TEMP_CELSIUS: "c", - TEMP_FAHRENHEIT: "c", # F should go into C metric + TEMP_CELSIUS: "celsius", + TEMP_FAHRENHEIT: "celsius", # F should go into C metric PERCENTAGE: "percent", } default = unit.replace("/", "_per_") diff --git a/tests/components/prometheus/test_init.py b/tests/components/prometheus/test_init.py index b1abe1de3e5..f8fcdd4561a 100644 --- a/tests/components/prometheus/test_init.py +++ b/tests/components/prometheus/test_init.py @@ -31,9 +31,12 @@ class FilterTest: should_pass: bool -async def prometheus_client(hass, hass_client): +async def prometheus_client(hass, hass_client, namespace): """Initialize an hass_client with Prometheus component.""" - await async_setup_component(hass, prometheus.DOMAIN, {prometheus.DOMAIN: {}}) + config = {} + if namespace is not None: + config[prometheus.CONF_PROM_NAMESPACE] = namespace + await async_setup_component(hass, prometheus.DOMAIN, {prometheus.DOMAIN: config}) await async_setup_component(hass, sensor.DOMAIN, {"sensor": [{"platform": "demo"}]}) @@ -98,9 +101,9 @@ async def prometheus_client(hass, hass_client): return await hass_client() -async def test_view(hass, hass_client): +async def test_view_empty_namespace(hass, hass_client): """Test prometheus metrics view.""" - client = await prometheus_client(hass, hass_client) + client = await prometheus_client(hass, hass_client, "") resp = await client.get(prometheus.API_ENDPOINT) assert resp.status == 200 @@ -117,7 +120,7 @@ async def test_view(hass, hass_client): ) assert ( - 'temperature_c{domain="sensor",' + 'sensor_temperature_celsius{domain="sensor",' 'entity="sensor.outside_temperature",' 'friendly_name="Outside Temperature"} 15.6' in body ) @@ -129,7 +132,7 @@ async def test_view(hass, hass_client): ) assert ( - 'current_temperature_c{domain="climate",' + 'climate_current_temperature_celsius{domain="climate",' 'entity="climate.heatpump",' 'friendly_name="HeatPump"} 25.0' in body ) @@ -160,7 +163,7 @@ async def test_view(hass, hass_client): ) assert ( - 'humidity_percent{domain="sensor",' + 'sensor_humidity_percent{domain="sensor",' 'entity="sensor.outside_humidity",' 'friendly_name="Outside Humidity"} 54.0' in body ) @@ -172,7 +175,7 @@ async def test_view(hass, hass_client): ) assert ( - 'power_kwh{domain="sensor",' + 'sensor_power_kwh{domain="sensor",' 'entity="sensor.radio_energy",' 'friendly_name="Radio Energy"} 14.0' in body ) @@ -208,6 +211,31 @@ async def test_view(hass, hass_client): ) +async def test_view_default_namespace(hass, hass_client): + """Test prometheus metrics view.""" + client = await prometheus_client(hass, hass_client, None) + resp = await client.get(prometheus.API_ENDPOINT) + + assert resp.status == 200 + assert resp.headers["content-type"] == CONTENT_TYPE_TEXT_PLAIN + body = await resp.text() + body = body.split("\n") + + assert len(body) > 3 + + assert "# HELP python_info Python platform information" in body + assert ( + "# HELP python_gc_objects_collected_total " + "Objects collected during gc" in body + ) + + assert ( + 'homeassistant_sensor_temperature_celsius{domain="sensor",' + 'entity="sensor.outside_temperature",' + 'friendly_name="Outside Temperature"} 15.6' in body + ) + + @pytest.fixture(name="mock_client") def mock_client_fixture(): """Mock the prometheus client."""