mweinelt / ha-prometheus-sensor

Import 🔥 Prometheus query results into 🏡 Home Assistant 📈
MIT License
21 stars 7 forks source link

fix HA exception when prometheus query fails #18

Closed DanielLeone closed 1 month ago

DanielLeone commented 1 month ago

Hi, thanks for making this project - I get some good use out of it!

I'm seeing this exception when my prometheus query returns no result.

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 669, in state
    numerical_value = float(value)  # type:ignore[arg-type]
                      ^^^^^^^^^^^^
ValueError: could not convert string to float: 'problem'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 352, in _async_setup_platform
    await asyncio.gather(*pending)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 533, in async_add_entities
    await asyncio.gather(*tasks)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 782, in _async_add_entity
    await entity.add_to_platform_finish()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1325, in add_to_platform_finish
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 989, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1110, in _async_write_ha_state
    state, attr, capabilities, shadowed_attr = self.__async_calculate_state()
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1047, in __async_calculate_state
    state = self._stringify_state(available)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 995, in _stringify_state
    if (state := self.state) is None:
                 ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 671, in state
    raise ValueError(
ValueError: Sensor sensor.electrical_box_temperature has device class 'temperature', state class 'None' unit '°C' and suggested precision 'None' thus indicating it has a numeric value; however, it has the non-numeric value: 'problem' (<class 'str'>)

As per the error, I believe it's an issue that we're setting _attr_native_value to "problem" via STATE_PROBLEM since in most cases a prometheus query will return a number, and most device classes probably don't support both numbers and strings as values (such as temperature here).

I've made a change so we instead set the available property to false if there's an error, and the native value to None - which seems to be allowed as per the sensor.py code.

This has the added benefit of showing up in the HA UI when there's an issue (instead of breaking all prometheus sensors with the current exception):

image

I'm new to home assistant code, so I have no idea if this is right or wrong, I'm just fixing issues I ran into 🙏


For context, here's a snippet of the configuration yaml I'm using, which causes the error (when paired with a prometheus query which yields no value)

sensor:
  - platform: prometheus_sensor
    url: http://localhost:8428
    queries:
      - name: Electrical Box Temperature
        expr: mqtt_tempc{topic="xxx"}
        unit_of_measurement: °C
        device_class: temperature
mweinelt commented 1 month ago

Thank you! I pushed a commit on top, that makes the return signature simpler, by just wrapping the result in a dataclass. PTAL.

DanielLeone commented 1 month ago

Thank you! I pushed a commit on top, that makes the return signature simpler, by just wrapping the result in a dataclass. PTAL.

@mweinelt LGTM! :)