I'm using alembic
in my code to apply database migrations at application start. I'm also using Python's builtin logging
lib to log to the terminal. After applying the migrations (or running any alembic
command that prints to stdout
it seems) my loggers stop working, though.
Code:
import logging
import alembic.command
from alembic.config import Config as AlembicConfig
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("app")
logger.debug("Applying alembic migrations.")
alembic_config = AlembicConfig("alembic.ini")
alembic_config.attributes["sqlalchemy.url"] = connection_string
alembic.command.upgrade(alembic_config, "head", tag="from_app")
logger.debug("Terminating app.")
Expected output:
DEBUG:app:Applying alembic migrations.
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
DEBUG:app:Terminating app.
Actual output:
DEBUG:app:Applying alembic migrations.
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
The last line is missing.
I've tried setting the log level again after applying the migrations (I thought maybe it changed the root logger log level):
...
alembic.command.upgrade(alembic_config, "head", tag="from_app")
logger.setLevel(logging.DEBUG)
logger.debug("Terminating app.")
In fact, even logger.critical("blah")
won't log anything anymore.
I've also tried applying the basic config again and getting the logger again:
...
alembic.command.upgrade(alembic_config, "head", tag="from_app")
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("app")
logger.debug("Terminating app.")
But to no avail. Even the root logger isn't logging anymore:
...
alembic.command.upgrade(alembic_config, "head", tag="from_app")
logging.basicConfig(level=logging.DEBUG)
logging.debug("Terminating app.")
Is there anything I can do to make sure that my loggers are logging? I'd like to keep using the builtin logging functionality, but I'm also open to using some lib for that.
The answer will be found in your alembic.ini
file.
You're running a command which was intended to be a script, not an API call, so alembic is configuring its own logging using logging.fileConfig
, which by default uses disable_existing_loggers=True
. That option will disable any existing non-root loggers unless they or their ancestors are explicitly named in the logging configuration file.
So, the path of least resistance will be to setup your logging configuration in there too. There will be a section with the logging configuration in alembic.ini
- look for a [loggers]
section header. You'll want to modify the content so that your own loggers remain visible - add a [logger_app]
section with the desired handlers, formatters etc.
For consistency's sake, you may want to switch to using fileConfig
from your own script too, instead of the logging.basicConfig
.
An alternative option would be to run alembic scripts in a subprocess, so that their logging configuration doesn't concern you. The stdout/stderr of the subprocess can always be captured and re-emitted as log events from your main process.