Skip to content

Commit 9f8812e

Browse files
committed
http fixes, pushgateway client
1 parent 73abc55 commit 9f8812e

File tree

6 files changed

+73
-20
lines changed

6 files changed

+73
-20
lines changed

prometheus_push_client/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
statsd_udp_aiostream,
1414
influx_udp_stream,
1515
statsd_udp_stream,
16+
openmetrics_http_async,
17+
openmetrics_http_thread,
1618
)
1719
from .formats.influx import InfluxFormat
1820
from .formats.statsd import StatsdFormat

prometheus_push_client/decorators.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ def influx_udp_thread(host, port, period=15.0, registry=ppc.PUSH_REGISTRY):
2121
return _sync_wrap(client)
2222

2323

24-
def influx_http_async(url, period=15.0, registry=ppc.PUSH_REGISTRY):
24+
def influx_http_async(url, verb="POST", period=15.0, registry=ppc.PUSH_REGISTRY):
2525
client = ppc.AsyncBatchClient(
2626
format=ppc.InfluxFormat(registry=registry),
27-
transport=ppc.AioHttpTransport(url),
27+
transport=ppc.AioHttpTransport(url, verb),
2828
period=period,
2929
)
3030
return _async_wrap(client)
3131

3232

33-
def influx_http_thread(url, period=15.0, registry=ppc.PUSH_REGISTRY):
33+
def influx_http_thread(url, verb="POST", period=15.0, registry=ppc.PUSH_REGISTRY):
3434
client = ppc.ThreadBatchClient(
3535
format=ppc.InfluxFormat(registry=registry),
36-
transport=ppc.SyncHttpTransport(url),
36+
transport=ppc.SyncHttpTransport(url, verb),
3737
period=period,
3838
)
3939
return _sync_wrap(client)
@@ -89,6 +89,24 @@ def statsd_udp_stream(host, port, registry=ppc.PUSH_REGISTRY):
8989
return _sync_wrap(client)
9090

9191

92+
def openmetrics_http_async(url, verb="POST", period=15.0, registry=ppc.PUSH_REGISTRY):
93+
client = ppc.AsyncBatchClient(
94+
format=ppc.OpenMetricsFormat(registry=registry),
95+
transport=ppc.AioHttpTransport(url, verb),
96+
period=period,
97+
)
98+
return _async_wrap(client)
99+
100+
101+
def openmetrics_http_thread(url, verb="POST", period=15.0, registry=ppc.PUSH_REGISTRY):
102+
client = ppc.ThreadBatchClient(
103+
format=ppc.OpenMetricsFormat(registry=registry),
104+
transport=ppc.SyncHttpTransport(url, verb),
105+
period=period,
106+
)
107+
return _sync_wrap(client)
108+
109+
92110
#
93111
# decorator AND context manager
94112
#

prometheus_push_client/formats/base.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,22 @@ def iter_samples(self):
1616

1717
def format_metrics(self, *metrics):
1818
for metric in metrics:
19+
for line in self.format_header(metric):
20+
yield _enc(line)
21+
1922
for sample in metric.samples:
2023
line = self.format_sample(sample, metric)
21-
if isinstance(line, str):
22-
line = line.encode("utf-8")
23-
yield line
24+
yield _enc(line)
25+
26+
def format_header(self, metric):
27+
return
28+
yield # "empty" generator by default
2429

2530
def format_sample(self, metric, sample):
26-
raise NotImplementedError()
31+
raise NotImplementedError()
32+
33+
34+
def _enc(line):
35+
if isinstance(line, str):
36+
return line.encode("utf-8")
37+
return line

prometheus_push_client/formats/openmetrics.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class OpenMetricsFormat(BaseFormat):
77
https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md
88
"""
99

10+
FMT_DATATYPE = "# TYPE %(measurement)s %(dtype)s"
1011
FMT_DATAPOINT = "%(measurement)s%(tag_set)s %(value)s%(timestamp)s"
1112

1213
ESCAPING = str.maketrans({
@@ -16,7 +17,25 @@ class OpenMetricsFormat(BaseFormat):
1617
})
1718

1819

19-
def format_sample(self, sample, metric):
20+
def format_header(self, metric):
21+
# as in generate_lastest implemented at:
22+
# https://github.com/prometheus/client_python/blob/master/prometheus_client/exposition.py
23+
24+
mname, mtype = metric.name, metric.type
25+
if metric.type == "counter":
26+
mname = f"{mname}_total"
27+
elif metric.type in ("info", "stateset"):
28+
mtype = "gauge"
29+
elif metric.type == "gaugehistogram":
30+
mtype = "histogram"
31+
32+
yield self.FMT_DATATYPE % dict(measurement=mname, dtype=mtype)
33+
yield self.FMT_DATATYPE % dict(
34+
measurement=f"{metric.name}_created",
35+
dtype="gauge"
36+
)
37+
38+
def format_sample(self, sample, _):
2039
tag_set = ""
2140
if sample.labels:
2241
tags = (f'{k}="{v.translate(self.ESCAPING)}"' for k, v in sample.labels.items())
@@ -26,10 +45,9 @@ def format_sample(self, sample, metric):
2645
if sample.timestamp: # pragma: no cover
2746
ts = " %s" % sample.timestamp
2847

29-
# TODO: TYPE string?
3048
return self.FMT_DATAPOINT % dict(
3149
measurement=sample.name,
3250
tag_set=tag_set,
3351
value=sample.value,
3452
timestamp=ts,
35-
)
53+
)

prometheus_push_client/transports/http.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,25 @@
99

1010

1111
class BaseHttpTransport:
12-
def __init__(self, url):
12+
def __init__(self, url, verb="POST"):
1313
self._validate()
1414
self.url = url
15+
self.verb = verb
1516
self.session = None
17+
#TODO: basic auth, custom headers, tls ?
1618

1719
def _validate(self): # pragma: no cover
1820
pass
1921

22+
def prepare_data(self, iterable):
23+
data = b"\n".join(iterable)
24+
to_pad = sum(ord(b"\n") != char for char in data[-2:])
25+
return data.ljust(len(data) + to_pad, b"\n") # ensure ends with "\n\n"
26+
2027
def push_all_sync(self):
2128
raise NotImplementedError("brave proposal")
2229

2330

24-
# TODO: configurable push formats ?
25-
26-
2731
class SyncHttpTransport(BaseHttpTransport):
2832
def _validate(self):
2933
if requests is None:
@@ -36,8 +40,8 @@ def stop(self):
3640
self.session.close()
3741

3842
def push_all(self, iterable):
39-
data = b"\n".join(iterable)
40-
self.session.post(self.url, data=data)
43+
data = self.prepare_data(iterable)
44+
resp = self.session.request(self.verb, self.url, data=data)
4145

4246

4347
class AioHttpTransport(BaseHttpTransport):
@@ -52,6 +56,6 @@ async def stop(self):
5256
await self.session.close()
5357

5458
async def push_all(self, iterable):
55-
data = b"\n".join(iterable)
56-
async with self.session.post(self.url, data=data) as _:
59+
data = self.prepare_data(iterable)
60+
async with self.session.request(self.verb, self.url, data=data) as _:
5761
pass

prometheus_push_client/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.0.7"
1+
__version__ = "0.0.8"

0 commit comments

Comments
 (0)