Enumerate available states in Prometheus startup (#97993)
parent
69117cb8e3
commit
9144ef7ed8
|
@ -120,10 +120,15 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
default_metric,
|
default_metric,
|
||||||
)
|
)
|
||||||
|
|
||||||
hass.bus.listen(EVENT_STATE_CHANGED, metrics.handle_state_changed)
|
hass.bus.listen(EVENT_STATE_CHANGED, metrics.handle_state_changed_event)
|
||||||
hass.bus.listen(
|
hass.bus.listen(
|
||||||
EVENT_ENTITY_REGISTRY_UPDATED, metrics.handle_entity_registry_updated
|
EVENT_ENTITY_REGISTRY_UPDATED, metrics.handle_entity_registry_updated
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for state in hass.states.all():
|
||||||
|
if entity_filter(state.entity_id):
|
||||||
|
metrics.handle_state(state)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,16 +167,13 @@ class PrometheusMetrics:
|
||||||
self._metrics = {}
|
self._metrics = {}
|
||||||
self._climate_units = climate_units
|
self._climate_units = climate_units
|
||||||
|
|
||||||
def handle_state_changed(self, event):
|
def handle_state_changed_event(self, event):
|
||||||
"""Listen for new messages on the bus, and add them to Prometheus."""
|
"""Handle new messages from the bus."""
|
||||||
if (state := event.data.get("new_state")) is None:
|
if (state := event.data.get("new_state")) is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
entity_id = state.entity_id
|
|
||||||
_LOGGER.debug("Handling state update for %s", entity_id)
|
|
||||||
domain, _ = hacore.split_entity_id(entity_id)
|
|
||||||
|
|
||||||
if not self._filter(state.entity_id):
|
if not self._filter(state.entity_id):
|
||||||
|
_LOGGER.debug("Filtered out entity %s", state.entity_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (old_state := event.data.get("old_state")) is not None and (
|
if (old_state := event.data.get("old_state")) is not None and (
|
||||||
|
@ -179,6 +181,14 @@ class PrometheusMetrics:
|
||||||
) != state.attributes.get(ATTR_FRIENDLY_NAME):
|
) != state.attributes.get(ATTR_FRIENDLY_NAME):
|
||||||
self._remove_labelsets(old_state.entity_id, old_friendly_name)
|
self._remove_labelsets(old_state.entity_id, old_friendly_name)
|
||||||
|
|
||||||
|
self.handle_state(state)
|
||||||
|
|
||||||
|
def handle_state(self, state):
|
||||||
|
"""Add/update a state in Prometheus."""
|
||||||
|
entity_id = state.entity_id
|
||||||
|
_LOGGER.debug("Handling state update for %s", entity_id)
|
||||||
|
domain, _ = hacore.split_entity_id(entity_id)
|
||||||
|
|
||||||
ignored_states = (STATE_UNAVAILABLE, STATE_UNKNOWN)
|
ignored_states = (STATE_UNAVAILABLE, STATE_UNKNOWN)
|
||||||
|
|
||||||
handler = f"_handle_{domain}"
|
handler = f"_handle_{domain}"
|
||||||
|
|
|
@ -107,6 +107,34 @@ async def generate_latest_metrics(client):
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("namespace", [""])
|
||||||
|
async def test_setup_enumeration(hass, hass_client, entity_registry, namespace):
|
||||||
|
"""Test that setup enumerates existing states/entities."""
|
||||||
|
|
||||||
|
# The order of when things are created must be carefully controlled in
|
||||||
|
# this test, so we don't use fixtures.
|
||||||
|
|
||||||
|
sensor_1 = entity_registry.async_get_or_create(
|
||||||
|
domain=sensor.DOMAIN,
|
||||||
|
platform="test",
|
||||||
|
unique_id="sensor_1",
|
||||||
|
unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||||
|
original_device_class=SensorDeviceClass.TEMPERATURE,
|
||||||
|
suggested_object_id="outside_temperature",
|
||||||
|
original_name="Outside Temperature",
|
||||||
|
)
|
||||||
|
set_state_with_entry(hass, sensor_1, 12.3, {})
|
||||||
|
assert await async_setup_component(hass, prometheus.DOMAIN, {prometheus.DOMAIN: {}})
|
||||||
|
|
||||||
|
client = await hass_client()
|
||||||
|
body = await generate_latest_metrics(client)
|
||||||
|
assert (
|
||||||
|
'homeassistant_sensor_temperature_celsius{domain="sensor",'
|
||||||
|
'entity="sensor.outside_temperature",'
|
||||||
|
'friendly_name="Outside Temperature"} 12.3' in body
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("namespace", [""])
|
@pytest.mark.parametrize("namespace", [""])
|
||||||
async def test_view_empty_namespace(client, sensor_entities) -> None:
|
async def test_view_empty_namespace(client, sensor_entities) -> None:
|
||||||
"""Test prometheus metrics view."""
|
"""Test prometheus metrics view."""
|
||||||
|
|
Loading…
Reference in New Issue