LogService.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # -*- coding: utf-8 -*-
  2. # Description:
  3. # Author: Pawel Krupa (paulfantom)
  4. # Author: Ilya Mashchenko (ilyam8)
  5. # SPDX-License-Identifier: GPL-3.0-or-later
  6. from glob import glob
  7. import sys
  8. import os
  9. from bases.FrameworkServices.SimpleService import SimpleService
  10. class LogService(SimpleService):
  11. def __init__(self, configuration=None, name=None):
  12. SimpleService.__init__(self, configuration=configuration, name=name)
  13. self.log_path = self.configuration.get('path')
  14. self.__glob_path = self.log_path
  15. self._last_position = 0
  16. self.__re_find = dict(current=0, run=0, maximum=60)
  17. self.__open_args = {'errors': 'replace'} if sys.version_info[0] > 2 else {}
  18. def _get_raw_data(self):
  19. """
  20. Get log lines since last poll
  21. :return: list
  22. """
  23. lines = list()
  24. try:
  25. if self.__re_find['current'] == self.__re_find['run']:
  26. self._find_recent_log_file()
  27. size = os.path.getsize(self.log_path)
  28. if size == self._last_position:
  29. self.__re_find['current'] += 1
  30. return list() # return empty list if nothing has changed
  31. elif size < self._last_position:
  32. self._last_position = 0 # read from beginning if file has shrunk
  33. with open(self.log_path, **self.__open_args) as fp:
  34. fp.seek(self._last_position)
  35. for line in fp:
  36. lines.append(line)
  37. self._last_position = fp.tell()
  38. self.__re_find['current'] = 0
  39. except (OSError, IOError) as error:
  40. self.__re_find['current'] += 1
  41. self.error(str(error))
  42. return lines or None
  43. def _find_recent_log_file(self):
  44. """
  45. :return:
  46. """
  47. self.__re_find['run'] = self.__re_find['maximum']
  48. self.__re_find['current'] = 0
  49. self.__glob_path = self.__glob_path or self.log_path # workaround for modules w/o config files
  50. path_list = glob(self.__glob_path)
  51. if path_list:
  52. self.log_path = max(path_list)
  53. return True
  54. return False
  55. def check(self):
  56. """
  57. Parse basic configuration and check if log file exists
  58. :return: boolean
  59. """
  60. if not self.log_path:
  61. self.error('No path to log specified')
  62. return None
  63. if self._find_recent_log_file() and os.access(self.log_path, os.R_OK) and os.path.isfile(self.log_path):
  64. return True
  65. self.error('Cannot access {0}'.format(self.log_path))
  66. return False
  67. def create(self):
  68. # set cursor at last byte of log file
  69. self._last_position = os.path.getsize(self.log_path)
  70. status = SimpleService.create(self)
  71. return status