Skip to content

Commit

Permalink
Merge 284108e into b0ca504
Browse files Browse the repository at this point in the history
  • Loading branch information
justin-richert committed Mar 2, 2018
2 parents b0ca504 + 284108e commit 737f355
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 81 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ celerybeat-schedule

# dotenv
.env
.envrc

# virtualenv
.venv
Expand Down
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=no-self-use,ungrouped-imports,import-error
disable=no-self-use,ungrouped-imports,import-error,duplicate-code

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down
3 changes: 1 addition & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ name = "pypi"
[packages]

Flask = "*"
raven = "*"
"raven[flask]" = "*"
raven = {version = "*", extras = ["flask"]}


[dev-packages]
Expand Down
68 changes: 10 additions & 58 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ This project requires Python 3.6 and Flask 0.12

## Installation

To install it, simply run
To install it without Sentry support, simply run

pip install flask-logger

To install it with Sentry support, run

pip install flask-logger[raven]

## Usage

Import it and wrap app
Expand Down
11 changes: 9 additions & 2 deletions flask_logger/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
import logging
import sys

from raven import Client
from raven.handlers.logging import SentryHandler
try:
from raven import Client
from raven.handlers.logging import SentryHandler
RAVEN_IMPORTED = True
except ImportError:
RAVEN_IMPORTED = False

LOGGERS = {}

Expand Down Expand Up @@ -47,6 +51,9 @@ def _log(self, name, dsn):
return logger

