Martin Thoma
Martin Thoma

Reputation: 136605

What is the advantage of using Flasks app.logger?

I'm typically using the standard logging library or structlog. Recently, when I tried to add a test to a function, I've seen that it uses current_app.logger - which means that this function needed an application context. Otherwise, it didn't need the application context.

Is there an advantage of using the current_app.logger instead of logger = logging.getLogger(__name__)? Is there maybe data available that is not available to the standard logger?

MVCE

import logging
from flask import Flask, current_app

app = Flask(__name__)

# Normal Python logging
logger = logging.getLogger(__name__)
ch = logging.StreamHandler()
logger.addHandler(ch)
logger.setLevel(logging.DEBUG)

# Flasks app logger
app.logger.setLevel(logging.DEBUG)


@app.route("/")
def index():
    current_app.logger.info("flask-app logger info-msg")
    logger.info("base-logger infomsg")
    return "foo"


if __name__ == "__main__":
    app.run()

Upvotes: 2

Views: 1748

Answers (2)

Ken Kinder
Ken Kinder

Reputation: 13140

Mostly it's a matter of configuration. From the Flask source code on logging:

def create_logger(app):
    """Get the Flask app's logger and configure it if needed.
    The logger name will be the same as
    :attr:`app.import_name <flask.Flask.name>`.
    When :attr:`~flask.Flask.debug` is enabled, set the logger level to
    :data:`logging.DEBUG` if it is not set.
    If there is no handler for the logger's effective level, add a
    :class:`~logging.StreamHandler` for
    :func:`~flask.logging.wsgi_errors_stream` with a basic format.
    """

So if you use Flask's logger object, you get one configured with the log level already set based on Flask's other settings, along with a handler.

Notice that within Flask's source code, the logger is used:

    def log_exception(self, exc_info):
        """Logs an exception.  This is called by :meth:`handle_exception`
        if debugging is disabled and right before the handler is called.
        The default implementation logs the exception as error on the
        :attr:`logger`.
        .. versionadded:: 0.8
        """
        self.logger.error(
            f"Exception on {request.path} [{request.method}]", exc_info=exc_info
        )

So given that Flask and presumably apps written using Flask use the current_app.logger log, it would generally be prudent to follow that pattern, since any additional configuration will also be propagated. If you had a compelling reason to, however, you could certainly use your own logger.

Upvotes: 3

Mr. Hobo
Mr. Hobo

Reputation: 562

Setting logger = logging.getLogger(__name__) configures your root logger by default, which you might not want in a production environment. For instance when you define a logger per file/module then you might fall into a trap like the one explained here. So as explained and commented by @noslenkwah.

Having an internal logger is not unique to Flask, it's the standard way to use logging in Python. Every module defines it's own logger, but the configuration of the logging is only handled by the last link in the chain: your project.

My point - if you have a small application, you can obviously stick to a default logger. For more control over the application and setting more than one logger, you might want to check Python Comprehensive Logging using YAML Configuration and a use-case which I've tried to build from this YAML file, to integrate it in one of my hobby projects.

Upvotes: 0

Related Questions