2017-01-16 10:40:00 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2017-02-01 22:03:54 +00:00
|
|
|
#
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
|
|
# in the Software without restriction, including without limitation the rights
|
|
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
|
|
# furnished to do so, subject to the following conditions:
|
|
|
|
#
|
|
|
|
# The above copyright notice and this permission notice shall be included in
|
|
|
|
# all copies or substantial portions of the Software.
|
|
|
|
#
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
# SOFTWARE.
|
|
|
|
|
2017-01-15 16:36:01 +00:00
|
|
|
"""
|
|
|
|
Extra functionality for Flask logging
|
|
|
|
|
|
|
|
Flask-Logging-Extras is a Flask extension that plugs into the logging
|
|
|
|
mechanism of Flask applications.
|
2017-01-16 10:40:00 +00:00
|
|
|
|
|
|
|
Flask-Logging-Extras requires you to set FLASK_LOGGING_EXTRAS_KEYWORDS to a
|
|
|
|
dictionary value, where the dictionary key is a the key you can use in the
|
|
|
|
log message format, and the value is a default value that is substituted if
|
|
|
|
no value is present in the message record.
|
2017-01-15 16:36:01 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
2018-01-30 13:22:17 +00:00
|
|
|
from flask import has_request_context, request, current_app, has_app_context
|
2017-02-02 15:33:14 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
__version_info__ = ('1', '0', '0')
|
2017-01-15 16:36:01 +00:00
|
|
|
__version__ = '.'.join(__version_info__)
|
|
|
|
__author__ = 'Gergely Polonkai'
|
2017-02-01 22:03:54 +00:00
|
|
|
__license__ = 'MIT'
|
2018-05-02 10:35:15 +00:00
|
|
|
__copyright__ = '(c) 2015-2018 Benchmarked.games'
|
2017-01-15 16:36:01 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
|
|
|
|
class FlaskExtraLoggerFormatter(logging.Formatter):
|
|
|
|
"""A log formatter class that is capable of adding extra keywords to log
|
2017-02-02 15:33:14 +00:00
|
|
|
formatters and logging the blueprint name
|
2017-01-16 07:56:58 +00:00
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
import logging
|
2018-05-02 10:35:15 +00:00
|
|
|
from logging.config import dictConfig
|
|
|
|
|
|
|
|
dictConfig({
|
|
|
|
'formatters': {
|
|
|
|
'extras': {
|
|
|
|
'format': '[%(asctime)s] [%(levelname)s] [%(category)s] [%(blueprint)s] %(message)s',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'handlers': {
|
|
|
|
'extras_handler': {
|
|
|
|
'class': 'logging.FileHandler',
|
|
|
|
'args': ('app.log', 'a'),
|
|
|
|
'formatter': 'extras',
|
|
|
|
'level': 'INFO',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'loggers': {
|
|
|
|
'my_app': {
|
|
|
|
'handlers': ['extras_handler'],
|
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
2017-01-16 07:56:58 +00:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
2017-01-16 10:40:00 +00:00
|
|
|
app.config['FLASK_LOGGING_EXTRAS_KEYWORDS'] = {'category': '<unset>'}
|
2017-02-02 15:33:14 +00:00
|
|
|
app.config['FLASK_LOGGING_EXTRAS_BLUEPRINT'] = ('blueprint',
|
|
|
|
'<APP>',
|
|
|
|
'<NOT REQUEST>')
|
2017-01-16 07:56:58 +00:00
|
|
|
|
2017-02-02 15:33:14 +00:00
|
|
|
bp = Blueprint('my_blueprint', __name__)
|
|
|
|
app.register_blueprint(bp)
|
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
logger = logging.getLogger('my_app')
|
2017-01-16 07:56:58 +00:00
|
|
|
|
|
|
|
# This will produce something like this in app.log:
|
2018-05-02 10:35:15 +00:00
|
|
|
# [2018-05-02 12:44:48.944] [INFO] [my category] [<NOT REQUEST>] The message
|
|
|
|
logger.info('The message', extra=dict(category='my category'))
|
2017-02-02 15:33:14 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
@app.route('/1')
|
2017-02-02 15:33:14 +00:00
|
|
|
def route_1():
|
2018-05-02 10:35:15 +00:00
|
|
|
# This will produce a log message like this:
|
|
|
|
# [2018-05-02 12:44:48.944] [INFO] [<unset>] [<APP>] Message
|
|
|
|
logger.info('Message')
|
2017-02-02 15:33:14 +00:00
|
|
|
|
|
|
|
return ''
|
|
|
|
|
|
|
|
@bp.route('/2')
|
|
|
|
def route_2():
|
2018-05-02 10:35:15 +00:00
|
|
|
# This will produce a log message like this:
|
|
|
|
# [2018-05-02 12:44:48.944] [INFO] [<unset>] [my_blueprint] Message
|
|
|
|
logger.info('Message')
|
2017-02-02 15:33:14 +00:00
|
|
|
|
|
|
|
return ''
|
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
# This will produce a log message like this:
|
|
|
|
# [2018-05-02 12:44:48.944] [INFO] [<unset>] [<NOT REQUEST>] Message
|
|
|
|
logger.info('Message')
|
2017-01-15 16:36:01 +00:00
|
|
|
"""
|
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
def _collect_keywords(self, record):
|
|
|
|
"""Collect all valid keywords and add them to the log record if not present
|
2017-01-16 07:56:58 +00:00
|
|
|
"""
|
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
# We assume we do have an active app context here
|
|
|
|
defaults = current_app.config.get('FLASK_LOGGING_EXTRAS_KEYWORDS', {})
|
2017-01-16 07:56:58 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
for keyword, default in defaults.items():
|
|
|
|
if keyword not in record.__dict__:
|
|
|
|
setattr(record, keyword, default)
|
2017-01-15 16:36:01 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
def format(self, record):
|
|
|
|
bp_var, bp_app, bp_noreq = ('blueprint', '<app>', '<not a request>')
|
|
|
|
blueprint = None
|
2017-01-15 16:36:01 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
if has_app_context():
|
|
|
|
self._collect_keywords(record)
|
2017-01-16 10:40:00 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
bp_var, bp_app, bp_noreq = current_app.config.get('FLASK_LOGGING_EXTRAS_BLUEPRINT',
|
|
|
|
(bp_var, bp_app, bp_noreq))
|
2017-01-15 16:36:01 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
if bp_var and has_request_context():
|
|
|
|
blueprint = request.blueprint or bp_app
|
2017-01-15 16:36:01 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
if bp_var and bp_var not in record.__dict__:
|
|
|
|
blueprint = blueprint or bp_noreq
|
2017-01-15 16:36:01 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
setattr(record, bp_var, blueprint)
|
2017-01-16 07:56:58 +00:00
|
|
|
|
2018-05-02 10:35:15 +00:00
|
|
|
return super(FlaskExtraLoggerFormatter, self).format(record)
|