🔍 Code Extractor

class PerformanceLogger

Maturity: 48

A context manager class that measures and logs the execution time of code blocks, with support for custom metrics and automatic error handling.

File:
/tf/active/vicechatdev/contract_validity_analyzer/utils/logging_utils.py
Lines:
80 - 126
Complexity:
simple

Purpose

PerformanceLogger is designed to track and log performance metrics for operations in Python applications. It uses the context manager protocol (with statement) to automatically start timing when entering a code block and log results when exiting. It captures execution duration, handles both successful and failed operations differently, and allows adding custom metrics during execution. This is useful for monitoring application performance, debugging slow operations, and collecting runtime statistics.

Source Code

class PerformanceLogger:
    """Context manager for logging performance metrics."""
    
    def __init__(self, operation_name: str, logger: Optional[logging.Logger] = None):
        """
        Initialize performance logger.
        
        Args:
            operation_name: Name of the operation being timed
            logger: Logger instance (optional)
        """
        self.operation_name = operation_name
        self.logger = logger or get_logger(__name__)
        self.start_time = None
        self.end_time = None
        self.metrics = {}
    
    def __enter__(self):
        """Start timing."""
        self.start_time = time.time()
        self.logger.debug(f"Starting operation: {self.operation_name}")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """End timing and log results."""
        self.end_time = time.time()
        duration = self.end_time - self.start_time
        
        if exc_type is None:
            # Success
            self.logger.info(f"Completed operation: {self.operation_name} in {duration:.2f}s")
            if self.metrics:
                metrics_str = ", ".join(f"{k}={v}" for k, v in self.metrics.items())
                self.logger.info(f"Metrics for {self.operation_name}: {metrics_str}")
        else:
            # Error occurred
            self.logger.error(f"Operation failed: {self.operation_name} after {duration:.2f}s - {exc_val}")
    
    def add_metric(self, key: str, value: Any):
        """Add a metric to be logged."""
        self.metrics[key] = value
    
    def get_duration(self) -> Optional[float]:
        """Get the duration of the operation."""
        if self.start_time and self.end_time:
            return self.end_time - self.start_time
        return None

Parameters

Name Type Default Kind
bases - -

Parameter Details

operation_name: A descriptive string identifier for the operation being timed. This name appears in all log messages to identify which operation's performance is being measured. Should be meaningful and unique enough to distinguish different operations in logs.

logger: An optional logging.Logger instance to use for output. If not provided, the class will obtain a logger using get_logger(__name__). This allows integration with existing logging configurations or use of a default logger.

Return Value

The __init__ method returns a PerformanceLogger instance. The __enter__ method returns self, allowing the instance to be bound to a variable in the 'with' statement. The get_duration() method returns a float representing the elapsed time in seconds if both start and end times are set, otherwise returns None. The add_metric() method returns None.

Class Interface

Methods

__init__(self, operation_name: str, logger: Optional[logging.Logger] = None)

Purpose: Initialize the PerformanceLogger with an operation name and optional logger

Parameters:

  • operation_name: Name of the operation being timed
  • logger: Optional logger instance; if None, uses get_logger(__name__)

Returns: None (constructor)

__enter__(self)

Purpose: Context manager entry point that starts the timer and logs operation start

Returns: Returns self to allow binding to a variable in the with statement

__exit__(self, exc_type, exc_val, exc_tb)

Purpose: Context manager exit point that stops the timer and logs results or errors

Parameters:

  • exc_type: Exception type if an exception occurred, None otherwise
  • exc_val: Exception value if an exception occurred, None otherwise
  • exc_tb: Exception traceback if an exception occurred, None otherwise

Returns: None (implicitly returns None, allowing exceptions to propagate)

add_metric(self, key: str, value: Any)

Purpose: Add a custom metric to be logged when the operation completes successfully

Parameters:

  • key: String identifier for the metric
  • value: Value of the metric (can be any type that converts to string)

Returns: None

get_duration(self) -> Optional[float]

Purpose: Retrieve the duration of the operation in seconds

Returns: Float representing duration in seconds if timing is complete, None if timing hasn't started or finished

Attributes

Name Type Description Scope
operation_name str Name of the operation being timed, used in log messages instance
logger logging.Logger Logger instance used for outputting performance information instance
start_time Optional[float] Timestamp when the operation started (from time.time()), None before __enter__ is called instance
end_time Optional[float] Timestamp when the operation ended (from time.time()), None before __exit__ is called instance
metrics Dict[str, Any] Dictionary storing custom metrics added during operation execution, logged on successful completion instance

Dependencies

  • logging
  • time
  • typing

Required Imports

import logging
import time
from typing import Optional, Any

Usage Example

import logging
import time
from typing import Optional, Any

# Assuming get_logger is defined or use standard logger
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)

# Basic usage
with PerformanceLogger('data_processing', logger) as perf:
    # Simulate some work
    time.sleep(1)
    # Add custom metrics
    perf.add_metric('records_processed', 1000)
    perf.add_metric('cache_hits', 45)

# Get duration after completion
print(f"Duration: {perf.get_duration():.2f}s")

# Usage with error handling
try:
    with PerformanceLogger('risky_operation') as perf:
        # This will be logged as failed
        raise ValueError('Something went wrong')
except ValueError:
    pass

Best Practices

  • Always use as a context manager with the 'with' statement to ensure proper timing and cleanup
  • Provide descriptive operation names that clearly identify what is being measured
  • Add metrics using add_metric() during the operation, not after the context exits
  • Call get_duration() only after the context has exited to get accurate timing
  • The logger should be configured before use to ensure log messages are captured
  • Metrics are logged only on successful completion (no exception); failed operations log the error but not metrics
  • The class does not suppress exceptions - they propagate normally after logging
  • Instance can be reused but timing will reflect only the most recent context entry/exit
  • Thread-safe for independent instances but not for shared instances across threads

Similar Components

AI-powered semantic similarity - components with related functionality:

  • function log_performance 72.9% similar

    A context manager decorator that logs the performance metrics of an operation by wrapping it with a PerformanceLogger instance.

    From: /tf/active/vicechatdev/contract_validity_analyzer/utils/logging_utils.py
  • class ProgressLogger 65.0% similar

    A progress tracking logger that monitors and reports the progress of long-running operations with timing statistics, error counts, and estimated completion times.

    From: /tf/active/vicechatdev/contract_validity_analyzer/utils/logging_utils.py
  • function setup_logging_v3 48.8% similar

    Configures Python's logging system for testing purposes with both console and file output.

    From: /tf/active/vicechatdev/contract_validity_analyzer/test_implementation.py
  • function setup_test_logging 47.4% similar

    Configures Python logging with both console and file output for test execution, returning a logger instance for the calling module.

    From: /tf/active/vicechatdev/contract_validity_analyzer/test_local_document.py
  • function setup_test_logging_v3 46.9% similar

    Configures Python logging with both console and file output for test execution, returning a logger instance for the calling module.

    From: /tf/active/vicechatdev/contract_validity_analyzer/test_ocr_retry.py
← Back to Browse