How to store Tornado logs to a file?

2020-06-16 04:04发布

问题:

I've been facing issues where my server is throwing a 500 if the API isn't accessed for 30 mins at a stretch. To check the problem, I need to keep track of every single API request made. I'm using Tornado in front of Flask. This is my code so far:

import tornado.httpserver
import tornado.ioloop
import tornado.web
from flasky import app
from tornado.wsgi import WSGIContainer
from tornado.ioloop import IOLoop
from tornado.web import FallbackHandler

from tornado.log import enable_pretty_logging
enable_pretty_logging()


tr = WSGIContainer(app)

application = tornado.web.Application([
    (r".*", FallbackHandler, dict(fallback=tr)),
])

if __name__ == '__main__':
    application.listen(5000)
    IOLoop.instance().start()

Whats the most efficient way to store the logs to some file?

I tried doing this but it only works when the process exits with 0:

import sys
import time
timestr = time.strftime("%Y%m%d-%H%M%S")
filename = "C:/Source/logs/" + timestr + ".log"

class Logger(object):
    def __init__(self):
        self.terminal = sys.stdout
        self.log = open(filename, "a")

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)

    def flush(self):
        pass

sys.stdout = Logger()

回答1:

You have used enable_pretty_logging which is good, and if you might note the documentation says you can pass in a logger. So what is a logger? Turns out Python has very extensive support for logging actions through the builtin logging module (which is mentioned in the documentation too). Generally, you need to set up handlers that write to some specific file, which you can do by

handler = logging.FileHandler(log_file_filename)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info('foo')

This will log all info level entries (or higher) into the file. These loggers can be gathered by the logging.getLogger function, and you can explicitly select these as per the tornado documentation by

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

Simply append your handler to the logger that is generating the messages you want to log to a file. If it's the tornado.application generating the messages you want to see

handler = logging.FileHandler(log_file_filename)
app_log = logging.getLogger("tornado.application")
enable_pretty_logging()
app_log.addHandler(handler)

Or you can also use the builtin tornado options that enable this

tornado.options.options['log_file_prefix'].set(log_file_prefix)
tornado.options.parse_command_line()