Logging handler to send logs to your OpenSearch cluster with bulk SSL. Forked from https://github.com/logzio/logzio-python-handler
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.0 KiB

7 years ago
  1. import sys
  2. import json
  3. import logging
  4. import datetime
  5. import traceback
  6. import logging.handlers
  7. from .sender import LogzioSender
  8. from .exceptions import LogzioException
  9. class LogzioHandler(logging.Handler):
  10. def __init__(self,
  11. token,
  12. logzio_type="python",
  13. logs_drain_timeout=3,
  14. url="https://listener.logz.io:8071",
  15. debug=False):
  16. if not token:
  17. raise LogzioException("Logz.io Token must be provided")
  18. self.logzio_type = logzio_type
  19. self.logzio_sender = LogzioSender(
  20. token=token,
  21. url=url,
  22. logs_drain_timeout=logs_drain_timeout,
  23. debug=debug)
  24. logging.Handler.__init__(self)
  25. def extra_fields(self, message):
  26. not_allowed_keys = (
  27. 'args', 'asctime', 'created', 'exc_info', 'stack_info', 'exc_text',
  28. 'filename', 'funcName', 'levelname', 'levelno', 'lineno', 'module',
  29. 'msecs', 'msecs', 'message', 'msg', 'name', 'pathname', 'process',
  30. 'processName', 'relativeCreated', 'thread', 'threadName')
  31. if sys.version_info < (3, 0):
  32. var_type = (basestring, bool, dict, float,
  33. int, long, list, type(None))
  34. else:
  35. var_type = (str, bool, dict, float, int, list, type(None))
  36. extra_fields = {}
  37. for key, value in message.__dict__.items():
  38. if key not in not_allowed_keys:
  39. if isinstance(value, var_type):
  40. extra_fields[key] = value
  41. else:
  42. extra_fields[key] = repr(value)
  43. return extra_fields
  44. def flush(self):
  45. self.logzio_sender.flush()
  46. def format(self, record):
  47. message = super(LogzioHandler, self).format(record)
  48. try:
  49. return json.loads(message)
  50. except (TypeError, ValueError):
  51. return message
  52. def format_exception(self, exc_info):
  53. return '\n'.join(traceback.format_exception(*exc_info))
  54. def format_message(self, message):
  55. now = datetime.datetime.utcnow()
  56. timestamp = now.strftime("%Y-%m-%dT%H:%M:%S") + \
  57. ".%03d" % (now.microsecond / 1000) + "Z"
  58. return_json = {
  59. "logger": message.name,
  60. "line_number": message.lineno,
  61. "path_name": message.pathname,
  62. "log_level": message.levelname,
  63. "type": self.logzio_type,
  64. "message": message.getMessage(),
  65. "@timestamp": timestamp
  66. }
  67. if message.exc_info:
  68. return_json["exception"] = self.format_exception(message.exc_info)
  69. else:
  70. formatted_message = self.format(message)
  71. return_json.update(self.extra_fields(message))
  72. if isinstance(formatted_message, dict):
  73. return_json.update(formatted_message)
  74. else:
  75. return_json["message"] = formatted_message
  76. return return_json
  77. def emit(self, record):
  78. self.logzio_sender.append(self.format_message(record))