Logging
Quality Score
Overall Score: 9.0/10 ⭐ Outstanding
- Technical Accuracy: 30/35
- Code Quality: 22/25
- Educational Value: 24/25
- Documentation: 14/15
Last reviewed: June 22, 2026
Logging is a very important part of any application. It allows you to track the
code execution and to debug the application. Python has a built-in logging
module that allows you to log messages to the console, to a file, or to a remote
server. In contrast to the print function, the logging module is more
complete, allowing you to configure the log level, the log format, and the log
destination.
Logging is based in handlers. A handler is an object that receives the log
messages and decides what to do with them. The logging module has several
built-in handlers, such as StreamHandler, FileHandler, RotatingFileHandler
or TimedRotatingFileHandler. But you can create your own handler by inherit
the Handler class. Notifiers is a 3pp
library that provides with extra handlers with the ability to send notifications
to different services.
Any handler can have different configurations, such as the log level or the log
format. The log level is used to filter the log messages. The log format is used
to format the log messages. You can use the built-in log formats or create your
own format by using the Formatter class. Also, a logger can have filters to
filter the log messages before they are sent to the handlers. This way you can
have more control over the log messages, like modifying or discarding them.
Best practices
- Set different log levels for different environments. For example, you may set
DEBUGlevel in development andERRORlevel in production. - Set a specific format for the log messages, including the timestamp or the log level. Using a standard format makes it easier to read the log messages.
- Use the
extraparameter to pass the data to the log message. - Use pipelines
|to separate the different parts of the log message. It can be useful to filter the log messages, or even to parse them. - To include variables in your log message aside from
extra, don't useformatorf-stringin the log call. Instead use the%s, likelogger.info('Variable: %s', value). - Use
logging.exceptionto log an exception message and the stack trace. - Set the different logger instance you are going to use with
logging.getLogger. This way you can configure the logger in one place and use it in different modules.
logging library
This is the built-in Python logging library. It is very flexible and allows you to configure the log level, the log format, and the log destination.
Each logger has a name, and the loggers are organized in a tree-like structure. The root logger is the top-level logger, and all other loggers are children of the root logger.
src.intermediate.logging.default_logging(level)
Example of default logging configuration with basic usage.
Shows how to use Python's built-in logging module without custom configuration. Logs messages at all severity levels to demonstrate the default output format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
int
|
The logging level to set. Must be one of the standard logging levels: DEBUG (10), INFO (20), WARNING (30), ERROR (40), or CRITICAL (50). |
required |
Raises:
| Type | Description |
|---|---|
IndexError
|
If the provided level is not a valid logging level. |
Source code in src/intermediate/logging/custom_logging.py
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
src.intermediate.logging.custom_logging_format(format, datefmt)
Example of custom logging format and date format configuration.
Shows how to customize the logging output by specifying a format string for the log message and a date format string. Additional configuration options like filename and filemode can be used with basicConfig to write logs to files.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
format
|
str
|
Format string for log messages. Can include fields like %(levelname)s, %(message)s, %(asctime)s, etc. |
required |
datefmt
|
str
|
Format string for timestamps using time.strftime() format codes (e.g., '%Y-%m-%d %H:%M:%S'). |
required |
Note
Additional basicConfig parameters: - filename: File path for logging with FileHandler - filemode: Mode to open the log file (e.g., 'a' for append)
Source code in src/intermediate/logging/custom_logging.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
src.intermediate.logging.lazy_logging_format()
Example of lazy logging format.
Avoid using concatenation or f-strings in logging calls. This function demonstrates how to use lazy formatting in logging, where the log message is formatted only if the message is actually going to be logged. This can improve performance when logging is disabled for certain levels.
Source code in src/intermediate/logging/custom_logging.py
68 69 70 71 72 73 74 75 76 77 78 79 | |
src.intermediate.logging.CustomFilter
Bases: Filter
Custom logging filter to mask sensitive information in log records.
This filter extends logging.Filter to automatically detect and mask sensitive information such as passwords and email addresses in log records. It uses regular expressions to identify sensitive data and applies appropriate masking functions.
Attributes:
| Name | Type | Description |
|---|---|---|
keys_to_mask |
Dictionary mapping attribute names to their masking configuration. Each configuration contains a regex pattern and the name of the masking function to apply. |
Source code in src/intermediate/logging/filtering.py
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
Always customize the logging configuration to your needs. The default configuration is very basic and may not be suitable for your application, specially to debug it.
loguru library
Loguru is a third-party library that simplifies the logging configuration to the bare minimum, such as log level and log format. But you can also can configure much more easily, such as:
- color customization.
- log rotation, retention and compression.
- custom log levels.
- lazy evaluation of log messages.
src.intermediate.logging.default_loguru()
Example of default loguru configuration with basic usage.
Shows how to use the loguru library without custom configuration. Loguru provides colorized output, better formatting, and easier configuration compared to the standard logging module. Logs messages at all severity levels to demonstrate the default output.
Source code in src/intermediate/logging/custom_logging.py
82 83 84 85 86 87 88 89 90 91 92 93 94 | |
src.intermediate.logging.custom_loguru_format_and_level(format, level)
Example of custom loguru configuration with format and level.
Shows how to add a custom sink to loguru with specific formatting and log level. Loguru uses the add() method to configure where logs go (sink) and how they are formatted. Sinks can be stdout, files, or custom handlers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
format
|
str
|
Format string for log messages. Can include fields like {level}, {message}, {time}, {name}, etc. Uses Python's string formatting syntax. |
required |
level
|
str
|
Minimum log level as a string (e.g., 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'). |
required |
Note
The sink parameter in logger.add() can be: - sys.stdout or sys.stderr for console output - A file path string for file logging - A logging.Handler instance for custom handling
For more information, see: https://loguru.readthedocs.io/en/stable/api/logger.html#loguru._logger.Logger.add
Source code in src/intermediate/logging/custom_logging.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |