Coverage for custom_components / remote_logger / handler.py: 100%

20 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-22 21:55 +0000

1from __future__ import annotations 

2 

3import datetime as dt 

4import logging 

5import re 

6import typing 

7 

8from homeassistant import __path__ as HOMEASSISTANT_PATH # noqa: N812 

9from homeassistant.components.system_log import LogEntry 

10from homeassistant.util import dt as dt_util 

11 

12if typing.TYPE_CHECKING: 

13 from collections.abc import Callable 

14 

15 from homeassistant.core import HomeAssistant 

16 

17type KeyType = tuple[str, tuple[str, int], tuple[str, int, str] | None] 

18 

19 

20class ExportingLogHandler(logging.Handler): 

21 """Log handler for error messages.""" 

22 

23 def __init__( 

24 self, 

25 hass: HomeAssistant, 

26 handler: Callable, 

27 ) -> None: 

28 """Initialize a new LogErrorHandler.""" 

29 super().__init__() 

30 self.handler = handler 

31 self.tz = dt_util.get_default_time_zone() 

32 self.paths_re = re.compile(rf"(?:{re.escape(HOMEASSISTANT_PATH[0])}|{re.escape(hass.config.config_dir)})/(.*)") 

33 

34 def emit(self, record: logging.LogRecord) -> None: 

35 """Save error and warning logs. 

36 

37 Everything logged with error or warning is saved in local buffer. A 

38 default upper limit is set to 50 (older entries are discarded) but can 

39 be changed if needed. 

40 """ 

41 if record.name.startswith("custom_components.remote_logger"): 

42 # guard against loops, use exposed entities to check for remote_logger errors 

43 return 

44 entry: LogEntry = LogEntry(record, self.paths_re, formatter=self.formatter, figure_out_source=True) 

45 self.handler(entry.to_dict(), time_fired=dt.datetime.fromtimestamp(record.created, tz=self.tz))