Issue
I'm looking to set up a logging database handler that will save all the information that Flask currently outputs into the console (unhandled exceptions, werkzeug, sqlachemy), as well as my custom logging messages.
I'm having trouble setting this all up. Questions:
1) Why doesn't the simulated Arithmetic Error in the about view doesn't get picked up by any logger?
2) Why doesn't the werkzeug logger correctly display the server loaded and only has output 'error on request %s' for the simulated Aritmetic error.
3)Is there any simpler way just to pipe everything that is written by the Flask server (and its components) to a DB?
Appreciate the responses and any other suggestion.
What I've done until now:
models.py
class Log(DB.Model):
__tablename__ = 'logs'
id = DB.Column(DB.Integer, primary_key=True) # auto incrementing
logger = DB.Column(DB.String(100)) # the name of the logger. (e.g. myapp.views)
level = DB.Column(DB.String(100)) # info, debug, or error?
trace = DB.Column(DB.String(4096)) # the full traceback printout
msg = DB.Column(DB.String(4096)) # any custom log you may have included
created_at = DB.Column(DB.DateTime, default=DB.func.now()) # the current timestamp
def __init__(self, logger=None, level=None, trace=None, msg=None):
self.logger = logger
self.level = level
self.trace = trace
self.msg = msg
def __unicode__(self):
return self.__repr__()
def __repr__(self):
return "<Log: %s - %s>" % (self.created_at.strftime('%m/%d/%Y-%H:%M:%S'), self.msg[:50])
core.py
"""
This module contains the core objects of the application:
the Flask (APP) object and the database object.
"""
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from samo.config import CONFIG_BY_NAME, ENVIRONMENT
APP = Flask(__name__)
APP.config.from_object('samo.config')
APP.config.from_object(CONFIG_BY_NAME[ENVIRONMENT])
DB = SQLAlchemy(APP)
DB.create_all()
LOGIN_MANAGER = LoginManager()
LOGIN_MANAGER.init_app(APP)
LOGIN_MANAGER.session_protection = "strong"
LOGIN_MANAGER.login_view = "auth.login"
run.py
from samo.core import APP as app, DB
from flask_wtf.csrf import CSRFProtect
from samo.config import config
from samo.models import Log
import traceback
import logging
class SQLAlchemyHandler(logging.Handler):
def emit(self, record):
trace = None
exc = record.__dict__['exc_info']
if exc:
trace = traceback.format_exc(exc)
log = Log(
logger=record.__dict__['name'],
level=record.__dict__['levelname'],
trace=trace,
msg=record.__dict__['msg'],)
DB.session.add(log)
DB.session.commit()
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
ch = SQLAlchemyHandler()
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
loggers = [logger, logging.getLogger('werkzeug'), logging.getLogger('sqlalchemy'), logging.getLogger('flask.app')]
for l in loggers:
l.addHandler(ch)
csrf = CSRFProtect()
if __name__ == '__main__':
csrf.init_app(app)
logger.critical('TEST CRITICAL ERROR')
app.run(host=config['ENV']['HOST'])
views.py
@APP.route('/about')
def about():
"""
Renders the about page.
:return: html template
"""
search = SearchForm(request.form)
raise ArithmeticError('A nasty error')
return render_template('about.html', postsearchform=search)
what was inserted in the database
Solution
In case anyone stumbles upon this
in run.py, this is the only change I made to get to the desired result.
from samo.core import APP as app, DB
from flask_wtf.csrf import CSRFProtect
from samo.config import config
from samo.models import Log
import traceback
import logging
class SQLAlchemyHandler(logging.Handler):
def emit(self, record):
trace = None
exc = record.__dict__['exc_info']
if exc:
trace = traceback.format_exc() ##CHANGE HERE, removed exc parameter
log = Log(
logger=record.__dict__['name'],
level=record.__dict__['levelname'],
trace=trace,
msg=record.__dict__['msg'],)
DB.session.add(log)
DB.session.commit()
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
ch = SQLAlchemyHandler()
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
loggers = [logger, logging.getLogger('werkzeug'), logging.getLogger('sqlalchemy'), logging.getLogger('flask.app')]
for l in loggers:
l.addHandler(ch)
csrf = CSRFProtect()
if __name__ == '__main__':
csrf.init_app(app)
logger.critical('TEST CRITICAL ERROR')
app.run(host=config['ENV']['HOST'])
Problem solved.
Answered By - cnstlungu
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.