将异常记录到sqlAlchemy数据库中

因此,您希望登录到数据库,而不是文件。好吧,这里有一个简短的简要说明,你将如何做到这一点。

首先,我们需要为sqlacalchemy定义一个日志模型(在 myapp.models ):

 1from sqlalchemy import Column
 2from sqlalchemy.types import DateTime, Integer, String
 3from sqlalchemy.sql import func
 4from sqlalchemy.ext.declarative import declarative_base
 5
 6Base = declarative_base()
 7
 8class Log(Base):
 9    __tablename__ = 'logs'
10    id = Column(Integer, primary_key=True) # auto incrementing
11    logger = Column(String) # the name of the logger. (e.g. myapp.views)
12    level = Column(String) # info, debug, or error?
13    trace = Column(String) # the full traceback printout
14    msg = Column(String) # any custom log you may have included
15    created_at = Column(DateTime, default=func.now()) # the current timestamp
16
17    def __init__(self, logger=None, level=None, trace=None, msg=None):
18        self.logger = logger
19        self.level = level
20        self.trace = trace
21        self.msg = msg
22
23    def __unicode__(self):
24        return self.__repr__()
25
26    def __repr__(self):
27        return "<Log: %s - %s>" % (self.created_at.strftime('%m/%d/%Y-%H:%M:%S'), self.msg[:50])

这里发生的事情并不太令人兴奋。我们只是创建了一个名为“logs”的新表。

在我们开始如何使用这个表之前,这里有一个简单的回顾 logging 在脚本中工作:

 1# http://docs.python.org/howto/logging.html#configuring-logging
 2import logging
 3
 4# create logger
 5logger = logging.getLogger('simple_example')
 6logger.setLevel(logging.DEBUG)
 7
 8# create console handler and set level to debug
 9ch = logging.StreamHandler()
10ch.setLevel(logging.DEBUG)
11
12# create formatter
13formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
14
15# add formatter to ch
16ch.setFormatter(formatter)
17
18# add ch to logger
19logger.addHandler(ch)
20
21# 'application' code
22logger.debug('debug message')
23logger.info('info message')
24logger.warn('warn message')
25logger.error('error message')
26logger.critical('critical message')

从上面的介绍中你应该得到的是 handler 使用A formatter 以及执行 logging.LogRecord . 输出实际上来自 logging.Handler.emit , a method we will now override as we create our SQLAlchemyHandler.

现在让我们子类处理程序(将其放入 myapp.handlers ):

 1import logging
 2import traceback
 3
 4import transaction
 5
 6from models import Log, DBSession
 7
 8class SQLAlchemyHandler(logging.Handler):
 9    # A very basic logger that commits a LogRecord to the SQL Db
10    def emit(self, record):
11        trace = None
12        exc = record.__dict__['exc_info']
13        if exc:
14            trace = traceback.format_exc()
15        log = Log(
16            logger=record.__dict__['name'],
17            level=record.__dict__['levelname'],
18            trace=trace,
19            msg=record.__dict__['msg'],)
20        DBSession.add(log)
21        transaction.commit()

logging.LogRecord 为此 record is an instance, contains all it's nifty log information in it's __dict__ 属性。

现在,我们需要将这个日志处理程序添加到.ini配置文件中。在添加之前,production.ini文件应该包含如下内容:

 1[loggers]
 2keys = root, myapp, sqlalchemy
 3
 4[handlers]
 5keys = console
 6
 7[formatters]
 8keys = generic
 9
10[logger_root]
11level = WARN
12handlers = console
13
14[logger_myapp]
15level = WARN
16handlers =
17qualname = myapp
18
19[logger_sqlalchemy]
20level = WARN
21handlers =
22qualname = sqlalchemy.engine
23# "level = INFO" logs SQL queries.
24# "level = DEBUG" logs SQL queries and results.
25# "level = WARN" logs neither.  (Recommended for production systems.)
26
27[handler_console]
28class = StreamHandler
29args = (sys.stderr,)
30level = NOTSET
31formatter = generic
32
33[formatter_generic]
34format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s

我们必须增加我们的 SQLAlchemyHandler 混合。So make the following changes to your production.ini file.

 1[handlers]
 2keys = console, sqlalchemy
 3
 4[logger_myapp]
 5level = DEBUG
 6handlers = sqlalchemy
 7qualname = myapp
 8
 9[handler_sqlalchemy]
10class = myapp.handlers.SQLAlchemyHandler
11args = ()
12level = NOTSET
13formatter = generic

我们所做的更改只允许Paster识别新的处理程序- sqlalchemy ,位于 [handler_sqlalchemy] . 关于这个配置的其他大部分内容应该是简单的。如果有什么事情仍然令人困惑,那么利用这个机会来阅读Python logging 文档。

Below is an example of how you might use the logger in myapp.views ::

 1import logging
 2from pyramid.view import view_config
 3from pyramid.response import Response
 4
 5log = logging.getLogger(__name__)
 6
 7@view_config(route_name='home')
 8def root(request):
 9    log.debug('exception impending!')
10    try:
11        1/0
12    except:
13        log.exception('1/0 error')
14    log.info('test complete')
15    return Response("test complete!")

执行此视图代码时,最多可以看到三条(取决于配置文件中允许的日志记录级别)记录!

要获得更大的能量,请将其与 Pyramid 的“exclog”匹配,网址为https://docs.pylonsproject.org/projects/pyramid“exclog/en/latest”/