Browse Source

Improve exception logging

Add tests
opensearch
Marek Kudlacz 8 years ago
parent
commit
ffe751d0a6
6 changed files with 140 additions and 6 deletions
  1. +2
    -0
      .gitignore
  2. +6
    -5
      logzio/handler.py
  3. +1
    -1
      setup.py
  4. +12
    -0
      tests/__init__.py
  5. +0
    -0
      tests/unit/__init__.py
  6. +119
    -0
      tests/unit/handler_test.py

+ 2
- 0
.gitignore View File

@ -0,0 +1,2 @@
*.pyc

+ 6
- 5
logzio/handler.py View File

@ -4,6 +4,7 @@ import requests
import traceback import traceback
import datetime import datetime
import json import json
import os
from threading import Event, Thread, Condition, Lock, enumerate from threading import Event, Thread, Condition, Lock, enumerate
from time import sleep from time import sleep
@ -101,16 +102,16 @@ class LogzioHandler(logging.Handler):
# Release the condition # Release the condition
self.logs_counter_condition.release() self.logs_counter_condition.release()
def handle_exceptions(self, message):
message = '\n'.join(traceback.format_exception(*message.exc_info))
def format(self, record): def format(self, record):
message = super(LogzioHandler, self).format(record) message = super(LogzioHandler, self).format(record)
try: try:
return json.loads(message) return json.loads(message)
except TypeError:
except (TypeError, ValueError):
return message return message
def formatException(self, exc_info):
return '\n'.join(traceback.format_exception(*exc_info))
def format_message(self, message): def format_message(self, message):
now = datetime.datetime.utcnow() now = datetime.datetime.utcnow()
timestamp = now.strftime("%Y-%m-%dT%H:%M:%S") + ".%03d" % (now.microsecond / 1000) + "Z" timestamp = now.strftime("%Y-%m-%dT%H:%M:%S") + ".%03d" % (now.microsecond / 1000) + "Z"
@ -125,7 +126,7 @@ class LogzioHandler(logging.Handler):
} }
if message.exc_info: if message.exc_info:
return_json["message"] = self.handle_exceptions(message)
return_json["message"] = self.formatException(message.exc_info)
else: else:
formatted_message = self.format(message) formatted_message = self.format(message)
if isinstance(formatted_message, dict): if isinstance(formatted_message, dict):


+ 1
- 1
setup.py View File

@ -11,7 +11,7 @@ setup(
author_email="roi@logz.io", author_email="roi@logz.io",
url="https://github.com/logzio/logzio-python-handler/", url="https://github.com/logzio/logzio-python-handler/",
license="Apache License 2", license="Apache License 2",
packages=find_packages(),
packages=find_packages(exclude=["tests"]),
install_requires=[ install_requires=[
"requests" "requests"
], ],


+ 12
- 0
tests/__init__.py View File

@ -0,0 +1,12 @@
import os
import pkgutil
def load_tests(loader, suite, pattern):
for imp, modname, _ in pkgutil.walk_packages(__path__):
mod = imp.find_module(modname).load_module(modname)
for test in loader.loadTestsFromModule(mod):
print("Running TestCase: {}".format(modname))
suite.addTests(test)
print("=" * 70)
return suite

+ 0
- 0
tests/unit/__init__.py View File


+ 119
- 0
tests/unit/handler_test.py View File

@ -0,0 +1,119 @@
import ast
import unittest
import logging
import sys
import re
import os
from logzio.handler import LogzioHandler
def dummy_drain_messages():
pass
class TestHandler(unittest.TestCase):
def setUp(self):
self.handler = LogzioHandler('moo')
self.handler.drain_messages = dummy_drain_messages;
def test_json(self):
formatter = logging.Formatter(
'{ "appname":"%(name)s", "functionName":"%(funcName)s", \"lineNo":"%(lineno)d", "severity":"%(levelname)s", "message":"%(message)s"}')
self.handler.setFormatter(formatter)
record = logging.LogRecord(
name='my-logger',
level=0,
pathname='handler_test.py',
lineno=10,
msg="this is a test: moo.",
args=[],
exc_info=None,
func='test_json'
)
formatted_message = self.handler.format_message(record)
formatted_message["@timestamp"] = None
self.assertDictEqual(
formatted_message,
{
'@timestamp': None,
'appname': 'my-logger',
'functionName': 'test_json',
'lineNo': '10',
'line_number': 10,
'log_level': 'NOTSET',
'logger': 'my-logger',
'message': 'this is a test: moo.',
'path_name': 'handler_test.py',
'severity': 'NOTSET',
'type': 'python'
}
)
def test_string(self):
record = logging.LogRecord(
name='my-logger',
level=0,
pathname='handler_test.py',
lineno=10,
msg="this is a test: moo.",
args=[],
exc_info=None,
func='test_json'
)
formatted_message = self.handler.format_message(record)
formatted_message["@timestamp"] = None
self.assertDictEqual(
formatted_message,
{
'@timestamp': None,
'line_number': 10,
'log_level': 'NOTSET',
'logger': 'my-logger',
'message': 'this is a test: moo.',
'path_name': 'handler_test.py',
'type': 'python'
}
)
def test_exc(self):
exc_info = None
try:
raise ValueError("oops.")
except:
exc_info = sys.exc_info()
record = logging.LogRecord(
name='my-logger',
level=0,
pathname='handler_test.py',
lineno=10,
msg="this is a test: moo.",
args=[],
exc_info=exc_info,
func='test_json'
)
formatted_message = self.handler.format_message(record)
formatted_message["@timestamp"] = None
formatted_message["message"] = formatted_message["message"].replace(os.path.abspath(__file__), "")
formatted_message["message"] = re.sub(r", line \d+", "", formatted_message["message"])
self.assertDictEqual(
{
'@timestamp': None,
'line_number': 10,
'log_level': 'NOTSET',
'logger': 'my-logger',
'message': 'Traceback (most recent call last):\n\n File "", in test_exc\n raise ValueError("oops.")\n\nValueError: oops.\n',
'path_name': 'handler_test.py',
'type': 'python'
},
formatted_message
)
if __name__ == '__main__':
unittest.main()

Loading…
Cancel
Save