A simple, efficient timer for monitoring execution time and logging threshold violations
Project description
Timer Sentinel
A dead-simple, fast, and lightweight Python timer for catching slow code. Zero dependencies, optimized performance, just pure Python doing one thing well.
Why?
I built this after spending too much time debugging inconsistent latency in complex systems. Sometimes a function that should take 100ms randomly takes 5 seconds, and you need to know when and where.
This timer helped me catch those issues. Works great with Grafana + Loki for analyzing logs and creating alerts, or use the callback for whatever custom logic you need.
What it does
- ⏱️ Times your code with high precision
- 📊 Logs when it's too slow
- 🔔 Runs callbacks when thresholds are exceeded
- 🎯 Works as decorator, context manager, or manual timer
- 🔀 Supports async functions
- 🚀 Fast - optimized with
__slots__, minimal overhead - 🪶 Lightweight - zero dependencies, tiny footprint
- ⚡ Efficient - uses
time.perf_counter()for microsecond precision
Install
pip install timer-sentinel
Usage
from timer_sentinel import TimerSentinel
# Context manager
with TimerSentinel(threshold=1.0, name="db_query"):
slow_database_call()
# Decorator
@TimerSentinel(threshold=0.5)
def api_call():
return requests.get(url)
# Async
@TimerSentinel(threshold=0.5)
async def async_operation():
await some_io()
Real-world Examples
Catch slow database queries
@TimerSentinel(threshold=0.1, name="db_query")
def get_user(user_id):
return db.query(f"SELECT * FROM users WHERE id={user_id}")
Integration with Grafana + Loki
Just log to your standard logger and ship logs to Loki:
import logging
logger = logging.getLogger("production")
with TimerSentinel(threshold=1.0, logger=logger, name="api_call"):
call_external_api()
Create alerts in Grafana based on the "OVERTIME" keyword or parse execution times. Good for catching performance regressions in production.
API
TimerSentinel(
threshold: float, # Max time in seconds
name: str = "", # Timer name (uses function name if decorator)
logger: Logger | None = None, # Custom logger
on_exceed_keyword: str = "OVERTIME", # Log keyword
on_exceed_level: int = WARNING, # Log level
on_exceed_callback: Callable = None, # Callback function (sync or async)
callback_args: dict = None, # Args for callback
)
Callback:
- The
on_exceed_callbackcan be a synchronous or asynchronous function. If you provide an async function, it will be awaited automatically.
Methods:
start()- Start timingend()- Stop timingreport()- Log if threshold exceeded
Use as:
- Decorator:
@TimerSentinel(...) - Context manager:
with TimerSentinel(...) - Manual:
timer.start()→timer.end()→timer.report()
Requirements
- Python 3.10+
- No external dependencies
Contributing
Found a bug? Want a feature? Open an issue or PR on GitHub.
License
MIT License - do whatever you want with it.
Author
Aaron Ojeda · GitHub
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file timer_sentinel-1.0.3.tar.gz.
File metadata
- Download URL: timer_sentinel-1.0.3.tar.gz
- Upload date:
- Size: 5.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4115a8b9694c23191367c7ad9c266e2c60cc7d6ca05918ccdd7e7e6791afe66
|
|
| MD5 |
6cc6c5cd323b57d55cf6c3195d5add8f
|
|
| BLAKE2b-256 |
c1cbbc13b44bb720a0e09629abeb9bcc1818cee3cf0a51672978265c060b0c77
|
Provenance
The following attestation bundles were made for timer_sentinel-1.0.3.tar.gz:
Publisher:
publish-pypi.yml on aaronojedait/timer-sentinel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
timer_sentinel-1.0.3.tar.gz -
Subject digest:
f4115a8b9694c23191367c7ad9c266e2c60cc7d6ca05918ccdd7e7e6791afe66 - Sigstore transparency entry: 958029594
- Sigstore integration time:
-
Permalink:
aaronojedait/timer-sentinel@988d70331f520aecde2aa57ca3cf5610b0ecac6e -
Branch / Tag:
refs/tags/v1.0.3 - Owner: https://github.com/aaronojedait
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@988d70331f520aecde2aa57ca3cf5610b0ecac6e -
Trigger Event:
push
-
Statement type:
File details
Details for the file timer_sentinel-1.0.3-py3-none-any.whl.
File metadata
- Download URL: timer_sentinel-1.0.3-py3-none-any.whl
- Upload date:
- Size: 6.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75186802b4281a7d848a096c9897b33c94b52ff24bd11d16ae87de49b5766fbb
|
|
| MD5 |
3e0ed688f28e3428a8ed7eef0885f8e9
|
|
| BLAKE2b-256 |
42c8105b16baca623f9d3eae8ff6a2b66a8cd517b0d625bdb590ff1a08acde78
|
Provenance
The following attestation bundles were made for timer_sentinel-1.0.3-py3-none-any.whl:
Publisher:
publish-pypi.yml on aaronojedait/timer-sentinel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
timer_sentinel-1.0.3-py3-none-any.whl -
Subject digest:
75186802b4281a7d848a096c9897b33c94b52ff24bd11d16ae87de49b5766fbb - Sigstore transparency entry: 958029627
- Sigstore integration time:
-
Permalink:
aaronojedait/timer-sentinel@988d70331f520aecde2aa57ca3cf5610b0ecac6e -
Branch / Tag:
refs/tags/v1.0.3 - Owner: https://github.com/aaronojedait
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@988d70331f520aecde2aa57ca3cf5610b0ecac6e -
Trigger Event:
push
-
Statement type: