Skip to main content

Function-level CPU and Memory monitoring with visual terminal output

Project description

๐Ÿ“Š taskmon - Function-Level Performance Monitoring

Simple, powerful Python function monitoring with beautiful terminal output.

Track CPU, memory, and performance of any Python function with a simple decorator. Perfect for finding memory leaks, bottlenecks, and understanding your code's resource usage.

โœจ Features

  • ๐ŸŽฏ Function-level tracking - Monitor any function with a simple @monitor() decorator
  • ๐Ÿ“Š Real-time metrics - CPU, memory, execution time, and throughput
  • ๐ŸŽจ Beautiful output - Color-coded, visual terminal display
  • ๐Ÿ” Memory leak detection - Automatic detection of memory growth
  • ๐Ÿ“ˆ Nested function support - Track call hierarchies with visual indentation
  • ๐Ÿš€ Zero configuration - Works out of the box
  • ๐Ÿ“ Aggregated statistics - See summaries across all function calls
  • ๐Ÿงต Thread-safe - Works with multi-threaded applications

๐Ÿš€ Quick Start

Installation

pip install taskmon

Or install from source:

git clone https://github.com/kadirtutenn/taskmon
cd taskmon
pip install -e .

Basic Usage

from taskmon import monitor

@monitor()
def process_data(items):
    result = []
    for item in items:
        result.append(item * 2)
    return result

# Call your function normally
data = process_data([1, 2, 3, 4, 5])

Output:

โ”Œโ”€ ๐Ÿš€ process_data() started [call_1_1738574400123]
โ”‚  ๐Ÿ“Š Baseline: CPU 2.3% | MEM 156.2MB | THR 4
  โ””โ”€ โœ… process_data() completed in 0.02s
     ๐Ÿ“Š CPU: 3.1% [โ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] | MEM: ๐ŸŸข +0.8MB (peak: 157.0MB)
     โšก Processed: 5 items (250.0 items/s)

๐Ÿ“š Usage Examples

1. Monitor Any Function

from taskmon import monitor

@monitor()
def calculate_fibonacci(n):
    if n <= 1:
        return n
    return calculate_fibonacci(n-1) + calculate_fibonacci(n-2)

result = calculate_fibonacci(10)

2. Track Code Sections

from taskmon import monitor, track

@monitor()
def data_pipeline():
    with track("load_data"):
        data = load_from_database()
    
    with track("process"):
        processed = process_data(data)
    
    with track("save"):
        save_to_database(processed)

data_pipeline()

Output shows nested structure:

โ”Œโ”€ ๐Ÿš€ data_pipeline() started
โ”‚  ๐Ÿ“Š Baseline: CPU 2.1% | MEM 145.3MB | THR 4
  โ”œโ”€ ๐Ÿš€ load_data started
  โ”‚  ๐Ÿ“Š Baseline: CPU 2.3% | MEM 145.5MB | THR 4
    โ””โ”€ โœ… load_data completed in 1.23s
       ๐Ÿ“Š CPU: 15.2% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘] | MEM: ๐ŸŸข +12.3MB (peak: 157.8MB)
  
  โ”œโ”€ ๐Ÿš€ process started
  โ”‚  ๐Ÿ“Š Baseline: CPU 3.1% | MEM 157.8MB | THR 4
    โ””โ”€ โœ… process completed in 2.45s
       ๐Ÿ“Š CPU: 45.6% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘] | MEM: ๐ŸŸก +45.2MB (peak: 203.0MB)
  
  โ””โ”€ โœ… data_pipeline() completed in 3.89s
     ๐Ÿ“Š CPU: 21.3% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘] | MEM: ๐ŸŸข +9.1MB (peak: 203.0MB)

3. Track Items Processed

from taskmon import monitor

@monitor()
def process_batch(items):
    results = []
    for item in items:
        results.append(transform_item(item))
    return results

# Automatically tracks len(results)
items = ["item1", "item2", "item3"]
process_batch(items)

Output:

โ””โ”€ โœ… process_batch() completed in 5.23s
   ๐Ÿ“Š CPU: 12.3% [โ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘] | MEM: ๐ŸŸข +2.1MB (peak: 158.4MB)
   โšก Processed: 3 items (0.6 items/s)

4. View Statistics

from taskmon import monitor, print_summary

@monitor()
def expensive_function(n):
    time.sleep(n)
    return n * 2

