pythonloggingbottlepython-logging

python bottle always logs to console, no logging to file


In a python project with multiple threads my logging works well to write to a logger file. Basically based on Logging, StreamHandler and standard streams

Part of my project is a bottle web server which runs well also. But every bottle call writes a log to the console like this:

 192.168.178.20 - - [26/Jun/2015 20:22:17] "GET /edit?addJob HTTP/1.1" 200 48028

How to handle this the same way as with the other code, so the bottle logs go also to the logger file?


Solution

  • If you're rolling your own solution, you should write a simple Bottle plugin that emits log lines to a logging logger. Here's an example that sets up a basic logger, defines the logging plugin, and creates a Bottle app with that plugin installed on all routes.

    from bottle import Bottle, request, response
    from datetime import datetime
    from functools import wraps
    import logging
    
    logger = logging.getLogger('myapp')
    
    # set up the logger
    logger.setLevel(logging.INFO)
    file_handler = logging.FileHandler('myapp.log')
    formatter = logging.Formatter('%(msg)s')
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
    
    def log_to_logger(fn):
        '''
        Wrap a Bottle request so that a log line is emitted after it's handled.
        (This decorator can be extended to take the desired logger as a param.)
        '''
        @wraps(fn)
        def _log_to_logger(*args, **kwargs):
            request_time = datetime.now()
            actual_response = fn(*args, **kwargs)
            # modify this to log exactly what you need:
            logger.info('%s %s %s %s %s' % (request.remote_addr,
                                            request_time,
                                            request.method,
                                            request.url,
                                            response.status))
            return actual_response
        return _log_to_logger
    
    app = Bottle()
    app.install(log_to_logger)
    
    @app.route('/')
    def home():
        return ['hello, world']
    
    app.run(host='0.0.0.0', port='8080', quiet=True)
    

    Running that code yields what you want:

    % python myapp.py &
    % curl -v http://localhost:8080/
    % tail myapp.log    
    127.0.0.1 2015-06-27 16:57:09.983249 GET http://localhost:8080/ 200 OK