Skip to content

Commit 16a2e3e

Browse files
✨ Add entity/device/area labels as tags
This PR adds tags based on entity relationship with device and areas by using their labels as tags. For instance, brightness entity of a light located in a bedroom will have tags based on the labels on the entity, its device and the area. This should help with building monitors/dashboards based on properties instead of listing explicitely entity names.
1 parent bd33cc5 commit 16a2e3e

File tree

1 file changed

+51
-5
lines changed

1 file changed

+51
-5
lines changed

custom_components/datadog_agentless/__init__.py

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
from homeassistant.const import Platform, EVENT_STATE_CHANGED, MATCH_ALL, EVENT_HOMEASSISTANT_STOP
2626
from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED
27+
from homeassistant.helpers import device_registry as dr
28+
from homeassistant.helpers import entity_registry as er
29+
from homeassistant.helpers import area_registry as ar
2730
from homeassistant.helpers.event import async_track_time_interval
2831
from homeassistant.components.automation import EVENT_AUTOMATION_TRIGGERED
2932
from homeassistant.const import __version__ as HAVERSION
@@ -72,7 +75,7 @@ def metrics_cancel_dequeuing(*_: Any) -> None:
7275
metrics_cancel_schedule()
7376
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, metrics_cancel_dequeuing)
7477

75-
event_listener=partial(full_event_listener, entry.data, constant_emitter, metrics_queue)
78+
event_listener=partial(full_event_listener, entry.data, hass, constant_emitter, metrics_queue)
7679
unsubscribe = hass.bus.async_listen(EVENT_STATE_CHANGED, event_listener)
7780
hass.data[DOMAIN][entry.entry_id]["unsubscribe_handler"] = unsubscribe
7881

@@ -386,13 +389,55 @@ def _extract_state(new_state: State, entity_id: str, value: Any, main_state: boo
386389
_LOGGER.warn(f"Cannot treat this state changed event: {entity_id} to convert to metric. Error was: %s", e)
387390
return None
388391

389-
def full_event_listener(creds: dict, constant_emitter: ConstantMetricEmitter, metrics_queue, event: Event[EventStateChangedData]):
392+
def additional_tags(hass, new_state) -> list[str]:
393+
"""
394+
Adds new tags if relevant based on labels of the entity
395+
"""
396+
tags = []
397+
entity_registry = er.async_get(hass)
398+
entity = entity_registry.async_get(new_state.entity_id)
399+
if entity is not None:
400+
for l in entity.labels:
401+
if ":" in l:
402+
tags.append(l)
403+
else:
404+
tags.append(f"entity_label:{l}")
405+
_LOGGER.debug(f"Added {len(entity.labels)} labels from entity")
406+
area_id = None
407+
device_registry = dr.async_get(hass)
408+
if entity.device_id is not None:
409+
device = device_registry.async_get(entity.device_id)
410+
if device is not None:
411+
for l in device.labels:
412+
if ":" in l:
413+
tags.append(l)
414+
else:
415+
tags.append(f"device_label:{l}")
416+
area_id = device.area_id
417+
_LOGGER.debug(f"Added {len(device.labels)} labels from device")
418+
if entity.area_id is not None:
419+
area_id = entity.area_id
420+
if area_id is not None:
421+
area_registry = ar.async_get(hass)
422+
# area registry method access is not consistent, it should be async_get
423+
area = area_registry.async_get_area(area_id)
424+
if area is not None:
425+
for l in area.labels:
426+
if ":" in l:
427+
tags.append(l)
428+
else:
429+
tags.append(f"device_label:{l}")
430+
_LOGGER.debug(f"Added {len(area.labels)} labels from area")
431+
return tags
432+
433+
434+
def full_event_listener(creds: dict, hass, constant_emitter: ConstantMetricEmitter, metrics_queue, event: Event[EventStateChangedData]):
390435
try:
391-
unsafe_full_event_listener(creds, constant_emitter, metrics_queue, event)
436+
unsafe_full_event_listener(creds, hass, constant_emitter, metrics_queue, event)
392437
except:
393438
_LOGGER.exception(f"An error occured in event_state_changed callback")
394439

395-
def unsafe_full_event_listener(creds: dict, constant_emitter: ConstantMetricEmitter, metrics_queue, event: Event[EventStateChangedData]):
440+
def unsafe_full_event_listener(creds: dict, hass, constant_emitter: ConstantMetricEmitter, metrics_queue, event: Event[EventStateChangedData]):
396441
new_state = event.data["new_state"]
397442
if new_state is None:
398443
_LOGGER.warn(f"This event has no new state, isn't it strange?. Event is {event}")
@@ -403,8 +448,9 @@ def unsafe_full_event_listener(creds: dict, constant_emitter: ConstantMetricEmit
403448
friendly_name = new_state.attributes.get("friendly_name")
404449
if len(values) == 0:
405450
return
451+
common_tags = additional_tags(hass, new_state)
406452
for (name, unit, value) in values:
407-
tags = [f"entity:{name}", "service:home-assistant", f"version:{HAVERSION}", f"env:{creds['env']}"]
453+
tags = common_tags + [f"entity:{name}", "service:home-assistant", f"version:{HAVERSION}", f"env:{creds['env']}"]
408454
unit_name = None
409455
if unit is not None:
410456
unit_name, conversion = unit

0 commit comments

Comments
 (0)