# Call multiple times
for i in range(5):
    expensive_function(i)

# Print summary
print_summary()

Output:

================================================================================
๐Ÿ“Š FUNCTION MONITORING SUMMARY
================================================================================

Function                                    Calls   Total Time   Avg Time   Failures
--------------------------------------------------------------------------------
__main__.expensive_function                     5       10.00s      2.000s      0 (0.0%)

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

5. Find Memory Leaks

from taskmon import monitor

@monitor()
def potential_leak():
    data = []
    for i in range(1000000):
        data.append(i)
    # Oops, forgot to clean up!
    return len(data)

potential_leak()

Output (notice the ๐Ÿ”ด red indicator):

โ””โ”€ โœ… potential_leak() completed in 0.15s
   ๐Ÿ“Š CPU: 85.2% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘] | MEM: ๐Ÿ”ด +156.3MB (peak: 312.5MB)
   โšก Processed: 1,000,000 items (6666666.7 items/s)

6. Real-World Example: Space Mission Data Pipeline

from taskmon import monitor, track

@monitor()
def plan_mission_data_collection():
    with track("Load Configuration"):
        satellites = get_satellite_config_cached()
    
    with track("Count Signals"):
        total_signals = get_total_signal_count()
    
    # Process in chunks
    chunk_size = 50000
    for offset in range(0, total_signals, chunk_size):
        with track(f"Process Chunk {offset//chunk_size + 1}"):
            process_signal_chunk(offset, chunk_size, satellites)

plan_mission_data_collection()

Output shows where memory leaks occur:

โ”Œโ”€ ๐Ÿš€ plan_mission_data_collection() started
  โ”œโ”€ ๐Ÿš€ Load Configuration started
    โ””โ”€ โœ… Load Configuration completed in 0.05s
       ๐Ÿ“Š CPU: 2.1% | MEM: ๐ŸŸข +1.2MB
  
  โ”œโ”€ ๐Ÿš€ Count Signals started
    โ””โ”€ โœ… Count Signals completed in 0.23s
       ๐Ÿ“Š CPU: 5.3% | MEM: ๐ŸŸข +0.1MB
  
  โ”œโ”€ ๐Ÿš€ Process Chunk 1 started
    โ””โ”€ โœ… Process Chunk 1 completed in 12.34s
       ๐Ÿ“Š CPU: 45.2% | MEM: ๐ŸŸข +2.3MB
  
  โ”œโ”€ ๐Ÿš€ Process Chunk 2 started
    โ””โ”€ โœ… Process Chunk 2 completed in 11.89s
       ๐Ÿ“Š CPU: 43.1% | MEM: ๐Ÿ”ด +125.6MB  <-- Memory leak here!
  
  โ””โ”€ โœ… plan_mission_data_collection() completed in 45.67s
     ๐Ÿ“Š CPU: 38.5% | MEM: ๐Ÿ”ด +128.4MB

๐ŸŽจ Visual Indicators

Status Icons

  • ๐Ÿš€ Function started
  • โœ… Successfully completed
  • โŒ Failed with error
  • โš ๏ธ Warning

Memory Status

  • ๐ŸŸข Green: < 10MB change (normal)
  • ๐ŸŸก Yellow: 10-100MB change (monitor)
  • ๐Ÿ”ด Red: > 100MB change (memory leak!)

CPU Bars

CPU: 15.2% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘]  <- Visual bar
CPU: 45.6% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘]
CPU: 85.2% [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘]

๐Ÿ“Š API Reference

@monitor(items_attr=None, print_summary=False)

Decorator to monitor function performance.

Parameters:

  • items_attr (str, optional): Attribute name to track as items_processed
  • print_summary (bool): Print summary after function completes

Example:

@monitor(items_attr='count', print_summary=True)
def process_data():
    return {"count": 100, "data": [...]}

track(section_name, items=0)

Context manager for monitoring code sections.

Parameters:

  • section_name (str): Name of the section
  • items (int): Number of items processed

Example:

with track("database_query", items=100):
    results = db.query(...)

get_stats(function_name=None)

Get function statistics.

Parameters:

  • function_name (str, optional): Specific function name, or None for all

Returns: Dict with statistics

Example:

stats = get_stats("my_module.my_function")
print(f"Total calls: {stats['total_calls']}")
print(f"Avg CPU: {stats['avg_cpu']:.1f}%")

