core/homeassistant/components/datadog/__init__.py

136 lines
3.8 KiB
Python

"""Support for sending data to Datadog."""
import logging
from datadog import DogStatsd, initialize
import voluptuous as vol
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import (
CONF_HOST,
CONF_PORT,
CONF_PREFIX,
EVENT_LOGBOOK_ENTRY,
EVENT_STATE_CHANGED,
STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv, state as state_helper
from homeassistant.helpers.typing import ConfigType
from . import config_flow as config_flow
from .const import (
CONF_RATE,
DEFAULT_HOST,
DEFAULT_PORT,
DEFAULT_PREFIX,
DEFAULT_RATE,
DOMAIN,
)
_LOGGER = logging.getLogger(__name__)
type DatadogConfigEntry = ConfigEntry[DogStatsd]
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_HOST, default=DEFAULT_HOST): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_PREFIX, default=DEFAULT_PREFIX): cv.string,
vol.Optional(CONF_RATE, default=DEFAULT_RATE): vol.All(
vol.Coerce(int), vol.Range(min=1)
),
}
)
},
extra=vol.ALLOW_EXTRA,
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Datadog integration from YAML, initiating config flow import."""
if DOMAIN not in config:
return True
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_IMPORT},
data=config[DOMAIN],
)
)
return True
async def async_setup_entry(hass: HomeAssistant, entry: DatadogConfigEntry) -> bool:
"""Set up Datadog from a config entry."""
data = entry.data
options = entry.options
host = data[CONF_HOST]
port = data[CONF_PORT]
prefix = options[CONF_PREFIX]
sample_rate = options[CONF_RATE]
statsd_client = DogStatsd(
host=host, port=port, namespace=prefix, disable_telemetry=True
)
entry.runtime_data = statsd_client
initialize(statsd_host=host, statsd_port=port)
def logbook_entry_listener(event):
name = event.data.get("name")
message = event.data.get("message")
entry.runtime_data.event(
title="Home Assistant",
message=f"%%% \n **{name}** {message} \n %%%",
tags=[
f"entity:{event.data.get('entity_id')}",
f"domain:{event.data.get('domain')}",
],
)
def state_changed_listener(event):
state = event.data.get("new_state")
if state is None or state.state == STATE_UNKNOWN:
return
metric = f"{prefix}.{state.domain}"
tags = [f"entity:{state.entity_id}"]
for key, value in state.attributes.items():
if isinstance(value, (float, int, bool)):
value = int(value) if isinstance(value, bool) else value
attribute = f"{metric}.{key.replace(' ', '_')}"
entry.runtime_data.gauge(
attribute, value, sample_rate=sample_rate, tags=tags
)
try:
value = state_helper.state_as_number(state)
entry.runtime_data.gauge(metric, value, sample_rate=sample_rate, tags=tags)
except ValueError:
pass
entry.async_on_unload(
hass.bus.async_listen(EVENT_LOGBOOK_ENTRY, logbook_entry_listener)
)
entry.async_on_unload(
hass.bus.async_listen(EVENT_STATE_CHANGED, state_changed_listener)
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: DatadogConfigEntry) -> bool:
"""Unload a Datadog config entry."""
runtime = entry.runtime_data
runtime.flush()
runtime.close_socket()
return True