We have a bunch of logging happening in our test popular automation framework and we were using standard Python logging module. We always wanted to make our debugging process simple and make logging look pleasant. Recently we came across the Python module Loguru which provides easier file logging with rotation / retention / compression and also provides good string formatting. Loguru is extremely simple, lightweight and at the same time very powerful and requires minimal setup code to start.
In this post, we are going to illustrate how we used Loguru in our Qxf2 framework
What is difference between standard logging and Loguru
Standard logging and Loguru provide almost the same functionality but Loguru reduces the pain of explicitly instantiating Logger and configuring the Handlers. The logger object is created and we can start using it to log messages. It acts like an interface that delivers the log messages to the configured handlers.
Loguru Implementation
In our framework, we replaced the standard logging with Loguru. Below sections details about the changes that we made for implementing Loguru.
Replace getLogger() function
Generally in standard logging mechanism, we call getLogger() which returns a logger with the specified name. With Loguru we need not explicitly do this, `from loguru import logger` is just enough. The logger is pre-configured and ready to use.
Replace standard Handler, Formatter, Filter
In Loguru, handlers are started using add(). Standard logging requires to create a Handler object and then call addHandler(). Loguru.logger automatically adds a handler when we import it. All the code for adding string and file handlers is not needed now in our framework. So we simply replaced below code
log = logging.getLogger(test_module_name) self.reset_log(log) self.set_log_level(log,level) self.add_stream_handler(log,level,format) if not os.path.exists(self.log_file_dir): os.makedirs(self.log_file_dir) if log_file_name is None: log_file_name = self.log_file_dir + os.sep + test_module_name + '.log' else: log_file_name = self.log_file_dir + os.sep + log_file_name self.add_file_handler(log,level,format,log_file_name) |
With
logger.add(log_file_name,level=level,format=format, rotation="30 days", filter=None, colorize=None, serialize=False, backtrace=True, enqueue=False, catch=True) |
The add() function is used for adding a handler, setting up log formatting, filtering messages and setting levels.
Loguru provides few parameters like rotation/ retention/ compression to remove the older files or compress the files. Since we have a lot of logging messages in our framework, we have set a rotation parameter to 30 which specifies that the current logged file should be closed and a new one created after every 30 days.
Replace the styling of the messages
We have defined date and time format as per our requirement in our constructor logging class
def __init__(self,log_file_name=None,level="DEBUG",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module} | {message}"): "Constructor for the logging class" self.log_file_name=log_file_name |
Similarly, we have implemented string formatting’s using {} in the write() function for writing out the message.
if level.lower()== 'debug': logger.debug("{module} | {msg}",module=d['caller_func'],msg=msg) elif level.lower()== 'info': logger.info("{module} | {msg}",module=d['caller_func'],msg=msg) |
Here is the console log which shows a colorful output after adding different formatters.
Loguru provides many other features like structured logging, customize the levels, gives better data handling, sends email notifications using notifiers, automatically adds colors to the logs etc. Since Loguru comes with pre-configured, ready to use and is compatible with the standard logging, we could quickly implement it in our framework. We hope this post helps you in getting started with Loguru. Happy Logging!
References
1. Python logging made (stupidly) simple
2. Loguru Documentation
I am an experienced engineer who has worked with top IT firms in India, gaining valuable expertise in software development and testing. My journey in QA began at Dell, where I focused on the manufacturing domain. This experience provided me with a strong foundation in quality assurance practices and processes.
I joined Qxf2 in 2016, where I continued to refine my skills, enhancing my proficiency in Python. I also expanded my skill set to include JavaScript, gaining hands-on experience and even build frameworks from scratch using TestCafe. Throughout my journey at Qxf2, I have had the opportunity to work on diverse technologies and platforms which includes working on powerful data validation framework like Great Expectations, AI tools like Whisper AI, and developed expertise in various web scraping techniques. I recently started exploring Rust. I enjoy working with variety of tools and sharing my experiences through blogging.
My interests are vegetable gardening using organic methods, listening to music and reading books.