Python logging
why logging?¶
- Logging is essential to understand the behaviour of the application
- Logging helps in debugging the unexpected issues or for simply tracking events.
- Logs can used to get insights, set monitoring alerts, etc.
logging levels¶
- Critical - used when error occured but execution can't be continued
- Error - used when error occured but execution can be continued
- Warning - used when something unexpected happened in the application, a problem, or a situation that might disturb one of the processes.
- Info - used to when debugging the app with less details
- Debug - used to when debug the app with specific details.
logging module¶
- python has a built-in module to handle the logging.
- it can be extended to write custom loggers based on the dev needs.
- let's look at the below code
import logging
# config logging
logger = logging.getLogger(name='mylogger')
logging.basicConfig(level=logging.DEBUG)
def calculate_simple_interest(p, t, r):
logger.info(f'principal={p} time={t} rate of interest={r}')
amount = p * (1 + r * t)
return amount
if __name__ == '__main__':
interest = calculate_simple_interest(1000, 12, 0.2)
- Try out the above code, we can see the below log in the console.
INFO:mylogger:principal=1000 time=12 rate of interest=0.2
logging handlers¶
- Handler is an object responsible for dispatching the appropriate log messages (based on the log messages' severity) to the handler's specified destination.
- Handlers are propagated like levels. If the logger has no handler set, its chain of ancestors is search for a handler.
import logging
logger = logging.getLogger('dev')
logger.setLevel(logging.INFO)
fileHandler = logging.FileHandler('test.log')
fileHandler.setLevel(logging.INFO)
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO)
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
logger.info('information message')
-
In the above code we have setup the two handlers.
-
file handler - writes the logs to the file
- stream handler - writes the logs to the stream if specified otherwise to
sys.stderr
is used.
logging formatters¶
- Formatter is an object which configures the final order, structure, and contents of the log record.
- In addition to the message string, log records also include date and time, log names, and log level severity.
import logging
logger = logging.getLogger('dev')
logger.setLevel(logging.INFO)
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.INFO)
logger.addHandler(consoleHandler)
formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')
consoleHandler.setFormatter(formatter)
logger.info('information message')
# output: 2022-12-25 10:25:12,080 dev INFO: information message
logging basicConfig¶
- The basicConfig configures the root logger.
- It does basic configuration for the logging system by creating a stream handler with a default formatter.
- The debug, info, warning, error and critical call basicConfig automatically if no handlers are defined for the root logger.
import logging
logging.basicConfig(
filename='/tmp/test.log',
format='%(filename)s: %(message)s',
level=logging.DEBUG
)
logging.debug('This is a debug message')
logging.info('This is an info message')
logging.warning('This is a warning message')
logging.error('This is an error message')
logging.critical('This is a critical message')
- when we run the above code, it writes the logs to the file
/tmp/test.log
. - when we do
cat /tmp/test.log
then it shows the below text
testlog.py: This is a debug message
testlog.py: This is an info message
testlog.py: This is a warning message
testlog.py: This is an error message
testlog.py: This is a critical message