pytrackio 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Deepanshu (danshu3007-lang)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -0,0 +1,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytrackio
3
+ Version: 0.1.0
4
+ Summary: Zero-dependency Python performance tracker. Decorate, time, count — then report.
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/danshu3007-lang/pytrackio
7
+ Project-URL: Repository, https://github.com/danshu3007-lang/pytrackio
8
+ Project-URL: Bug Tracker, https://github.com/danshu3007-lang/pytrackio/issues
9
+ Keywords: metrics,performance,tracking,profiling,monitoring,decorator,timer,benchmarking
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Classifier: Topic :: System :: Monitoring
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: license-file
24
+
25
+ # pytrackio
26
+
27
+ > Zero-dependency Python performance tracker. Decorate, time, count — then report.
28
+
29
+ [![Tests](https://github.com/danshu3007-lang/pytrackio/actions/workflows/tests.yml/badge.svg)](https://github.com/danshu3007-lang/pytrackio/actions)
30
+ [![PyPI version](https://img.shields.io/pypi/v/pytrackio?style=flat-square&color=blue)](https://pypi.org/project/pytrackio/)
31
+ [![Python](https://img.shields.io/badge/Python-3.10+-blue?style=flat-square&logo=python)](https://www.python.org/)
32
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE)
33
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen?style=flat-square)](pyproject.toml)
34
+
35
+ ```python
36
+ from pytrackio import track, timer, counter, report
37
+
38
+ @track
39
+ def fetch_user(user_id: int):
40
+ ... # your existing code, unchanged
41
+
42
+ with timer("database_query"):
43
+ results = db.execute(query)
44
+
45
+ counter("api_calls").increment()
46
+
47
+ report()
48
+ ```
49
+
50
+ ```
51
+ ╔════════════════════════════════════════════════════════════════════════╗
52
+ ║ pytrackio — Performance Report ║
53
+ ║ uptime: 4.21s ║
54
+ ╠════════════════════════════════════════════════════════════════════════╣
55
+ ║ Function / Block Calls Avg (ms) Min(ms) Max (ms) Errors ║
56
+ ╠════════════════════════════════════════════════════════════════════════╣
57
+ ║ fetch_user 42 120.34 98.10 310.50 — ║
58
+ ║ database_query 18 45.20 40.10 89.30 — ║
59
+ ╠════════════════════════════════════════════════════════════════════════╣
60
+ ║ Counters ║
61
+ ╠────────────────────────────────────────────────────────────────────────╣
62
+ ║ api_calls: 42 ║
63
+ ╚════════════════════════════════════════════════════════════════════════╝
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Why pytrackio?
69
+
70
+ Every other Python metrics tool requires Prometheus, StatsD, Grafana, or some external server. Setting them up takes hours.
71
+
72
+ **pytrackio works in 30 seconds:**
73
+ - ✅ Zero dependencies — pure Python stdlib only
74
+ - ✅ Zero configuration — no config files, no servers
75
+ - ✅ Zero changes to your logic — just add one decorator
76
+ - ✅ Thread-safe — works in concurrent applications
77
+ - ✅ Production-ready — proper error tracking, not just happy-path
78
+
79
+ ---
80
+
81
+ ## Installation
82
+
83
+ ```bash
84
+ pip install pytrackio
85
+ ```
86
+
87
+ ---
88
+
89
+ ## Usage
90
+
91
+ ### Track a function automatically
92
+
93
+ ```python
94
+ from pytrackio import track
95
+
96
+ @track
97
+ def process_order(order_id: int):
98
+ # your code here — nothing else changes
99
+ ...
100
+
101
+ # Call it normally
102
+ process_order(123)
103
+ process_order(456)
104
+ ```
105
+
106
+ ### Custom metric name
107
+
108
+ ```python
109
+ @track(name="payment_gateway")
110
+ def charge_card(amount: float):
111
+ ...
112
+ ```
113
+
114
+ ### Time any block of code
115
+
116
+ ```python
117
+ from pytrackio import timer
118
+
119
+ with timer("image_resize"):
120
+ resized = resize_image(img, width=800)
121
+
122
+ with timer("send_email"):
123
+ mailer.send(to=user.email, body=html)
124
+ ```
125
+
126
+ ### Count events
127
+
128
+ ```python
129
+ from pytrackio import counter
130
+
131
+ counter("cache_hits").increment()
132
+ counter("cache_misses").increment()
133
+ counter("retries").increment(3) # increment by N
134
+ counter("queue_size").decrement() # decrement
135
+
136
+ # Read the value anywhere
137
+ print(counter("cache_hits").value)
138
+ ```
139
+
140
+ ### Print the report
141
+
142
+ ```python
143
+ from pytrackio import report
144
+
145
+ report() # print to stdout
146
+ report(show_counters=False) # hide counters section
147
+ ```
148
+
149
+ ### Access raw data programmatically
150
+
151
+ ```python
152
+ from pytrackio import get_registry
153
+
154
+ registry = get_registry()
155
+
156
+ # Get summary for one metric
157
+ s = registry.summary("payment_gateway")
158
+ print(s.calls, s.avg_ms, s.error_rate)
159
+
160
+ # Get all summaries
161
+ for s in registry.all_summaries():
162
+ if s.error_rate > 5.0:
163
+ alert(f"{s.name} has {s.error_rate}% errors!")
164
+
165
+ # Reset between test runs
166
+ registry.reset()
167
+ ```
168
+
169
+ ---
170
+
171
+ ## Real-world example
172
+
173
+ ```python
174
+ from pytrackio import track, timer, counter, report
175
+ import requests as http
176
+
177
+ @track
178
+ def get_weather(city: str) -> dict:
179
+ r = http.get(f"https://api.example.com/weather?city={city}", timeout=5)
180
+ r.raise_for_status()
181
+ counter("api_calls").increment()
182
+ return r.json()
183
+
184
+ @track
185
+ def process_weather(data: dict) -> str:
186
+ with timer("format_output"):
187
+ return f"{data['city']}: {data['temp']}°C"
188
+
189
+ # Run your app...
190
+ for city in ["Delhi", "London", "Tokyo"]:
191
+ data = get_weather(city)
192
+ print(process_weather(data))
193
+
194
+ # See how everything performed
195
+ report()
196
+ ```
197
+
198
+ ---
199
+
200
+ ## API Reference
201
+
202
+ ### `@track`
203
+
204
+ ```python
205
+ @track
206
+ def my_func(): ...
207
+
208
+ @track(name="custom_name")
209
+ def my_func(): ...
210
+ ```
211
+
212
+ Tracks: call count, duration (min/max/avg), errors and error rate.
213
+ Never swallows exceptions — your original errors always propagate.
214
+
215
+ ---
216
+
217
+ ### `timer(name)`
218
+
219
+ ```python
220
+ with timer("block_name"):
221
+ ...
222
+ ```
223
+
224
+ Context manager. Records duration and any exceptions raised inside the block.
225
+
226
+ ---
227
+
228
+ ### `counter(name)`
229
+
230
+ ```python
231
+ counter("name").increment() # +1
232
+ counter("name").increment(n) # +n
233
+ counter("name").decrement() # -1
234
+ counter("name").reset() # → 0
235
+ counter("name").value # read current value
236
+ ```
237
+
238
+ ---
239
+
240
+ ### `report(stream, colour, show_counters)`
241
+
242
+ ```python
243
+ report()
244
+ report(show_counters=False)
245
+ report(colour=False) # force plain text
246
+ ```
247
+
248
+ Prints to stdout and returns the output as a string.
249
+
250
+ ---
251
+
252
+ ### `get_registry()`
253
+
254
+ Returns the global `MetricsRegistry` instance for programmatic access.
255
+
256
+ ```python
257
+ registry = get_registry()
258
+ registry.all_summaries() # List[MetricSummary]
259
+ registry.all_counters() # List[CounterState]
260
+ registry.summary("name") # Optional[MetricSummary]
261
+ registry.reset() # clear everything
262
+ registry.uptime_seconds() # float
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Contributing
268
+
269
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).
270
+
271
+ **Ideas for contributions:**
272
+ - Async support (`@track` for `async def` functions)
273
+ - Export to JSON / CSV
274
+ - Histogram bucketing
275
+ - `@track` for class methods
276
+ - Minimum call threshold filter in report
277
+
278
+ ---
279
+
280
+ ## Built by
281
+
282
+ **Deepanshu** — BCA Student at Chandigarh University, aspiring Data Analyst.
283
+
284
+ ---
285
+
286
+ ## License
287
+
288
+ [MIT](LICENSE)
@@ -0,0 +1,264 @@
1
+ # pytrackio
2
+
3
+ > Zero-dependency Python performance tracker. Decorate, time, count — then report.
4
+
5
+ [![Tests](https://github.com/danshu3007-lang/pytrackio/actions/workflows/tests.yml/badge.svg)](https://github.com/danshu3007-lang/pytrackio/actions)
6
+ [![PyPI version](https://img.shields.io/pypi/v/pytrackio?style=flat-square&color=blue)](https://pypi.org/project/pytrackio/)
7
+ [![Python](https://img.shields.io/badge/Python-3.10+-blue?style=flat-square&logo=python)](https://www.python.org/)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE)
9
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-zero-brightgreen?style=flat-square)](pyproject.toml)
10
+
11
+ ```python
12
+ from pytrackio import track, timer, counter, report
13
+
14
+ @track
15
+ def fetch_user(user_id: int):
16
+ ... # your existing code, unchanged
17
+
18
+ with timer("database_query"):
19
+ results = db.execute(query)
20
+
21
+ counter("api_calls").increment()
22
+
23
+ report()
24
+ ```
25
+
26
+ ```
27
+ ╔════════════════════════════════════════════════════════════════════════╗
28
+ ║ pytrackio — Performance Report ║
29
+ ║ uptime: 4.21s ║
30
+ ╠════════════════════════════════════════════════════════════════════════╣
31
+ ║ Function / Block Calls Avg (ms) Min(ms) Max (ms) Errors ║
32
+ ╠════════════════════════════════════════════════════════════════════════╣
33
+ ║ fetch_user 42 120.34 98.10 310.50 — ║
34
+ ║ database_query 18 45.20 40.10 89.30 — ║
35
+ ╠════════════════════════════════════════════════════════════════════════╣
36
+ ║ Counters ║
37
+ ╠────────────────────────────────────────────────────────────────────────╣
38
+ ║ api_calls: 42 ║
39
+ ╚════════════════════════════════════════════════════════════════════════╝
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Why pytrackio?
45
+
46
+ Every other Python metrics tool requires Prometheus, StatsD, Grafana, or some external server. Setting them up takes hours.
47
+
48
+ **pytrackio works in 30 seconds:**
49
+ - ✅ Zero dependencies — pure Python stdlib only
50
+ - ✅ Zero configuration — no config files, no servers
51
+ - ✅ Zero changes to your logic — just add one decorator
52
+ - ✅ Thread-safe — works in concurrent applications
53
+ - ✅ Production-ready — proper error tracking, not just happy-path
54
+
55
+ ---
56
+
57
+ ## Installation
58
+
59
+ ```bash
60
+ pip install pytrackio
61
+ ```
62
+
63
+ ---
64
+
65
+ ## Usage
66
+
67
+ ### Track a function automatically
68
+
69
+ ```python
70
+ from pytrackio import track
71
+
72
+ @track
73
+ def process_order(order_id: int):
74
+ # your code here — nothing else changes
75
+ ...
76
+
77
+ # Call it normally
78
+ process_order(123)
79
+ process_order(456)
80
+ ```
81
+
82
+ ### Custom metric name
83
+
84
+ ```python
85
+ @track(name="payment_gateway")
86
+ def charge_card(amount: float):
87
+ ...
88
+ ```
89
+
90
+ ### Time any block of code
91
+
92
+ ```python
93
+ from pytrackio import timer
94
+
95
+ with timer("image_resize"):
96
+ resized = resize_image(img, width=800)
97
+
98
+ with timer("send_email"):
99
+ mailer.send(to=user.email, body=html)
100
+ ```
101
+
102
+ ### Count events
103
+
104
+ ```python
105
+ from pytrackio import counter
106
+
107
+ counter("cache_hits").increment()
108
+ counter("cache_misses").increment()
109
+ counter("retries").increment(3) # increment by N
110
+ counter("queue_size").decrement() # decrement
111
+
112
+ # Read the value anywhere
113
+ print(counter("cache_hits").value)
114
+ ```
115
+
116
+ ### Print the report
117
+
118
+ ```python
119
+ from pytrackio import report
120
+
121
+ report() # print to stdout
122
+ report(show_counters=False) # hide counters section
123
+ ```
124
+
125
+ ### Access raw data programmatically
126
+
127
+ ```python
128
+ from pytrackio import get_registry
129
+
130
+ registry = get_registry()
131
+
132
+ # Get summary for one metric
133
+ s = registry.summary("payment_gateway")
134
+ print(s.calls, s.avg_ms, s.error_rate)
135
+
136
+ # Get all summaries
137
+ for s in registry.all_summaries():
138
+ if s.error_rate > 5.0:
139
+ alert(f"{s.name} has {s.error_rate}% errors!")
140
+
141
+ # Reset between test runs
142
+ registry.reset()
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Real-world example
148
+
149
+ ```python
150
+ from pytrackio import track, timer, counter, report
151
+ import requests as http
152
+
153
+ @track
154
+ def get_weather(city: str) -> dict:
155
+ r = http.get(f"https://api.example.com/weather?city={city}", timeout=5)
156
+ r.raise_for_status()
157
+ counter("api_calls").increment()
158
+ return r.json()
159
+
160
+ @track
161
+ def process_weather(data: dict) -> str:
162
+ with timer("format_output"):
163
+ return f"{data['city']}: {data['temp']}°C"
164
+
165
+ # Run your app...
166
+ for city in ["Delhi", "London", "Tokyo"]:
167
+ data = get_weather(city)
168
+ print(process_weather(data))
169
+
170
+ # See how everything performed
171
+ report()
172
+ ```
173
+
174
+ ---
175
+
176
+ ## API Reference
177
+
178
+ ### `@track`
179
+
180
+ ```python
181
+ @track
182
+ def my_func(): ...
183
+
184
+ @track(name="custom_name")
185
+ def my_func(): ...
186
+ ```
187
+
188
+ Tracks: call count, duration (min/max/avg), errors and error rate.
189
+ Never swallows exceptions — your original errors always propagate.
190
+
191
+ ---
192
+
193
+ ### `timer(name)`
194
+
195
+ ```python
196
+ with timer("block_name"):
197
+ ...
198
+ ```
199
+
200
+ Context manager. Records duration and any exceptions raised inside the block.
201
+
202
+ ---
203
+
204
+ ### `counter(name)`
205
+
206
+ ```python
207
+ counter("name").increment() # +1
208
+ counter("name").increment(n) # +n
209
+ counter("name").decrement() # -1
210
+ counter("name").reset() # → 0
211
+ counter("name").value # read current value
212
+ ```
213
+
214
+ ---
215
+
216
+ ### `report(stream, colour, show_counters)`
217
+
218
+ ```python
219
+ report()
220
+ report(show_counters=False)
221
+ report(colour=False) # force plain text
222
+ ```
223
+
224
+ Prints to stdout and returns the output as a string.
225
+
226
+ ---
227
+
228
+ ### `get_registry()`
229
+
230
+ Returns the global `MetricsRegistry` instance for programmatic access.
231
+
232
+ ```python
233
+ registry = get_registry()
234
+ registry.all_summaries() # List[MetricSummary]
235
+ registry.all_counters() # List[CounterState]
236
+ registry.summary("name") # Optional[MetricSummary]
237
+ registry.reset() # clear everything
238
+ registry.uptime_seconds() # float
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Contributing
244
+
245
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).
246
+
247
+ **Ideas for contributions:**
248
+ - Async support (`@track` for `async def` functions)
249
+ - Export to JSON / CSV
250
+ - Histogram bucketing
251
+ - `@track` for class methods
252
+ - Minimum call threshold filter in report
253
+
254
+ ---
255
+
256
+ ## Built by
257
+
258
+ **Deepanshu** — BCA Student at Chandigarh University, aspiring Data Analyst.
259
+
260
+ ---
261
+
262
+ ## License
263
+
264
+ [MIT](LICENSE)
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pytrackio"
7
+ version = "0.1.0"
8
+ description = "Zero-dependency Python performance tracker. Decorate, time, count — then report."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.10"
12
+ dependencies = []
13
+
14
+ keywords = [
15
+ "metrics", "performance", "tracking", "profiling",
16
+ "monitoring", "decorator", "timer", "benchmarking"
17
+ ]
18
+
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.10",
25
+ "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ "Topic :: System :: Monitoring",
29
+ "Typing :: Typed",
30
+ ]
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/danshu3007-lang/pytrackio"
34
+ Repository = "https://github.com/danshu3007-lang/pytrackio"
35
+ "Bug Tracker" = "https://github.com/danshu3007-lang/pytrackio/issues"
36
+
37
+ [tool.setuptools.packages.find]
38
+ where = ["."]
39
+ include = ["pytrackio*"]
40
+
41
+ [tool.pytest.ini_options]
42
+ testpaths = ["tests"]
@@ -0,0 +1,24 @@
1
+ """
2
+ pytrackio
3
+ =========
4
+ Zero-dependency Python performance tracker.
5
+
6
+ from pytrackio import track, timer, counter, report
7
+
8
+ @track
9
+ def my_function(): ...
10
+
11
+ with timer("block"): do_something()
12
+
13
+ counter("events").increment()
14
+ report()
15
+ """
16
+ from ._instruments import counter, timer, track
17
+ from ._report import report
18
+ from ._tracker import MetricSummary, get_registry
19
+
20
+ __version__ = "0.1.0"
21
+ __author__ = "Deepanshu"
22
+ __license__ = "MIT"
23
+
24
+ __all__ = ["track","timer","counter","report","get_registry","MetricSummary","__version__"]
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+ import functools, time
3
+ from contextlib import contextmanager
4
+ from typing import Any, Callable, Generator, Optional, TypeVar
5
+ from ._tracker import CounterState, get_registry
6
+
7
+ F = TypeVar("F", bound=Callable[..., Any])
8
+
9
+ def track(func=None, *, name=None):
10
+ """Decorator: track calls, duration and errors for any function.
11
+
12
+ Usage::
13
+
14
+ @track
15
+ def my_func(): ...
16
+
17
+ @track(name="custom")
18
+ def my_func(): ...
19
+ """
20
+ if func is None:
21
+ def decorator(f): return _wrap(f, name)
22
+ return decorator
23
+ return _wrap(func, name)
24
+
25
+ def _wrap(func, custom_name):
26
+ metric_name = custom_name or f"{func.__module__}.{func.__qualname__}"
27
+ registry = get_registry()
28
+ @functools.wraps(func)
29
+ def wrapper(*args, **kwargs):
30
+ start = time.perf_counter()
31
+ try:
32
+ result = func(*args, **kwargs)
33
+ registry.record(metric_name, (time.perf_counter()-start)*1000, True)
34
+ return result
35
+ except Exception as exc:
36
+ registry.record(metric_name, (time.perf_counter()-start)*1000, False, type(exc).__name__)
37
+ raise
38
+ return wrapper
39
+
40
+ @contextmanager
41
+ def timer(name: str) -> Generator[None, None, None]:
42
+ """Context manager: track duration of any code block.
43
+
44
+ Usage::
45
+
46
+ with timer("db_query"):
47
+ results = db.execute(query)
48
+ """
49
+ registry = get_registry()
50
+ start = time.perf_counter()
51
+ try:
52
+ yield
53
+ registry.record(name, (time.perf_counter()-start)*1000, True)
54
+ except Exception as exc:
55
+ registry.record(name, (time.perf_counter()-start)*1000, False, type(exc).__name__)
56
+ raise
57
+
58
+ def counter(name: str) -> CounterState:
59
+ """Get a named counter (created on first access).
60
+
61
+ Usage::
62
+
63
+ counter("hits").increment()
64
+ counter("hits").value
65
+ """
66
+ return get_registry().get_counter(name)