print_summary()

Print summary of all monitored functions.

clear_stats()

Clear all statistics.

get_active_calls()

Get list of currently active function calls.

Returns: List of FunctionMetrics objects

๐Ÿ”ง Advanced Usage

Custom Items Tracking

@monitor()
def process_batch(items):
    count = 0
    for item in items:
        process(item)
        count += 1
    return count  # Automatically tracked

Nested Function Monitoring

@monitor()
def parent_function():
    child_function_1()
    child_function_2()

@monitor()
def child_function_1():
    pass

@monitor()
def child_function_2():
    pass

Output shows hierarchy:

โ”Œโ”€ ๐Ÿš€ parent_function() started
  โ”œโ”€ ๐Ÿš€ child_function_1() started
    โ””โ”€ โœ… child_function_1() completed
  โ”œโ”€ ๐Ÿš€ child_function_2() started
    โ””โ”€ โœ… child_function_2() completed
  โ””โ”€ โœ… parent_function() completed

Integration with Celery

from celery import shared_task
from taskmon import monitor

@shared_task
@monitor()
def celery_task(data):
    process(data)

Programmatic Access

from taskmon import get_active_calls, get_stats

# Get currently running functions
active = get_active_calls()
for call in active:
    print(f"{call.function_name}: {call.memory_delta_mb:.1f}MB")

# Get historical stats
stats = get_stats()
for func_name, metrics in stats.items():
    if metrics['avg_cpu'] > 50:
        print(f"High CPU function: {func_name}")

๐ŸŽฏ Use Cases

1. Find Memory Leaks

@monitor()
def suspect_function():
    # Your code
    pass

Look for ๐Ÿ”ด indicators showing large memory growth.

2. Identify Bottlenecks

@monitor()
def pipeline():
    with track("step1"):
        slow_step()
    with track("step2"):
        fast_step()

See which sections take the most time.

3. Optimize Batch Processing

@monitor()
def process_chunks():
    for chunk in chunks:
        with track(f"chunk_{i}"):
            process(chunk)

Identify which chunks are slow or leak memory.

4. Monitor Production Code

@monitor()
def critical_api_endpoint():
    # Monitor in production
    pass

Track performance metrics over time.

๐Ÿ“ˆ Performance Overhead

taskmon is designed to be lightweight:

  • CPU overhead: < 1% in most cases
  • Memory overhead: < 1MB
  • Sampling: Background thread samples every 1 second
  • Thread-safe: Safe for multi-threaded applications

๐Ÿ› Troubleshooting

Output not showing colors?

Set your terminal to support ANSI colors:

export TERM=xterm-256color

Too much output?

Disable monitoring for specific functions:

# Just remove the decorator
def my_function():
    pass

Want quieter output?

The library respects standard output - redirect if needed:

import sys
sys.stdout = open('monitor.log', 'w')

๐Ÿค Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Submit a pull request

๐Ÿ“ License

MIT License - see LICENSE file for details.

๐Ÿ™ Acknowledgments

Built with:

  • psutil - Process and system utilities

๐Ÿ“ž Support


Made with โค๏ธ for Python developers who care about performance

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

taskmon-0.1.0.tar.gz (38.8 kB view details)

Uploaded Source

Built Distribution

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

taskmon-0.1.0-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file taskmon-0.1.0.tar.gz.

File metadata

  • Download URL: taskmon-0.1.0.tar.gz
  • Upload date:
  • Size: 38.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.17

File hashes

Hashes for taskmon-0.1.0.tar.gz
Algorithm Hash digest
SHA256 024420eeccd077278248d58a637a01339f0c61a4b9a772a1a8386ee0eb2ff6c7
MD5 deed58f4dfaf89fac3ef6cd0ff1b06c3
BLAKE2b-256 0b46d07dd1029b2d31700c00a71386632df4682d095c473ccaf0113aebdebde3

See more details on using hashes here.

File details

Details for the file taskmon-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: taskmon-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.17

File hashes

Hashes for taskmon-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0f3020e09bc182913cc53ac37c184082a7b61b4927982162c9fd36c3c4d3553b
MD5 9939a191a5c1e29201ffcd744001497e
BLAKE2b-256 b83a43c94f2a1091d334effd192c85316ce72740c5427574557e8eec139eeb50

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