Skip to content

Commit 17f9b94

Browse files
committed
Add initial summary implementation
1 parent abddf66 commit 17f9b94

File tree

12 files changed

+209
-2
lines changed

12 files changed

+209
-2
lines changed

.github/workflows/publish.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Upload package ty PYPI
2+
3+
on:
4+
release:
5+
types: [created]
6+
7+
jobs:
8+
publish:
9+
runs-on: ubuntu-latest
10+
timeout-minutes: 10
11+
environment: production
12+
13+
steps:
14+
- name: Check out repository code
15+
uses: actions/checkout@v3
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: '3.x'
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install setuptools wheel twine
26+
27+
- name: Build and publish
28+
env:
29+
TWINE_USERNAME: '__token__'
30+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
31+
run: |
32+
python setup.py sdist bdist_wheel
33+
twine upload dist/*

.github/workflows/tests.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: tests
2+
on: [push]
3+
4+
jobs:
5+
tests:
6+
runs-on: ubuntu-latest
7+
timeout-minutes: 10
8+
strategy:
9+
matrix:
10+
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
11+
12+
steps:
13+
- name: Checkout repository code
14+
uses: actions/checkout@v3
15+
16+
- name: Set up Python ${{ matrix.python-version }}
17+
uses: actions/setup-python@v4
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
21+
- name: Install dependencies
22+
run: |
23+
python -m pip install --upgrade pip setuptools
24+
pip install -r requirements/dev.txt
25+
pip install -r requirements/test.txt
26+
27+
- name: Tests with pytest
28+
run: pytest

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,6 @@ cython_debug/
157157
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158158
# and can be added to the global gitignore or merged into this file. For a more nuclear
159159
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
160-
#.idea/
160+
.idea/
161+
162+
.DS_Store

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# prometheus-summary
2-
Prometheus summary with quantiles
2+
Prometheus summary with quantiles over configurable sliding time window

prometheus_summary/__init__.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from typing import Iterable, Sequence, Optional, Tuple
2+
3+
import prometheus_client
4+
from prometheus_client.samples import Sample
5+
from quantile_estimator import TimeWindowEstimator
6+
7+
from .version import __version__
8+
9+
10+
class Summary(prometheus_client.Summary):
11+
# pairs of (quantile, allowed error)
12+
DEFAULT_INVARIANTS = ((0.50, 0.05), (0.90, 0.01), (0.99, 0.001))
13+
14+
def __init__(
15+
self,
16+
name: str,
17+
documentation: str,
18+
labelnames: Iterable[str] = (),
19+
namespace: str = '',
20+
subsystem: str = '',
21+
unit: str = '',
22+
registry: Optional[prometheus_client.CollectorRegistry] = prometheus_client.REGISTRY,
23+
_labelvalues: Optional[Sequence[str]] = None,
24+
invariants: Sequence[Tuple[float, float]] = DEFAULT_INVARIANTS,
25+
max_age_seconds: int = 10 * 60,
26+
age_buckets: int = 5,
27+
) -> None:
28+
self._invariants = invariants
29+
self._max_age_seconds = max_age_seconds
30+
self._age_buckets = age_buckets
31+
super().__init__(
32+
name,
33+
documentation,
34+
labelnames=labelnames,
35+
namespace=namespace,
36+
subsystem=subsystem,
37+
unit=unit,
38+
registry=registry,
39+
_labelvalues=_labelvalues,
40+
)
41+
42+
def _metric_init(self):
43+
super()._metric_init()
44+
self._estimator = TimeWindowEstimator(
45+
*self._invariants,
46+
max_age_seconds=self._max_age_seconds,
47+
age_buckets=self._age_buckets,
48+
)
49+
50+
def observe(self, amount):
51+
super().observe(amount)
52+
self._estimator.observe(amount)
53+
54+
def _child_samples(self):
55+
default_samples = super()._child_samples()
56+
quantile_samples = tuple(
57+
Sample("", {"quantile": str(quantile)}, self._estimator.query(quantile), None, None)
58+
for quantile, _ in self._invariants
59+
)
60+
return *default_samples, *quantile_samples

prometheus_summary/version.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
__version__ = "0.0.1"

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
testpaths = tests

requirements/dev.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
prometheus_client>=0.11.0
2+
quantile-estimator>=0.1.0

requirements/test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest

setup.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pathlib
2+
import setuptools
3+
from importlib.machinery import SourceFileLoader
4+
5+
version = SourceFileLoader("version", "prometheus_summary/version.py").load_module()
6+
7+
8+
def readfile(filename) -> str:
9+
return pathlib.Path(filename).read_text("utf-8").strip()
10+
11+
12+
setuptools.setup(
13+
name="prometheus-summary",
14+
version=version.__version__,
15+
author="RefaceAI",
16+
author_email="github-support@reface.ai",
17+
description="Prometheus summary with quantiles over configurable sliding time window",
18+
long_description=readfile("README.md"),
19+
long_description_content_type="text/markdown",
20+
license="Apache License 2.0",
21+
url="https://github.com/RefaceAI/prometheus-summary",
22+
packages=["prometheus_summary"],
23+
install_requires=[
24+
"prometheus_client>=0.11.0",
25+
"quantile-estimator>=0.1.0",
26+
],
27+
platforms="Platform Independent",
28+
classifiers=[
29+
"Development Status :: 3 - Alpha",
30+
"Intended Audience :: Developers",
31+
"License :: OSI Approved :: Apache Software License",
32+
"Operating System :: OS Independent",
33+
"Topic :: Scientific/Engineering :: Mathematics",
34+
],
35+
)

0 commit comments

Comments
 (0)