tornado总结10-日志配置

原创
2016/11/28 23:31
阅读数 1.4W

tornado源代码分析

打开site-packages/tornado/log.py,最开头的注释文档说明了tornado的日志模块是直接和logging模块集成的

"""Logging support for Tornado.

Tornado uses three logger streams:

* ``tornado.access``: Per-request logging for Tornado's HTTP servers (and
  potentially other servers in the future)
* ``tornado.application``: Logging of errors from application code (i.e.
  uncaught exceptions from callbacks)
* ``tornado.general``: General-purpose logging, including any errors
  or warnings from Tornado itself.

These streams may be configured independently using the standard library's
`logging` module.  For example, you may wish to send ``tornado.access`` logs
to a separate file for analysis.
"""

其中一共用到了三种被命名的logger

access_log = logging.getLogger("tornado.access")
app_log = logging.getLogger("tornado.application")
gen_log = logging.getLogger("tornado.general")

access_log 用于记录每一个访问请求

app_log 用于记录程序运行过程中,所有未被处理的异常

gen_log 用于记录tornado自己运行过程中报的错误和警告

 

 

自定义访问日志格式

先看下tornado的源代码,access_log是在tornado.web.RequestHandler中调用的,打开site-packages/tornado/web.py, 日志是在请求完成时调用log_request完成的

def log_request(self, handler):
    """Writes a completed HTTP request to the logs.

    By default writes to the python root logger.  To change
    this behavior either subclass Application and override this method,
    or pass a function in the application settings dictionary as
    ``log_function``.
    """
    if "log_function" in self.settings:
        self.settings["log_function"](handler)
        return
    if handler.get_status() < 400:
        log_method = access_log.info
    elif handler.get_status() < 500:
        log_method = access_log.warning
    else:
        log_method = access_log.error
    request_time = 1000.0 * handler.request.request_time()
    log_method("%d %s %.2fms", handler.get_status(),
               handler._request_summary(), request_time)

其中的日志格式是由handler._request_summary()来决定的

def _request_summary(self):
    return "%s %s (%s)" % (self.request.method, self.request.uri,
                           self.request.remote_ip)

因此我们只需要继承tornado.web.RequestHandler,然后重写_request_summary就可以配置自己的access_log格式了,下面是我自己写的一个BaseHandler

class BaseHandler(tornado.web.RequestHandler):
    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__(application, request)
        self._operator_name = 'NO_LOGIN'

    def _request_summary(self):
        if self.request.method == 'post':
            return "%s %s (%s@%s)" % (self.request.method, self.request.uri,
                                      self._operator_name, self.request.remote_ip)

        return "%s %s %s(%s@%s)" % (self.request.method, self.request.uri, self.request.body.decode(),
                                  self._operator_name, self.request.remote_ip)

BaseHandler重写了_request_summary,并给日志增加了操作者信息和远端IP信息

 

使用配置档初始化

一个logging.yaml例子,这里只配置了tornado.access,其中的logs文件夹需要手动建立

version: 1

loggers:
  root:
    level: DEBUG
    handlers: [console]
  tornado:
    level: DEBUG
    handlers: [console,log]
    propagate: no
  tornado.access:
    level: DEBUG
    handlers: [console, access]
    propagate: no
  log:
    level: DEBUG
    handlers: [console,log]
    propagate: no

formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
  timedRotating:
    format: '%(asctime)s %(name)-12s %(levelname)-8s - %(message)s'

handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: simple
  access:
    class: logging.handlers.TimedRotatingFileHandler
    level: DEBUG
    formatter: simple
    filename: 'logs/access.log'
    when: 'midnight'
    interval: 1
    backupCount: 180
  log:
    class: logging.handlers.TimedRotatingFileHandler
    level: DEBUG
    formatter: timedRotating
    filename: 'logs/log.log'
    when: 'midnight'
    interval: 1
    backupCount: 180
    encoding: 'utf8'

tornado初始化之前记得初始化log配置

log_config = yaml.load(open('logging.yaml', 'r'))
logging.config.dictConfig(log_config)

 

 

 

 

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
1 收藏
0
分享
返回顶部
顶部