Logging Service#

class LoggingService(name: str, results_dir: Path | None = None, verbose: bool = False)[source]#

Bases: BaseService

Centralized logging service for the Brisk package.

This service provides comprehensive logging functionality including console and file logging with special support for TQDM progress bars. It handles memory buffering for delayed file output and provides organized log formatting with visual separators.

The service automatically configures different log levels for console and file output, and can buffer log messages in memory when no results directory is available, flushing them to file when the directory becomes available.

Attributes:
results_dirOptional[pathlib.Path]

The root directory for all results and log files

verbosebool

Whether to print verbose output to console

loggerlogging.Logger

The configured logger instance

_memory_handlerOptional[logging.MemoryHandler]

Memory handler for buffering logs when no file output is available

Notes

The service uses a memory handler to buffer log messages when no results directory is set, allowing logging to work before the directory structure is established. When a results directory is provided, logs are written to ‘error_log.txt’ in that directory.

Examples

>>> from brisk.services.logging import LoggingService
>>> from pathlib import Path
>>> 
>>> # Create logging service with verbose output
>>> logger_service = LoggingService("logging", Path("results"))
>>> 
>>> # Use the logger
>>> logger_service.logger.info("Starting experiment")
>>> logger_service.logger.warning("This is a warning")
>>> logger_service.logger.error("This is an error")
>>> 
>>> # Change results directory
>>> logger_service.set_results_dir(Path("new_results"))
close_file_handlers() None[source]#

Close and remove all file handlers from the logger.

This releases file locks on log files, which is necessary on Windows before the files can be deleted or moved.

set_results_dir(results_dir: Path) None[source]#

Set the results directory and reconfigure logging.

This method updates the results directory and reconfigures the logger to write to the new location. If there were buffered log messages in memory, they will be flushed to the new file location.

Parameters:
results_dirpathlib.Path

The new results directory for log files

Notes

If the results directory is the same as the current one, no changes are made. Otherwise, the logger is reconfigured and any buffered messages are flushed to the new file location.

Examples

>>> logger_service = LoggingService("logging", verbose=True)
>>> # Logs are buffered in memory
>>> logger_service.logger.info("This will be buffered")
>>> 
>>> # Set results directory - buffered logs will be flushed
>>> logger_service.set_results_dir(Path("results"))
>>> # Now logs go to results/error_log.txt
setup_logger() None[source]#

Configure the logger with appropriate handlers and formatters.

This method sets up the logger with console and file handlers based on the current configuration. It handles memory buffering when no results directory is available and configures different log levels for console and file output.

Notes

The method automatically: - Removes existing handlers to prevent duplicates - Sets up console handler with TQDM support - Configures file handler if results_dir is available - Sets up memory buffering if no file output is possible - Flushes buffered messages when file output becomes available

class TqdmLoggingHandler(level=0)[source]#

Bases: Handler

A logging handler that writes messages through TQDM.

This handler ensures that log messages don’t interfere with TQDM progress bars by using TQDM’s write method. It automatically routes error messages to stderr and other messages to stdout, maintaining clean progress bar display during long-running operations.

Notes

This handler is essential when using TQDM progress bars in the Brisk package, as it prevents log messages from corrupting the progress bar display. It uses tqdm.write() which properly handles the terminal output formatting.

Examples

>>> import logging
>>> from brisk.services.logging import TqdmLoggingHandler
>>> 
>>> # Create handler and add to logger
>>> handler = TqdmLoggingHandler()
>>> logger = logging.getLogger("test")
>>> logger.addHandler(handler)
>>> 
>>> # Log messages won't interfere with TQDM progress bars
>>> logger.info("This won't break progress bars")
>>> logger.error("Errors go to stderr")
emit(record: LogRecord) None[source]#

Format and write a log record through TQDM.

Parameters:
recordLogRecord

The log record to be written

Notes

Uses stderr for error messages (level >= ERROR) and stdout for others. Preserves TQDM progress bar display by using tqdm.write().

class FileFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)[source]#

Bases: Formatter

A custom formatter that adds visual separators between log entries.

This formatter enhances log readability by adding horizontal lines between entries in log files. It makes it easier to distinguish between different log entries when reading log files, especially when there are many consecutive log messages.

Notes

The formatter adds an 80-character horizontal line before each log entry, making log files more readable and organized.

Examples

>>> import logging
>>> from brisk.services.logging import FileFormatter
>>> 
>>> # Create formatter and add to file handler
>>> formatter = FileFormatter("%(asctime)s - %(levelname)s - %(message)s")
>>> file_handler = logging.FileHandler("test.log")
>>> file_handler.setFormatter(formatter)
>>> 
>>> # Log entries will have visual separators
>>> logger = logging.getLogger("test")
>>> logger.addHandler(file_handler)
>>> logger.info("This message will have a separator line above it")
format(record: LogRecord) str[source]#

Format a log record with visual separators.

Parameters:
recordLogRecord

The log record to be formatted

Returns:
str

Formatted log message with separator lines

Notes

Adds an 80-character horizontal line before each log entry.