Skip to main content

A powerful decorator-based logging library with automatic depth tracking, log levels, smart argument formatting, and full async support.

Project description

Logorator

A powerful decorator-based logging library for Python with support for both synchronous and asynchronous functions, featuring automatic depth tracking, log levels, and smart argument formatting.

Features

  • Simple decorator-based logging for function calls
  • Full async support for both synchronous and asynchronous functions
  • Automatic depth tracking with visual indentation for nested calls
  • Log levels (DEBUG, INFO, WARNING, ERROR) with color coding
  • Smart argument formatting - shows parameter names and handles objects intelligently
  • Argument filtering - include or exclude specific parameters
  • Function execution time measurement
  • ANSI color-coded output for better readability
  • Optional file output with automatic color stripping
  • Configurable output formats (normal and short modes)
  • Custom notes for inline logging
  • Works with classes - instance methods, class methods, static methods

Installation

pip install logorator

Quick Start

from logorator import Logger

@Logger()
def add(a, b):
    return a + b

result = add(3, 5)

Output:

Running add
  a: 3
  b: 5
Finished add  Time elapsed: 0.15 ms

Basic Usage

Synchronous Functions

from logorator import Logger

@Logger()
def calculate(x, y, operation="add"):
    if operation == "add":
        return x + y
    return x - y

result = calculate(10, 5, operation="subtract")

Output:

Running calculate
  x: 10
  y: 5
  operation: subtract
Finished calculate  Time elapsed: 0.12 ms

Asynchronous Functions

from logorator import Logger
import asyncio

@Logger()
async def fetch_data(url):
    await asyncio.sleep(1)
    return f"Data from {url}"

asyncio.run(fetch_data("https://example.com"))

Output:

Running async fetch_data
  url: https://example.com
