Custom Logging

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.

  • logging is used to create the custom logger.

  • Path helps manage file paths.

  • webdriver launches 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 Logging provides complete control over logging behavior.

  • A custom logger can write messages to both the console and log files.

  • FileHandler saves logs to files, while StreamHandler displays logs in the console.

  • Formatter defines how log messages are displayed.

  • Custom logging is a standard practice in professional Selenium automation frameworks for debugging and execution tracking.