# statman
[![Python package](https://github.com/jasonray/statman-stopwatch.py/actions/workflows/python-package.yml/badge.svg)](https://github.com/jasonray/statman-stopwatch.py/actions/workflows/python-package.yml)
[![PyPI version](https://badge.fury.io/py/statman.svg)](https://badge.fury.io/py/statman)
[![Known Vulnerabilities](https://snyk.io/test/github/jasonray/statman.py/badge.svg)](https://snyk.io/test/github/jasonray/statman.py)
# Overview
Statman is a collection of metric collectors to embed within your python application. It includes a registry to easily access your metrics.
`Statman` => registry
`Metric` => set of classes that can perform metric collection
`Stopwatch` => a metric class responsible for tracking time delta
`Gauge` => a metric class responsible for providing a single value
`Calculation` => a metric class responsible for performing calculations
`Rate` => a specialized calculation metric which calculates x/y rate
# Install it!
Statman is availble from [pypi](https://pypi.org/project/statman/).
It can be manually installed by:
```
pip install statman
```
or by adding the following to your `requirements.txt`:
```
statman=*
```
# Use it
## Statman (Registry)
`Statman` offers a registery to make it easily to globally access metrics. Perhaps you will create and register a stopwatch in the depths of your codebase to measure the time to write to a database, and then want to access that result in some other part of your application.
### Register
* `register(name, metric)` => manually register a new metric
### Get
* `get(name)` => get a metric by name
### Count
* `count()` => returns a count of the registered metrics.
### Reset
* `reset()` => clears all metrics from the registry.
### Specialized register / get
* `stopwatch(name)` => returns a stopwatch instance. If there is a registered stopwatch with this name, return it. If there is no registered stopwatch with this name, create a new instance, register it, and return it.
## Stopwatch
`Stopwatch` is for timing operations within your system. Suppose that you are trying to track down where the system is slow. Put a stopwatch around certain critical areas, time those operations, and compare.
### Constructor
* `Stopwatch(name=None, autostart=False, initial_delta=None)` => create an instance of a stopwatch.
* If `autostart` set to true, the stopwatch will automatically start
* If `initial_delta` is set to a value, and `read` of the stopwatch is incremented by this amount. This can be helpful if you adding timings together.
* `name` is used for to string / reporting for identification of this metric. Defaults to blank
* If `enable_history` is set to true, when a timing is collected (`stop` invoked), an event is collected. This can be accessed by the `history` property to examing statistics on this stopwatch
### Start
* `start()` => starts the stopwatch, let the timing begin!
### Read
* `read(units, precision)` => reads the stopwatch to determine how much time has elapsed. Returns the time elapsed in seconds.
* The elapsed time will be returned based upon the `units` ('m' minutes, 's' seconds, 'ms', milliseconds). Defaults to seconds.
* If precision is provided, `read()` will round to the number of decimals places based on precision.
* Note: `read` does NOT stop the stopwatch - if the stopwatch is runnning, it will continues to run.
* `time(units, precision)` => alias for `read()`
### Stop
* `stop(units, precision)` => stops the stopwatch, and returns the time elapsed in seconds
* See read for the role of `units` and `precision`
### Reset
* `reset()` => restores the stopwatch back to init state and clears start and stop times
### Restart
* `restart()` => `reset`s the stopwatch, then `start`s it
### History
* `history` => if `enable_history` set during stopwatch construction, the `history` property returns an instance of a history object, which can be used for examing statistics
## Gauge
A gauge is an instantaneous measurement of a value. Suppose that you are interested in counting the number of messages that have been processed. A gauge can be used to count events and produce a value.
### Constructor
* `Gauge(name=None, value: float = 0)` => create an instance of a gauge
* If `value` is provided, this will be used as the initial value of the gauge
### Value
* `value()` => get / set the current value of the gauge
### Increment / Decrement
* `increment(amount: int = 1)` => adds to the current value
* `decrement(amount: int = 1)` => subtracts from the current value
## Calculation
### Constructor
* `Calculation(name=None, function=None)` => creates a new instance of a calculation metric
#### Function
* `function` => set the function used the calculation.
* The function is to be a parameterless function that returns a numeric value.
* The function can internally reference other items, such as other Statman metrics or access to other resources.
* The function can be a named or lambda function.
#### Value / Read
* `read(precision: int = None)` => execute the function, and returns the value rounded based on specified precision
* `value(self)` => execute the function, and returns the value
## Rate
### Constructor
* `Rate(name=None, numerator_metric_name=None, denominator_metric_name=None)` => creates a new instance of a rate metric
* The `Rate` metric extends the `Calculation` metric, where the function is numerator/denominator
* The `numerator_metric_name` and `denominator_metric_name` refer to other metrics within the Statman registry
## Examples
### Maually Register Metric
``` python
from statman import Statman
Statman.register('expensive-operation-timing',Stopwatch())
stopwatch = Statman.get('expensive-operation-timing')
```
### Stopwatch via Statman Registry
``` python
from statman import Statman
Statman.stopwatch('stopwatch-name').start()
# do some expensive operation that you want to measure
Statman.stopwatch('stopwatch-name').read()
print(f'event took {Statman.stopwatch('stopwatch-name').read(precision=1)}s to execute') # event took 1.0s to execute
```
### Stopwatch: Direct Usage (no registry)
``` python
from statman import Stopwatch
sw = Stopwatch()
sw.start()
# do some expensive operation that you want to measure
delta = sw.stop()
print(f'event took {sw.read(precision=1)}s to execute') # event took 1.0s to execute
```
### Stopwatch: History
``` python
from statman import Stopwatch
number_of_events = 1000000
sw = Stopwatch(enable_history=True)
for i in range(0, number_of_events):
sw.start()
# do some expensive operation that you want to measure
sw.stop()
print('number of measurements:', sw.history.count())
print('min:', sw.history.min_value())
print('max:', sw.history.max_value())
print('ave:', sw.history.average_value())
print('mode:', sw.history.mode_value())
```
### Gauge using increment via Statman Registry
``` python
from statman import Statman
Statman.gauge('number-of-messages-processed')
# in area where something interesting occurs, update gauge
# update can occur using .increment() or .value=
Statman.gauge('number-of-messages_processed').increment()
print('number-of-messages_processed:', Statman.gauge('number-of-messages_processed').value)
```
### Calculation via Statman Registry
``` python
from statman import Statman
Statman.calculation('messages-per-second').function = lambda: (Statman.gauge('messages-processed').value / Statman.stopwatch('sw').value)
Statman.stopwatch('time-to-process-batch').start()
# code to process batch, incrementing each time message is handles
Statman.gauge('messages-processed').increment()
Statman.stopwatch('sw').stop()
print(Statman.calculation('messages-per-second').value)
```
### Rate via Statman Registry
``` python
from statman import Statman
Statman.stopwatch('sw').start()
time.sleep(0.5)
Statman.stopwatch('sw').stop()
Statman.gauge('messages_processed').value = 100
Statman.rate(name='messages_per_second', numerator_metric_name='messages_processed', denominator_metric_name='sw')
print(Statman.rate('messages_per_second').value)
```
Raw data
{
"_id": null,
"home_page": "",
"name": "statman",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": "",
"keywords": "stats,metrics,stopwatch,timing,performance,monitoring",
"author": "Mighty Pulpo",
"author_email": "jayray.net@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/8a/59/a4afde30631a20a63c1e2e1d757b5d8825e0abc634df0640c9d86c9ce3f1/statman-1.4.6.tar.gz",
"platform": null,
"description": "# statman\n\n[![Python package](https://github.com/jasonray/statman-stopwatch.py/actions/workflows/python-package.yml/badge.svg)](https://github.com/jasonray/statman-stopwatch.py/actions/workflows/python-package.yml)\n[![PyPI version](https://badge.fury.io/py/statman.svg)](https://badge.fury.io/py/statman)\n[![Known Vulnerabilities](https://snyk.io/test/github/jasonray/statman.py/badge.svg)](https://snyk.io/test/github/jasonray/statman.py)\n\n# Overview\n\nStatman is a collection of metric collectors to embed within your python application. It includes a registry to easily access your metrics.\n\n`Statman` => registry \n`Metric` => set of classes that can perform metric collection \n`Stopwatch` => a metric class responsible for tracking time delta \n`Gauge` => a metric class responsible for providing a single value \n`Calculation` => a metric class responsible for performing calculations \n`Rate` => a specialized calculation metric which calculates x/y rate\n\n# Install it!\n\nStatman is availble from [pypi](https://pypi.org/project/statman/).\n\nIt can be manually installed by:\n```\npip install statman\n```\n\nor by adding the following to your `requirements.txt`:\n```\nstatman=*\n```\n\n# Use it\n\n## Statman (Registry)\n\n`Statman` offers a registery to make it easily to globally access metrics. Perhaps you will create and register a stopwatch in the depths of your codebase to measure the time to write to a database, and then want to access that result in some other part of your application.\n\n### Register\n* `register(name, metric)` => manually register a new metric\n\n### Get\n* `get(name)` => get a metric by name\n\n### Count\n* `count()` => returns a count of the registered metrics.\n\n### Reset\n* `reset()` => clears all metrics from the registry.\n\n### Specialized register / get\n* `stopwatch(name)` => returns a stopwatch instance. If there is a registered stopwatch with this name, return it. If there is no registered stopwatch with this name, create a new instance, register it, and return it.\n\n## Stopwatch\n\n`Stopwatch` is for timing operations within your system. Suppose that you are trying to track down where the system is slow. Put a stopwatch around certain critical areas, time those operations, and compare.\n\n### Constructor\n* `Stopwatch(name=None, autostart=False, initial_delta=None)` => create an instance of a stopwatch.\n * If `autostart` set to true, the stopwatch will automatically start\n * If `initial_delta` is set to a value, and `read` of the stopwatch is incremented by this amount. This can be helpful if you adding timings together.\n * `name` is used for to string / reporting for identification of this metric. Defaults to blank\n * If `enable_history` is set to true, when a timing is collected (`stop` invoked), an event is collected. This can be accessed by the `history` property to examing statistics on this stopwatch\n \n### Start\n* `start()` => starts the stopwatch, let the timing begin!\n\n### Read\n* `read(units, precision)` => reads the stopwatch to determine how much time has elapsed. Returns the time elapsed in seconds.\n * The elapsed time will be returned based upon the `units` ('m' minutes, 's' seconds, 'ms', milliseconds). Defaults to seconds.\n * If precision is provided, `read()` will round to the number of decimals places based on precision.\n * Note: `read` does NOT stop the stopwatch - if the stopwatch is runnning, it will continues to run.\n* `time(units, precision)` => alias for `read()`\n\n### Stop\n* `stop(units, precision)` => stops the stopwatch, and returns the time elapsed in seconds\n * See read for the role of `units` and `precision`\n\n### Reset\n* `reset()` => restores the stopwatch back to init state and clears start and stop times\n\n### Restart\n* `restart()` => `reset`s the stopwatch, then `start`s it\n\n### History\n* `history` => if `enable_history` set during stopwatch construction, the `history` property returns an instance of a history object, which can be used for examing statistics\n\n## Gauge\n\nA gauge is an instantaneous measurement of a value. Suppose that you are interested in counting the number of messages that have been processed. A gauge can be used to count events and produce a value.\n\n### Constructor\n* `Gauge(name=None, value: float = 0)` => create an instance of a gauge\n * If `value` is provided, this will be used as the initial value of the gauge\n\n### Value\n* `value()` => get / set the current value of the gauge\n\n### Increment / Decrement\n* `increment(amount: int = 1)` => adds to the current value\n* `decrement(amount: int = 1)` => subtracts from the current value\n\n## Calculation\n\n### Constructor\n* `Calculation(name=None, function=None)` => creates a new instance of a calculation metric\n\n#### Function\n* `function` => set the function used the calculation.\n * The function is to be a parameterless function that returns a numeric value. \n * The function can internally reference other items, such as other Statman metrics or access to other resources. \n * The function can be a named or lambda function.\n\n#### Value / Read\n* `read(precision: int = None)` => execute the function, and returns the value rounded based on specified precision\n* `value(self)` => execute the function, and returns the value\n\n## Rate\n\n### Constructor\n* `Rate(name=None, numerator_metric_name=None, denominator_metric_name=None)` => creates a new instance of a rate metric\n * The `Rate` metric extends the `Calculation` metric, where the function is numerator/denominator\n * The `numerator_metric_name` and `denominator_metric_name` refer to other metrics within the Statman registry\n\n## Examples\n\n### Maually Register Metric\n``` python\nfrom statman import Statman\nStatman.register('expensive-operation-timing',Stopwatch())\n\nstopwatch = Statman.get('expensive-operation-timing')\n```\n\n### Stopwatch via Statman Registry\n``` python\nfrom statman import Statman\n\nStatman.stopwatch('stopwatch-name').start()\n# do some expensive operation that you want to measure\nStatman.stopwatch('stopwatch-name').read()\n\nprint(f'event took {Statman.stopwatch('stopwatch-name').read(precision=1)}s to execute') # event took 1.0s to execute\n```\n\n### Stopwatch: Direct Usage (no registry)\n``` python\nfrom statman import Stopwatch\nsw = Stopwatch()\nsw.start()\n\n# do some expensive operation that you want to measure\n\ndelta = sw.stop()\nprint(f'event took {sw.read(precision=1)}s to execute') # event took 1.0s to execute\n```\n\n### Stopwatch: History\n``` python\nfrom statman import Stopwatch\nnumber_of_events = 1000000\n\nsw = Stopwatch(enable_history=True)\nfor i in range(0, number_of_events):\n sw.start()\n # do some expensive operation that you want to measure\n sw.stop()\n\nprint('number of measurements:', sw.history.count())\nprint('min:', sw.history.min_value())\nprint('max:', sw.history.max_value())\nprint('ave:', sw.history.average_value())\nprint('mode:', sw.history.mode_value())\n```\n\n### Gauge using increment via Statman Registry\n``` python\nfrom statman import Statman\nStatman.gauge('number-of-messages-processed')\n\n# in area where something interesting occurs, update gauge\n# update can occur using .increment() or .value=\nStatman.gauge('number-of-messages_processed').increment()\n\nprint('number-of-messages_processed:', Statman.gauge('number-of-messages_processed').value)\n```\n\n### Calculation via Statman Registry\n``` python\nfrom statman import Statman\n\nStatman.calculation('messages-per-second').function = lambda: (Statman.gauge('messages-processed').value / Statman.stopwatch('sw').value)\nStatman.stopwatch('time-to-process-batch').start()\n\n# code to process batch, incrementing each time message is handles\nStatman.gauge('messages-processed').increment()\n\nStatman.stopwatch('sw').stop()\n\nprint(Statman.calculation('messages-per-second').value)\n```\n\n### Rate via Statman Registry\n``` python\nfrom statman import Statman\n\nStatman.stopwatch('sw').start()\ntime.sleep(0.5)\nStatman.stopwatch('sw').stop()\n\nStatman.gauge('messages_processed').value = 100\n\nStatman.rate(name='messages_per_second', numerator_metric_name='messages_processed', denominator_metric_name='sw')\nprint(Statman.rate('messages_per_second').value)\n```\n",
"bugtrack_url": null,
"license": "",
"summary": "Collection of metrics collection tools, including a simple stopwatch",
"version": "1.4.6",
"project_urls": null,
"split_keywords": [
"stats",
"metrics",
"stopwatch",
"timing",
"performance",
"monitoring"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2e4eaac87f2f43a6494d170cee6e4e9d7ec20822d0773db603b6654b3a9a9fe4",
"md5": "7954080858b6d15dc400abd023162d07",
"sha256": "a692f908c884051439d8133cf6939bb5f555752fe2ee3308c46bb5dc8dad732f"
},
"downloads": -1,
"filename": "statman-1.4.6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7954080858b6d15dc400abd023162d07",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 10135,
"upload_time": "2024-01-29T18:10:56",
"upload_time_iso_8601": "2024-01-29T18:10:56.564205Z",
"url": "https://files.pythonhosted.org/packages/2e/4e/aac87f2f43a6494d170cee6e4e9d7ec20822d0773db603b6654b3a9a9fe4/statman-1.4.6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8a59a4afde30631a20a63c1e2e1d757b5d8825e0abc634df0640c9d86c9ce3f1",
"md5": "8238b8b0ba43ea619f4fa54544558d0d",
"sha256": "99f476118a0c98445f7be4bb1ed13e8e40c53b93d528f60fc44502c831b054ce"
},
"downloads": -1,
"filename": "statman-1.4.6.tar.gz",
"has_sig": false,
"md5_digest": "8238b8b0ba43ea619f4fa54544558d0d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 10958,
"upload_time": "2024-01-29T18:10:57",
"upload_time_iso_8601": "2024-01-29T18:10:57.701998Z",
"url": "https://files.pythonhosted.org/packages/8a/59/a4afde30631a20a63c1e2e1d757b5d8825e0abc634df0640c9d86c9ce3f1/statman-1.4.6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-29 18:10:57",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "statman"
}