Introduction
As automation frameworks grow, simple console logging is often not sufficient for debugging and maintaining test execution. Testers may need logs to be displayed in the console during execution while also saving them to a log file for future analysis.
Custom Logging allows you to configure your own logger with custom settings such as log levels, formatting, output destinations, and multiple handlers. Instead of relying on the default logging configuration, a custom logger provides greater flexibility and control over how log messages are generated and stored.
In Selenium automation frameworks, custom logging is commonly used to record browser actions, application events, test execution steps, errors, and debugging information. These logs can be displayed in the console and simultaneously written to log files, making troubleshooting much easier.
In this tutorial, you’ll learn what Custom Logging is, why it is used, how to create a custom logger in Python, and how it can be integrated into Selenium automation frameworks.
What is Custom Logging?
Custom Logging is the process of creating and configuring your own logger instead of using Python’s default logging configuration.
A custom logger allows you to:
Define your own logger name.
Configure logging levels.
Create custom log formats.
Write logs to multiple destinations.
Save logs to files.
Display logs in the console.
Control how log messages are handled.
This makes automation frameworks more organized and easier to debug.
Why Use Custom Logging?
Custom logging provides several benefits:
Displays logs in multiple locations.
Saves logs for future analysis.
Improves debugging.
Provides consistent log formatting.
Supports reusable logging configuration.
Simplifies framework maintenance.
Records detailed execution history.
Improves troubleshooting.
Components of a Custom Logger
A custom logger typically consists of:
Logger
Handler
Formatter
Logging Level
Log File
These components work together to generate and store log messages.
Example
import logging
from pathlib import Path
from selenium import webdriver
def build_logger(log_file):
logger = logging.getLogger("custom_selenium")
logger.setLevel(logging.INFO)
logger.handlers.clear()
file_handler = logging.FileHandler(
log_file,
encoding="utf-8"
)
stream_handler = logging.StreamHandler()
formatter = logging.Formatter(
"%(asctime)s | %(levelname)s | %(message)s"
)
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
return logger
def test_custom_logging(tmp_path):
log_file = tmp_path / "test.log"
logger = build_logger(log_file)
driver = webdriver.Chrome()
try:
logger.info("Starting custom logging demo")
driver.get(
"https://www.testmuai.com/selenium-playground/"
)
logger.info(
"Title: %s",
driver.title
)
assert log_file.exists()
assert "Starting custom logging demo" in log_file.read_text(
encoding="utf-8"
)
finally:
driver.quit()
Understanding the Code
Import Required Modules
import logging
from pathlib import Path
from selenium import webdriver
The required modules are imported.
loggingis used to create the custom logger.Pathhelps manage file paths.webdriverlaunches and controls the browser.
Create a Logger
logger = logging.getLogger("custom_selenium")
A logger named custom_selenium is created.
Using a custom name helps identify log messages generated by your automation framework.
Set the Logging Level
logger.setLevel(logging.INFO)
The logger is configured to record INFO messages and all higher-level messages such as WARNING, ERROR, and CRITICAL.
Clear Existing Handlers
logger.handlers.clear()
Existing handlers are removed before adding new ones.
This prevents duplicate log messages when the logger is created multiple times.
Create a File Handler
file_handler = logging.FileHandler(
log_file,
encoding="utf-8"
)
The FileHandler writes log messages to the file specified by log_file.
This creates a persistent log file that can be reviewed later.
Create a Stream Handler
stream_handler = logging.StreamHandler()
The StreamHandler displays log messages in the console while the test is running.
This allows testers to monitor execution in real time.
Create a Log Formatter
formatter = logging.Formatter(
"%(asctime)s | %(levelname)s | %(message)s"
)
A formatter defines how each log entry will appear.
The format includes:
%(asctime)s→ Date and time%(levelname)s→ Logging level%(message)s→ Log message
Example output:
2026-07-16 10:15:30 | INFO | Starting custom logging demo
Apply the Formatter
file_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)
The formatter is applied to both the file handler and the console handler.
As a result, both outputs use the same log format.
Add the Handlers
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
The handlers are attached to the logger.
From this point onward, every log message is written to both:
Console
Log File
Return the Logger
return logger
The configured logger is returned so it can be reused throughout the automation framework.
Create the Log File
log_file = tmp_path / "test.log"
logger = build_logger(log_file)
A temporary log file named test.log is created.
The custom logger is initialized using this file.
Launch the Browser
driver = webdriver.Chrome()
A new Chrome browser instance is launched.
Write Log Messages
logger.info("Starting custom logging demo")
An INFO-level message is written.
The message appears in both the console and the log file.
Open the Application
driver.get(
"https://www.testmuai.com/selenium-playground/"
)
The Selenium Playground application is opened.
Log the Page Title
logger.info(
"Title: %s",
driver.title
)
The page title is written to both the console and the log file.
Example output:
INFO | Title: Selenium Playground
Verify the Log File
assert log_file.exists()
The assertion verifies that the log file was successfully created.
Verify the Log Content
assert "Starting custom logging demo" in log_file.read_text(
encoding="utf-8"
)
The log file is read and verified to ensure that the expected log message was written successfully.
Close the Browser
finally:
driver.quit()
The browser is closed after the test execution.
Practical Example
Suppose an e-commerce automation framework executes hundreds of Selenium test cases every night.
A custom logger records browser launches, user login attempts, product searches, checkout operations, and failures. The logs are displayed in the console during execution and saved to log files for future analysis.
Automation Testing Example
Consider an online banking application.
During automated fund transfer testing, the framework records customer login, account selection, transaction details, and logout operations. If a transfer fails, the custom log file provides a detailed history of every action performed, helping developers identify the exact point of failure.
Real-World Example
Custom logging is widely used in:
Selenium Automation Frameworks
PyTest Frameworks
API Automation Frameworks
Jenkins Pipelines
GitHub Actions
Azure DevOps
Banking Applications
Healthcare Systems
E-commerce Platforms
Enterprise Automation Projects
Professional automation frameworks rely on custom logging to maintain detailed execution records and simplify debugging.
Advantages of Custom Logging
Records execution history.
Writes logs to multiple destinations.
Improves debugging.
Provides reusable logging configuration.
Supports consistent formatting.
Makes troubleshooting easier.
Organizes framework logs.
Enhances automation maintainability.
Common Mistakes Beginners Make
Creating Multiple Loggers Without Clearing Handlers
Always clear existing handlers before adding new ones to avoid duplicate log entries.
Using Only Console Logging
Save logs to a file so they can be reviewed after test execution.
Using Poor Log Formats
Include timestamps, logging levels, and meaningful messages for better debugging.
Logging Sensitive Information
Avoid logging passwords, API keys, or confidential user data.
Best Practices
Create a reusable logger utility.
Use both console and file handlers.
Include timestamps in log messages.
Use appropriate logging levels.
Keep log messages meaningful.
Store log files in a dedicated logs folder.
Combine logging with screenshots and reports for complete debugging information.
Conclusion
Custom Logging gives Selenium automation frameworks complete control over how log messages are generated, formatted, and stored. By using custom loggers with multiple handlers, automation frameworks can display logs in the console while simultaneously saving them to files. This improves debugging, simplifies maintenance, and provides detailed execution records, making custom logging an essential component of professional Selenium automation frameworks.
Frequently Asked Questions (FAQs)
What is Custom Logging?
Custom Logging is the process of creating and configuring your own logger to control how log messages are generated, formatted, and stored.
Why should I use Custom Logging instead of the default logging configuration?
Custom Logging provides greater flexibility by allowing you to define custom formats, logging levels, and multiple output destinations such as the console and log files.
What is a Handler in Python Logging?
A handler determines where log messages are sent, such as the console (StreamHandler) or a file (FileHandler).
Why is logger.handlers.clear() used?
It removes existing handlers to prevent duplicate log messages when the logger is initialized multiple times.
Is Custom Logging used in professional automation frameworks?
Yes.
Professional Selenium automation frameworks commonly use custom loggers to generate structured log messages, save execution history, support debugging, and maintain consistent logging across the entire framework.
Key Takeaways
Custom Loggingprovides complete control over logging behavior.A custom logger can write messages to both the console and log files.
FileHandlersaves logs to files, whileStreamHandlerdisplays logs in the console.Formatterdefines how log messages are displayed.Custom logging is a standard practice in professional Selenium automation frameworks for debugging and execution tracking.