def _setup_sentry(self, logger, dsn):
if not RAVEN_IMPORTED:
raise Exception('If specifying SENTRY_DSN, raven must be installed'
' (pip install flask-logger[raven])')
sentry_client = Client(dsn, auto_log_stacks=True)
sentry_handler = SentryHandler(sentry_client)
sentry_handler.setLevel(logging.ERROR)
Expand Down
30 changes: 15 additions & 15 deletions flask_logger/tests/test_extension.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""Test the logger extension module."""
# pylint: disable=protected-access,redefined-outer-name,unused-variable

# pylint: disable=protected-access,redefined-outer-name,unused-variable,invalid-name
import logging
import unittest
from unittest.mock import MagicMock, patch

from flask import Flask

from flask_logger import Logger # isort:skip
from flask_logger.extension import LOGGERS # isort:skip
from flask_logger import extension # isort:skip

TEST_DSN = 'http://foo:bar@sentry.local/1?timeout=1' # Got this from raven-python repo tests

Expand All @@ -33,8 +34,7 @@ def tearDown(self):
"""Tear down tests."""
self.ctx.pop()
# reset any mock loggers at module level
# pylint: disable=invalid-name
LOGGERS = {} # noqa
extension.LOGGERS = {} # noqa

def test_default_config(self):
"""Test the default configs."""
Expand Down Expand Up @@ -67,7 +67,7 @@ def test_custom_kwarg_config_init_app(self):
def test_log(self):
"""Test reusing same logger to validate module caching."""
logger = Logger(self.app)
LOGGERS[('test', None)] = MagicMock()
extension.LOGGERS[('test', None)] = MagicMock()
self.assertIsInstance(logger._log('test', None), MagicMock)

def test_log_no_logger(self):
Expand Down Expand Up @@ -97,7 +97,7 @@ def test_setup_stdout(self, mock_handler, mock_formatter):
"""Test setup stdout."""
logger = Logger(self.app)
mock_logger = MagicMock()
LOGGERS[('test', None)] = mock_logger
extension.LOGGERS[('test', None)] = mock_logger

mock_handler.return_value = MagicMock()
mock_formatter.return_value = MagicMock()
Expand All @@ -112,7 +112,7 @@ def test_debug(self):
"""Test debug level logging."""
logger = Logger(self.app) # default level is error
mock_logger = MagicMock()
LOGGERS[('foo', None)] = mock_logger
extension.LOGGERS[('foo', None)] = mock_logger

logger.debug('foo', 'bar', extra={'foo': 'bar'})
mock_logger.assert_not_called()
Expand All @@ -122,7 +122,7 @@ def test_debug(self):
}
logger2 = Logger(self.app, config)
mock_logger2 = MagicMock()
LOGGERS[('foo2', None)] = mock_logger2
extension.LOGGERS[('foo2', None)] = mock_logger2

mock_logger2.debug = MagicMock()
logger2.debug('foo2', 'bar', extra={'foo': 'bar'})
Expand All @@ -132,7 +132,7 @@ def test_info(self):
"""Test info level logging."""
logger = Logger(self.app) # default level is error
mock_logger = MagicMock()
LOGGERS[('foo', None)] = mock_logger
extension.LOGGERS[('foo', None)] = mock_logger

logger.info('foo', 'bar', extra={'foo': 'bar'})
mock_logger.assert_not_called()
Expand All @@ -142,7 +142,7 @@ def test_info(self):
}
logger2 = Logger(self.app, config)
mock_logger2 = MagicMock()
LOGGERS[('foo2', None)] = mock_logger2
extension.LOGGERS[('foo2', None)] = mock_logger2
mock_logger2.info = MagicMock()

logger2.info('foo2', 'bar', extra={'foo': 'bar'})
Expand All @@ -152,7 +152,7 @@ def test_warning(self):
"""Test warning level logging."""
logger = Logger(self.app) # default level is error
mock_logger = MagicMock()
LOGGERS[('foo', None)] = mock_logger
extension.LOGGERS[('foo', None)] = mock_logger

logger.warning('foo', 'bar', extra={'foo': 'bar'})
mock_logger.assert_not_called()
Expand All @@ -162,7 +162,7 @@ def test_warning(self):
}
logger2 = Logger(self.app, config)
mock_logger2 = MagicMock()
LOGGERS[('foo2', None)] = mock_logger2
extension.LOGGERS[('foo2', None)] = mock_logger2
mock_logger2.warning = MagicMock()

logger2.warning('foo2', 'bar', extra={'foo': 'bar'})
Expand All @@ -172,7 +172,7 @@ def test_error(self):
"""Test error level logging."""
logger = Logger(self.app) # default level is error
mock_logger = MagicMock()
LOGGERS[('foo', None)] = mock_logger
extension.LOGGERS[('foo', None)] = mock_logger
mock_logger.error = MagicMock()

logger.error('foo', 'bar', extra={'foo': 'bar'})
Expand All @@ -182,7 +182,7 @@ def test_critical(self):
"""Test critical level logging."""
logger = Logger(self.app) # default level is error
mock_logger = MagicMock()
LOGGERS[('foo', None)] = mock_logger
extension.LOGGERS[('foo', None)] = mock_logger
mock_logger.critical = MagicMock()

logger.critical('foo', 'bar', extra={'foo': 'bar'})
Expand All @@ -192,7 +192,7 @@ def test_exception(self):
"""Test critical level logging."""
logger = Logger(self.app) # default level is error
mock_logger = MagicMock()
LOGGERS[('foo', None)] = mock_logger
extension.LOGGERS[('foo', None)] = mock_logger
mock_logger.exception = MagicMock()

logger.exception('foo', 'bar', extra={'foo': 'bar'})
Expand Down
52 changes: 52 additions & 0 deletions flask_logger/tests/test_raven_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Test the logger extension module."""
# pylint: disable=protected-access,redefined-outer-name,unused-variable,invalid-name
import importlib
import sys
import unittest

import raven
from flask import Flask

import flask_logger

TEST_DSN = 'http://foo:bar@sentry.local/1?timeout=1'


def create_app():
"""Create a Flask app for context."""
app = Flask(__name__)
return app


class TestRavenImport(unittest.TestCase):
"""Test logger when raven isn't installed."""

def setUp(self):
"""Set up tests."""
# Force flask_logger to load without raven in the environment
sys.modules['raven'] = None
importlib.reload(flask_logger.extension)
self.app = create_app()
self.ctx = self.app.app_context()
self.ctx.push()

def tearDown(self):
"""Tear down tests."""
self.ctx.pop()
# reset any mock loggers at module level
# pylint: disable=invalid-name
LOGGERS = {} # noqa
sys.modules['raven'] = raven
# Reload flask logger to restore sys.modules to correct state
importlib.reload(flask_logger.extension)

def test_log_without_raven(self):
"""Test establishing logger when raven isn't installed."""
logger = flask_logger.Logger()
logger.init_app(self.app)
with self.assertRaises(Exception) as context:
logger.error('no_raven_logger', 'this will raise an exception', dsn=TEST_DSN)
self.assertEqual(
str(context.exception),
'If specifying SENTRY_DSN, raven must be installed (pip install flask-logger[raven])'
)

0 comments on commit 737f355

Please sign in to comment.