Log entity_id payload and template on MQTT value template error (#98353)

* Log entity_id payload and template on error

* Also handle cases with default values.

* Do not log payload twice

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Tweak test to assert without payload

* black

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
Jan Bouwhuis 2023-08-18 13:05:53 +02:00 committed by GitHub
parent 80a5e341b5
commit 5ef6c03610
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 7 deletions

View file

@ -231,11 +231,21 @@ class MqttValueTemplate:
values, values,
self._value_template, self._value_template,
) )
rendered_payload = ( try:
self._value_template.async_render_with_possible_json_value( rendered_payload = (
payload, variables=values self._value_template.async_render_with_possible_json_value(
payload, variables=values
)
) )
) except Exception as ex: # pylint: disable=broad-except
_LOGGER.error(
"%s: %s rendering template for entity '%s', template: '%s'",
type(ex).__name__,
ex,
self._entity.entity_id if self._entity else "n/a",
self._value_template.template,
)
raise ex
return rendered_payload return rendered_payload
_LOGGER.debug( _LOGGER.debug(
@ -248,9 +258,24 @@ class MqttValueTemplate:
default, default,
self._value_template, self._value_template,
) )
rendered_payload = self._value_template.async_render_with_possible_json_value( try:
payload, default, variables=values rendered_payload = (
) self._value_template.async_render_with_possible_json_value(
payload, default, variables=values
)
)
except Exception as ex: # pylint: disable=broad-except
_LOGGER.error(
"%s: %s rendering template for entity '%s', template: "
"'%s', default value: %s and payload: %s",
type(ex).__name__,
ex,
self._entity.entity_id if self._entity else "n/a",
self._value_template.template,
default,
payload,
)
raise ex
return rendered_payload return rendered_payload

View file

@ -41,6 +41,7 @@ from .test_common import help_all_subscribe_calls
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
MockEntity,
async_fire_mqtt_message, async_fire_mqtt_message,
async_fire_time_changed, async_fire_time_changed,
mock_restore_cache, mock_restore_cache,
@ -417,6 +418,37 @@ async def test_value_template_value(hass: HomeAssistant) -> None:
assert template_state_calls.call_count == 1 assert template_state_calls.call_count == 1
async def test_value_template_fails(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test the rendering of MQTT value template fails."""
# test rendering a value fails
entity = MockEntity(entity_id="sensor.test")
entity.hass = hass
tpl = template.Template("{{ value_json.some_var * 2 }}")
val_tpl = mqtt.MqttValueTemplate(tpl, hass=hass, entity=entity)
with pytest.raises(TypeError):
val_tpl.async_render_with_possible_json_value('{"some_var": null }')
await hass.async_block_till_done()
assert (
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' "
"rendering template for entity 'sensor.test', "
"template: '{{ value_json.some_var * 2 }}'"
) in caplog.text
caplog.clear()
with pytest.raises(TypeError):
val_tpl.async_render_with_possible_json_value(
'{"some_var": null }', default=100
)
assert (
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' "
"rendering template for entity 'sensor.test', "
"template: '{{ value_json.some_var * 2 }}', default value: 100 and payload: "
'{"some_var": null }'
) in caplog.text
async def test_service_call_without_topic_does_not_publish( async def test_service_call_without_topic_does_not_publish(
hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator hass: HomeAssistant, mqtt_mock_entry: MqttMockHAClientGenerator
) -> None: ) -> None: