Skip to main content

A lightweight, flexible performance tracking library for Python applications

Project description

✨ Tim The Enchanter ✨

A lightweight, flexible performance tracking library for Python applications. Easily measure and analyze execution times of your functions, code blocks, and processes.

Features

  • Zero dependencies - Just Python standard library
  • Minimal overhead - Designed to be lightweight
  • Request-scoped instances - Each request gets its own isolated tracker
  • Multiple reporting formats - Chronological, by-process, and aggregated statistics
  • Flexible configuration - Enable/disable via arguments or environment variables
  • Method chaining - Fluent interface for concise code
  • Context managers & decorators - Multiple ways to instrument your code
  • Support for async functions - Works with asyncio
  • Metadata support - Add context to your timing events
  • Concurrent safety - No shared state between requests

Example output

=====  Tim The Enchanter Performance Report  ingest_docs_de2a5e7e-70c1-4f9b-861c-d9a431e3cb24_20250314_094609 =====
Format: aggregate

Process Name                             |  Count   |  Total (s)   |   Avg (s)    |   Min (s)    |   Max (s)    |  Median (s)  |  StdDev (s)
-----------------------------------------------------------------------------------------------------------------------------------------------
get_context_docs                         |    1     |     8.510816 |     8.510816 |     8.510816 |     8.510816 |     8.510816 |     0.000000
summarize_chunk                          |    2     |     2.506251 |     1.253125 |     0.879834 |     1.626417 |     1.253125 |     0.527914
process_all_documents                    |    1     |     2.379968 |     2.379968 |     2.379968 |     2.379968 |     2.379968 |     0.000000
db_add_document                          |    2     |     2.231350 |     1.115675 |     0.747726 |     1.483624 |     1.115675 |     0.520359
split_document                           |    1     |     0.000170 |     0.000170 |     0.000170 |     0.000170 |     0.000170 |     0.000000

================================================================================

Installation

pip install tim-the-enchanter

Basic Usage

from tim_the_enchanter import TimTheEnchanter, TimTheEnchanterReportFormat

# Create a new tracker instance (request-scoped)
tracker = TimTheEnchanter.create(enabled=True)

# Start a session and get the session ID
session_id = tracker.start_session("my_api_request")
# or auto-generate a unique ID:
# session_id = tracker.start_session()

# Track a block of code
with tracker.time_process(session_id, "data_processing"):
    # Your code here
    process_data()

# Track a function with a decorator
@tracker.time_function(session_id)
def calculate_results():
    # Function code
    pass

# Track an async function
@tracker.time_async_function(session_id)
async def fetch_data():
    # Async function code
    pass

# Manual tracking
start_time = time.time()
# ... do something ...
duration = time.time() - start_time
tracker.record(session_id, "manual_operation", duration)

# Generate reports
tracker.print_report(session_id, TimTheEnchanterReportFormat.CHRONOLOGICAL)  # Time-ordered events
tracker.print_report(session_id, TimTheEnchanterReportFormat.BY_PROCESS)     # Grouped by process name
tracker.print_report(session_id, TimTheEnchanterReportFormat.AGGREGATE)      # Statistical summary

# End the session
tracker.end_session(session_id)

Configuration Options

There are multiple ways to configure the performance tracker:

1. Factory Method (Recommended)

# Simple way to create and configure in one step
tracker = TimTheEnchanter.create(enabled=not is_production)

2. Direct Configuration

# Create a new instance and configure it
tracker = TimTheEnchanter().configure(enabled=True, reset_sessions=False)

Method Chaining

The tracker supports a fluent interface for concise code:

# Chain multiple operations
tracker = TimTheEnchanter().configure(enabled=True)
session_id = tracker.start_session("api_request")
tracker.record(session_id, "initialization", 0.05)
tracker.print_report(session_id, TimTheEnchanterReportFormat.CHRONOLOGICAL)
tracker.end_session(session_id)

Runtime Toggling

You can enable or disable tracking at runtime:

# Disable during specific operations
tracker.disable()
compute_expensive_operation()  # Not tracked
tracker.enable()

Session Management

# Create and manage multiple sessions
session1 = tracker.start_session("session1")
# ... operations ...
tracker.end_session(session1)

session2 = tracker.start_session("session2")
# ... more operations ...
tracker.print_report(session2, format=TimTheEnchanterReportFormat.AGGREGATE)
tracker.end_session(session2)

# List all active sessions
active_sessions = tracker.list_sessions()

# Delete a session when done
tracker.delete_session(session1)

Multiple Request Isolation

Each request can have its own isolated tracker instance:

# In a web application, each request gets its own tracker
async def handle_request(request_id: int):
    tracker = TimTheEnchanter.create(enabled=True)
    session_id = tracker.start_session(f"request_{request_id}")
    
    # Each request's operations are isolated
    with tracker.time_process(session_id, "request_processing"):
        # Process the request
        pass
    
    # Generate request-specific report
    report = tracker.report(session_id, TimTheEnchanterReportFormat.AGGREGATE)
    
    tracker.end_session(session_id)
    return report

Metadata Support

# Add contextual information to timing events
with tracker.time_process(session_id, "database_query", metadata={"table": "users", "filters": {"active": True}}):
    # Your code here
    pass

Performance Considerations

The tracker is designed to be lightweight, but for production environments, you may want to disable it:

# In your application startup code
is_production = os.environ.get("ENV") == "production"
tracker = TimTheEnchanter.create(enabled=not is_production)

When disabled, all tracking operations become no-ops with minimal overhead.

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

tim_the_enchanter-1.0.0.tar.gz (15.9 kB view details)

Uploaded Source

Built Distribution

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

tim_the_enchanter-1.0.0-py3-none-any.whl (9.5 kB view details)

Uploaded Python 3

File details

Details for the file tim_the_enchanter-1.0.0.tar.gz.

File metadata

  • Download URL: tim_the_enchanter-1.0.0.tar.gz
  • Upload date:
  • Size: 15.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for tim_the_enchanter-1.0.0.tar.gz
Algorithm Hash digest
SHA256 f63d12ef7523d36bfa46e07184f5622b696d8f1d528ae9349a16796d38e09e70
MD5 e8a8960a15d19952caa089affcec1f05
BLAKE2b-256 ce39e4efb76a9078e99fe2848ce8b01d5e8cd4abd4339ae7ee8f42d00535c492

See more details on using hashes here.

File details

Details for the file tim_the_enchanter-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for tim_the_enchanter-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a8b33aba27747024a81b60ce764930480985d710cb1f6ef75fb55d1cd20bb6f0
MD5 698c31685136f7ee264059f4ba4e3655
BLAKE2b-256 3aa9cc7fe6c1f68c74f33f8d126790763c916ef2877d3e7d6de48af5671c6182

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