Skip to content

Commit 156939b

Browse files
authored
Merge pull request #10 from faucetsdn/v0.17.0
Upgrade python3-prometheus-client to v0.17.0.
2 parents a024d98 + a6ede9f commit 156939b

6 files changed

Lines changed: 70 additions & 18 deletions

File tree

MANIFEST.in

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1-
recursive-include tests *
2-
prune tests/__pycache__
1+
graft tests
2+
global-exclude *.py[cod]
3+
prune __pycache__
4+
prune */__pycache__

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,55 @@ uwsgi --http 127.0.0.1:8000 --wsgi-file myapp.py --callable app
416416

417417
Visit http://localhost:8000/metrics to see the metrics
418418

419+
#### FastAPI + Gunicorn
420+
421+
To use Prometheus with [FastAPI](https://fastapi.tiangolo.com/) and [Gunicorn](https://gunicorn.org/) we need to serve metrics through a Prometheus ASGI application.
422+
423+
Save the snippet below in a `myapp.py` file
424+
425+
```python
426+
from fastapi import FastAPI
427+
from prometheus_client import make_asgi_app
428+
429+
# Create app
430+
app = FastAPI(debug=False)
431+
432+
# Add prometheus asgi middleware to route /metrics requests
433+
metrics_app = make_asgi_app()
434+
app.mount("/metrics", metrics_app)
435+
```
436+
437+
For Multiprocessing support, use this modified code snippet. Full multiprocessing intstructions are provided [here](https://github.com/prometheus/client_python#multiprocess-mode-eg-gunicorn).
438+
439+
```python
440+
from fastapi import FastAPI
441+
from prometheus_client import make_asgi_app
442+
443+
app = FastAPI(debug=False)
444+
445+
# Using multiprocess collector for registry
446+
def make_metrics_app():
447+
registry = CollectorRegistry()
448+
multiprocess.MultiProcessCollector(registry)
449+
return make_asgi_app(registry=registry)
450+
451+
452+
metrics_app = make_metrics_app()
453+
app.mount("/metrics", metrics_app)
454+
```
455+
456+
Run the example web application like this
457+
458+
```bash
459+
# Install gunicorn if you do not have it
460+
pip install gunicorn
461+
# If using multiple workers, add `--workers n` parameter to the line below
462+
gunicorn -b 127.0.0.1:8000 myapp:app -k uvicorn.workers.UvicornWorker
463+
```
464+
465+
Visit http://localhost:8000/metrics to see the metrics
466+
467+
419468
### Node exporter textfile collector
420469

421470
The [textfile collector](https://github.com/prometheus/node_exporter#textfile-collector)

prometheus_client/context_managers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def __enter__(self):
4646
def __exit__(self, typ, value, traceback):
4747
self._gauge.dec()
4848

49-
def __call__(self, f):
49+
def __call__(self, f: "F") -> "F":
5050
def wrapped(func, *args, **kwargs):
5151
with self:
5252
return func(*args, **kwargs)
@@ -75,7 +75,7 @@ def __exit__(self, typ, value, traceback):
7575
def labels(self, *args, **kw):
7676
self._metric = self._metric.labels(*args, **kw)
7777

78-
def __call__(self, f):
78+
def __call__(self, f: "F") -> "F":
7979
def wrapped(func, *args, **kwargs):
8080
# Obtaining new instance of timer every time
8181
# ensures thread safety and reentrancy.

prometheus_client/gc_collector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def collect(self) -> Iterable[Metric]:
2222
)
2323
uncollectable = CounterMetricFamily(
2424
'python_gc_objects_uncollectable',
25-
'Uncollectable object found during GC',
25+
'Uncollectable objects found during GC',
2626
labels=['generation'],
2727
)
2828

prometheus_client/parser.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import io as StringIO
22
import re
3+
from typing import Dict, Iterable, List, Match, Optional, TextIO, Tuple
34

45
from .metrics_core import Metric
56
from .samples import Sample
67

78

8-
def text_string_to_metric_families(text):
9+
def text_string_to_metric_families(text: str) -> Iterable[Metric]:
910
"""Parse Prometheus text format from a unicode string.
1011
1112
See text_fd_to_metric_families.
@@ -20,32 +21,32 @@ def text_string_to_metric_families(text):
2021
}
2122

2223

23-
def replace_escape_sequence(match):
24+
def replace_escape_sequence(match: Match[str]) -> str:
2425
return ESCAPE_SEQUENCES[match.group(0)]
2526

2627

2728
HELP_ESCAPING_RE = re.compile(r'\\[\\n]')
2829
ESCAPING_RE = re.compile(r'\\[\\n"]')
2930

3031

31-
def _replace_help_escaping(s):
32+
def _replace_help_escaping(s: str) -> str:
3233
return HELP_ESCAPING_RE.sub(replace_escape_sequence, s)
3334

3435

35-
def _replace_escaping(s):
36+
def _replace_escaping(s: str) -> str:
3637
return ESCAPING_RE.sub(replace_escape_sequence, s)
3738

3839

39-
def _is_character_escaped(s, charpos):
40+
def _is_character_escaped(s: str, charpos: int) -> bool:
4041
num_bslashes = 0
4142
while (charpos > num_bslashes
4243
and s[charpos - 1 - num_bslashes] == '\\'):
4344
num_bslashes += 1
4445
return num_bslashes % 2 == 1
4546

4647

47-
def _parse_labels(labels_string):
48-
labels = {}
48+
def _parse_labels(labels_string: str) -> Dict[str, str]:
49+
labels: Dict[str, str] = {}
4950
# Return if we don't have valid labels
5051
if "=" not in labels_string:
5152
return labels
@@ -95,7 +96,7 @@ def _parse_labels(labels_string):
9596

9697

9798
# If we have multiple values only consider the first
98-
def _parse_value_and_timestamp(s):
99+
def _parse_value_and_timestamp(s: str) -> Tuple[float, Optional[float]]:
99100
s = s.lstrip()
100101
separator = " "
101102
if separator not in s:
@@ -108,7 +109,7 @@ def _parse_value_and_timestamp(s):
108109
return value, timestamp
109110

110111

111-
def _parse_sample(text):
112+
def _parse_sample(text: str) -> Sample:
112113
# Detect the labels in the text
113114
try:
114115
label_start, label_end = text.index("{"), text.rindex("}")
@@ -133,7 +134,7 @@ def _parse_sample(text):
133134
return Sample(name, {}, value, timestamp)
134135

135136

136-
def text_fd_to_metric_families(fd):
137+
def text_fd_to_metric_families(fd: TextIO) -> Iterable[Metric]:
137138
"""Parse Prometheus text format from a file descriptor.
138139
139140
This is a laxer parser than the main Go parser,
@@ -145,10 +146,10 @@ def text_fd_to_metric_families(fd):
145146
name = ''
146147
documentation = ''
147148
typ = 'untyped'
148-
samples = []
149+
samples: List[Sample] = []
149150
allowed_names = []
150151

151-
def build_metric(name, documentation, typ, samples):
152+
def build_metric(name: str, documentation: str, typ: str, samples: List[Sample]) -> Metric:
152153
# Munge counters into OpenMetrics representation
153154
# used internally.
154155
if typ == 'counter':

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setup(
1010
name="prometheus_client",
11-
version="0.16.0",
11+
version="0.17.0",
1212
author="Brian Brazil",
1313
author_email="brian.brazil@robustperception.io",
1414
description="Python client for the Prometheus monitoring system.",

0 commit comments

Comments
 (0)