Finished async fetch_data (https://example.com)  Time elapsed: 1,002.34 ms

Nested Function Calls

Depth tracking is enabled by default, showing call hierarchy with indentation:

@Logger()
def outer(x):
    return inner(x * 2)

@Logger()
def inner(y):
    return y + 10

outer(5)

Output:

Running outer
  x: 5
  Running inner
    y: 10
  Finished inner  Time elapsed: 0.08 ms
Finished outer  Time elapsed: 0.25 ms

Advanced Features

Log Levels

Control logging verbosity with log levels and color coding:

from logorator import Logger, LogLevel

@Logger(level=LogLevel.DEBUG)    # Cyan - detailed info
def debug_function():
    pass

@Logger(level=LogLevel.INFO)     # Green - general info (default)
def info_function():
    pass

@Logger(level=LogLevel.WARNING)  # Yellow - warnings
def warning_function():
    pass

@Logger(level=LogLevel.ERROR)    # Red - errors
def error_function():
    pass

# Set global minimum level
Logger.set_level(LogLevel.WARNING)  # Only WARNING and ERROR will show

Argument Filtering

Exclude sensitive or verbose arguments:

@Logger(exclude_args=["password", "token"])
def login(username, password, token):
    # password and token won't be logged
    pass

@Logger(exclude_args=["self"])  # Common for class methods
def process(self, data):
    pass

Include only specific arguments:

@Logger(include_args=["user_id", "action"])
def audit_log(user_id, action, timestamp, metadata, session):
    # Only user_id and action will be logged
    pass

Working with Classes

Logger works seamlessly with all types of class methods:

class DataProcessor:
    def __init__(self, name):
        self.name = name
    
    @Logger(exclude_args=["self"])  # Hide self for cleaner output
    def process(self, data):
        return self._transform(data)
    
    @Logger(exclude_args=["self"])
    def _transform(self, data):
        return [x * 2 for x in data]
    
    @classmethod
    @Logger()
    def create(cls, name):
        return cls(name)
    
    @staticmethod
    @Logger()
    def validate(value):
        return value > 0

Output:

Running process
  data: [1, 2, 3]
  Running _transform
    data: [1, 2, 3]
  Finished _transform  Time elapsed: 0.05 ms
Finished process  Time elapsed: 0.15 ms

Custom Object Formatting

Logger intelligently formats objects:

class User:
    def __init__(self, name):
        self.name = name
    
    # Without __str__: shows "User"
    # With __str__: shows your custom format
    def __str__(self):
        return f"User({self.name})"

@Logger()
def greet(user):
    return f"Hello, {user.name}"

greet(User("Alice"))

Output:

Running greet
  user: User(Alice)
Finished greet  Time elapsed: 0.08 ms

File Output

Redirect logs to a file (ANSI colors are automatically stripped):

Logger.set_output("logs/application.log")

@Logger()
def main():
    # All logs go to file
    pass

# Switch back to console
Logger.set_output(None)

Custom Notes

Insert custom log messages during execution:

@Logger()
def process_data(data):
    Logger.note("Starting validation")
    # validation logic
    Logger.note("Validation complete")
    return data

Short Mode

Compact tab-separated output:

@Logger(mode="short")
def calculate(a, b):
    return a + b

Disable Depth Tracking

@Logger(show_depth=False)
def flat_logging():
    pass

Custom Function Names

@Logger(override_function_name="DatabaseConnect")
async def connect_to_db(url):
    pass

Global Silent Mode

import os

# Disable all logging in production
if os.environ.get("ENVIRONMENT") == "production":
    Logger.set_silent(True)

API Reference

Logger Class

Constructor Parameters

Logger(
    silent=None,                    # Override global silent mode
    mode="normal",                  # "normal" or "short"
    override_function_name=None,    # Custom name in logs
    level=LogLevel.INFO,            # Log level (DEBUG, INFO, WARNING, ERROR)
    include_args=None,              # List of args to include
    exclude_args=None,              # List of args to exclude
    show_depth=True                 # Enable depth tracking (default: True)
)

Class Methods

Logger.set_silent(silent=True)

Enable or disable all logging globally.

Logger.set_level(level)

Set the minimum log level to display.

Logger.set_level(LogLevel.WARNING)  # Only WARNING and ERROR
Logger.set_output(filename=None)

Set output file path. Pass None to log to console.

Logger.set_output("logs/app.log")
Logger.note(note="", mode="normal")

Log a custom note.

Logger.note("Processing complete")
Logger.log(message="", end="")

Low-level logging method (rarely needed directly).

Async Support

Logger fully supports asyncio including concurrent execution:

@Logger()
async def process_item(item_id):
    await asyncio.sleep(0.1)
    return f"Processed {item_id}"

@Logger()
async def main():
    # Concurrent execution - logs are properly tracked
    results = await asyncio.gather(
        process_item(1),
        process_item(2),
        process_item(3)
    )

asyncio.run(main())

Best Practices

1. Use @Logger() for Most Cases

The defaults work great for most scenarios:

@Logger()
def my_function(x, y):
    pass

2. Exclude self in Instance Methods

@Logger(exclude_args=["self"])
def process(self, data):
    pass

3. Use Log Levels Appropriately

  • DEBUG: Detailed diagnostic information
  • INFO: General informational messages (default)
  • WARNING: Warning messages for important events
  • ERROR: Error messages for serious problems

4. Filter Sensitive Data

@Logger(exclude_args=["password", "api_key", "token", "secret"])
def authenticate(username, password, api_key):
    pass

5. Set Global Level in Production

# In production, only show warnings and errors
Logger.set_level(LogLevel.WARNING)

Combining with Other Decorators

Place @Logger() as the outermost (top) decorator:

@Logger()
@cache
@validate_input
def expensive_calculation(x):
    pass

Requirements

  • Python 3.7+
  • No external dependencies

License

MIT License

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Changelog

Version 2.0.0

  • Added log levels (DEBUG, INFO, WARNING, ERROR)
  • Added automatic depth tracking with indentation
  • Added smart argument formatting for objects
  • Added parameter name display for all arguments
  • Added argument filtering (include_args/exclude_args)
  • Improved async support with contextvars
  • Enhanced class method support

Version 1.0.0

  • Initial release
  • Basic decorator logging
  • Async function support
  • File output
  • ANSI color support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

logorator-2.0.2.tar.gz (9.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

logorator-2.0.2-py3-none-any.whl (7.3 kB view details)

Uploaded Python 3

File details

Details for the file logorator-2.0.2.tar.gz.

File metadata

  • Download URL: logorator-2.0.2.tar.gz
  • Upload date:
  • Size: 9.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for logorator-2.0.2.tar.gz
Algorithm Hash digest
SHA256 8d1a79b7372725ebe160b86f9fcc8271428d94ca8cbaf98c19c79500058a55b1
MD5 0a81467c95a79d05e96bd4e1c5594115
BLAKE2b-256 fe3b5884b1d6731f49e440fb232039ee21e921de8af08736a6db181cb0729378

See more details on using hashes here.

File details

Details for the file logorator-2.0.2-py3-none-any.whl.

File metadata

  • Download URL: logorator-2.0.2-py3-none-any.whl
  • Upload date:
  • Size: 7.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.2

File hashes

Hashes for logorator-2.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1ee9fe8ecc899277e865c0cabf03b388a871ea5b8d4d88bc9c75b0db4f4dc567
MD5 7578d7b2190838189040f0297acd6934
BLAKE2b-256 385c935435a6aa1b325bcf2e7a82cb3babeee0cc2e4977285f795aae1893dcc4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page