<h1>Logging<aclass="headerlink"href="#logging"title="Link to this heading">¶</a></h1>
<p>Flask uses standard Python <aclass="reference external"href="https://docs.python.org/3/library/logging.html#module-logging"title="(in Python v3.13)"><codeclass="xref py py-mod docutils literal notranslate"><spanclass="pre">logging</span></code></a>. Messages about your Flask
application are logged with <aclass="reference internal"href="api.html#flask.Flask.logger"title="flask.Flask.logger"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">app.logger</span></code></a>,
which takes the same name as <aclass="reference internal"href="api.html#flask.Flask.name"title="flask.Flask.name"><codeclass="xref py py-attr docutils literal notranslate"><spanclass="pre">app.name</span></code></a>. This
logger can also be used to log your own messages.</p>
<spanclass="n">app</span><spanclass="o">.</span><spanclass="n">logger</span><spanclass="o">.</span><spanclass="n">info</span><spanclass="p">(</span><spanclass="s1">'</span><spanclass="si">%s</span><spanclass="s1"> logged in successfully'</span><spanclass="p">,</span><spanclass="n">user</span><spanclass="o">.</span><spanclass="n">username</span><spanclass="p">)</span>
<spanclass="n">app</span><spanclass="o">.</span><spanclass="n">logger</span><spanclass="o">.</span><spanclass="n">info</span><spanclass="p">(</span><spanclass="s1">'</span><spanclass="si">%s</span><spanclass="s1"> failed to log in'</span><spanclass="p">,</span><spanclass="n">user</span><spanclass="o">.</span><spanclass="n">username</span><spanclass="p">)</span>
<p>If you don’t configure logging, Python’s default log level is usually
‘warning’. Nothing below the configured level will be visible.</p>
<sectionid="basic-configuration">
<h2>Basic Configuration<aclass="headerlink"href="#basic-configuration"title="Link to this heading">¶</a></h2>
<p>When you want to configure logging for your project, you should do it as soon
as possible when the program starts. If <aclass="reference internal"href="api.html#flask.Flask.logger"title="flask.Flask.logger"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">app.logger</span></code></a>
is accessed before logging is configured, it will add a default handler. If
possible, configure logging before creating the application object.</p>
<p>This example uses <aclass="reference external"href="https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig"title="(in Python v3.13)"><codeclass="xref py py-func docutils literal notranslate"><spanclass="pre">dictConfig()</span></code></a> to create a logging
configuration similar to Flask’s default, except for all logs:</p>
<spanclass="s1">'format'</span><spanclass="p">:</span><spanclass="s1">'[</span><spanclass="si">%(asctime)s</span><spanclass="s1">] </span><spanclass="si">%(levelname)s</span><spanclass="s1"> in </span><spanclass="si">%(module)s</span><spanclass="s1">: </span><spanclass="si">%(message)s</span><spanclass="s1">'</span><spanclass="p">,</span>
automatically. During requests, it will write to the stream specified by the
WSGI server in <codeclass="docutils literal notranslate"><spanclass="pre">environ['wsgi.errors']</span></code> (which is usually
<aclass="reference external"href="https://docs.python.org/3/library/sys.html#sys.stderr"title="(in Python v3.13)"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">sys.stderr</span></code></a>). Outside a request, it will log to <aclass="reference external"href="https://docs.python.org/3/library/sys.html#sys.stderr"title="(in Python v3.13)"><codeclass="xref py py-data docutils literal notranslate"><spanclass="pre">sys.stderr</span></code></a>.</p>
</section>
<sectionid="removing-the-default-handler">
<h3>Removing the Default Handler<aclass="headerlink"href="#removing-the-default-handler"title="Link to this heading">¶</a></h3>
<p>If you configured logging after accessing
<aclass="reference internal"href="api.html#flask.Flask.logger"title="flask.Flask.logger"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">app.logger</span></code></a>, and need to remove the default
<h2>Email Errors to Admins<aclass="headerlink"href="#email-errors-to-admins"title="Link to this heading">¶</a></h2>
<p>When running the application on a remote server for production, you probably
won’t be looking at the log messages very often. The WSGI server will probably
send log messages to a file, and you’ll only check that file if a user tells
you something went wrong.</p>
<p>To be proactive about discovering and fixing bugs, you can configure a
<aclass="reference external"href="https://docs.python.org/3/library/logging.handlers.html#logging.handlers.SMTPHandler"title="(in Python v3.13)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">logging.handlers.SMTPHandler</span></code></a> to send an email when errors and higher
<spanclass="s1">'[</span><spanclass="si">%(asctime)s</span><spanclass="s1">] </span><spanclass="si">%(levelname)s</span><spanclass="s1"> in </span><spanclass="si">%(module)s</span><spanclass="s1">: </span><spanclass="si">%(message)s</span><spanclass="s1">'</span>
<p>This requires that you have an SMTP server set up on the same server. See the
Python docs for more information about configuring the handler.</p>
</section>
<sectionid="injecting-request-information">
<h2>Injecting Request Information<aclass="headerlink"href="#injecting-request-information"title="Link to this heading">¶</a></h2>
<p>Seeing more information about the request, such as the IP address, may help
debugging some errors. You can subclass <aclass="reference external"href="https://docs.python.org/3/library/logging.html#logging.Formatter"title="(in Python v3.13)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">logging.Formatter</span></code></a> to inject
your own fields that can be used in messages. You can change the formatter for
Flask’s default handler, the mail handler defined above, or any other
<spanclass="s1">'</span><spanclass="si">%(levelname)s</span><spanclass="s1"> in </span><spanclass="si">%(module)s</span><spanclass="s1">: </span><spanclass="si">%(message)s</span><spanclass="s1">'</span>
<h3>Werkzeug<aclass="headerlink"href="#werkzeug"title="Link to this heading">¶</a></h3>
<p>Werkzeug logs basic request/response information to the <codeclass="docutils literal notranslate"><spanclass="pre">'werkzeug'</span></code> logger.
If the root logger has no handlers configured, Werkzeug adds a
<aclass="reference external"href="https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler"title="(in Python v3.13)"><codeclass="xref py py-class docutils literal notranslate"><spanclass="pre">StreamHandler</span></code></a> to its logger.</p>
</section>
<sectionid="flask-extensions">
<h3>Flask Extensions<aclass="headerlink"href="#flask-extensions"title="Link to this heading">¶</a></h3>
<p>Depending on the situation, an extension may choose to log to
<aclass="reference internal"href="api.html#flask.Flask.logger"title="flask.Flask.logger"><codeclass="xref py py-meth docutils literal notranslate"><spanclass="pre">app.logger</span></code></a> or its own named logger. Consult each