Logging like a pro
Every program needs to be transparent on what’s hapening inside of it. This way we can debug it quickly, and validate that it works as expected.
Logging is an action of recording the events that happen in the program.
1. Print 📝
The simplest way to log is to use the print
function.
This is okay for initial development, but not so much for production. It’s not so easy to filter messages made by print.
And when you spam too many prints in production, let’s say on a Jenkins instance, you are risking DDoSing it. Don’t ask how I know this. 😅
Print issues:
- No level filtering: Everything prints, even debug info in production
- Not so easy to test, write to files, etc.
2. Logging 🪵
This is the preferred way to capture events in any Python application that’s running in production.
import logging
# Configure logging
logging.basicConfig(
level=logging.WARNING,
format='%(asctime)s | %(levelname)s: %(message)s',
handlers=[
logging.StreamHandler() # Surfaces logs to console
]
)
# Won't show because level is set to WARNING
logging.debug("Processing request.")
logging.info("Application started successfully")
# These will show (level WARNING and above)
logging.warning("High memory usage detected")
error_code = 404
logging.error("Error %d occurred during processing", error_code)
- Note how
%s
was used instead of f-strings (f”{error_code} …”). This is because this way it’s lazy and won’t evaluate unless the log level for it is enabled. - StreamHandler controls where your logs go. By default, logs go to the console, but you can send them to files or other destinations.
3. Log Levels
Python’s logging module provides different levels of severity:
- DEBUG (10): Detailed information for diagnosing problems
- INFO (20): General information about program execution
- WARNING (30): Something unexpected happened, but the program can continue
- ERROR (40): A more serious problem occurred
- CRITICAL (50): A critical problem that may prevent the program from running