Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions prometheus_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#!/usr/bin/python

from . import core
from . import exposition
from . import gc_collector
from . import metrics
from . import metrics_core
from . import platform_collector
from . import process_collector
from . import registry
from . import metrics_core
from . import metrics

__all__ = ['Counter', 'Gauge', 'Summary', 'Histogram', 'Info', 'Enum']

Expand Down Expand Up @@ -57,5 +56,6 @@

start_http_server(8000)
import time

while True:
time.sleep(1)
7 changes: 2 additions & 5 deletions prometheus_client/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@

from .metrics import Counter, Enum, Gauge, Histogram, Info, Summary
from .metrics_core import (
CounterMetricFamily, GaugeHistogramMetricFamily, GaugeMetricFamily,
HistogramMetricFamily, InfoMetricFamily, Metric, Sample,
StateSetMetricFamily, SummaryMetricFamily, UnknownMetricFamily,
UntypedMetricFamily,
)
CounterMetricFamily, GaugeHistogramMetricFamily, GaugeMetricFamily, HistogramMetricFamily, InfoMetricFamily,
Comment thread
tusharmakkar08 marked this conversation as resolved.
Metric, StateSetMetricFamily, SummaryMetricFamily, UnknownMetricFamily, UntypedMetricFamily)
from .registry import CollectorRegistry, REGISTRY
from .samples import Exemplar, Sample, Timestamp

Expand Down
9 changes: 8 additions & 1 deletion prometheus_client/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
if sys.version_info >= (3,):
from inspect import getfullargspec


def get_init(cls):
return cls.__init__
else:
Expand All @@ -65,6 +66,7 @@ def __iter__(self):

getargspec = inspect.getargspec


def get_init(cls):
return cls.__init__.__func__

Expand Down Expand Up @@ -246,7 +248,7 @@ def decorator(caller, _func=None):
if inspect.isclass(caller):
name = caller.__name__.lower()
doc = 'decorator(%s) converts functions/generators into ' \
'factories of %s objects' % (caller.__name__, caller.__name__)
'factories of %s objects' % (caller.__name__, caller.__name__)
elif inspect.isfunction(caller):
if caller.__name__ == '<lambda>':
name = '_lambda_'
Expand Down Expand Up @@ -284,12 +286,16 @@ def __call__(self, func):
if n_args == 2 and not init.varargs: # (self, genobj) Python 2.7
def __init__(self, g, *a, **k):
return _GeneratorContextManager.__init__(self, g(*a, **k))


ContextManager.__init__ = __init__
elif n_args == 2 and init.varargs: # (self, gen, *a, **k) Python 3.4
pass
elif n_args == 4: # (self, gen, args, kwds) Python 3.5
def __init__(self, g, *a, **k):
return _GeneratorContextManager.__init__(self, g, a, k)


ContextManager.__init__ = __init__

contextmanager = decorator(ContextManager)
Expand Down Expand Up @@ -380,6 +386,7 @@ def dec(f):
check(getfullargspec(f).args, operator.lt, ' in ' + f.__name__)
typemap[types] = f
return f

return dec

def dispatch_info(*types):
Expand Down
59 changes: 31 additions & 28 deletions prometheus_client/exposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
from urllib.request import build_opener, Request, HTTPHandler
from urllib.parse import quote_plus, parse_qs, urlparse


CONTENT_TYPE_LATEST = str('text/plain; version=0.0.4; charset=utf-8')
'''Content type of the latest text format'''
"""Content type of the latest text format"""

PYTHON26_OR_OLDER = sys.version_info < (2, 7)


def make_wsgi_app(registry=REGISTRY):
'''Create a WSGI app which serves the metrics from a registry.'''
"""Create a WSGI app which serves the metrics from a registry."""

def prometheus_app(environ, start_response):
params = parse_qs(environ.get('QUERY_STRING', ''))
r = registry
Expand All @@ -48,6 +48,7 @@ def prometheus_app(environ, start_response):
headers = [(str('Content-type'), content_type)]
start_response(status, headers)
return [output]

return prometheus_app


Expand All @@ -68,22 +69,22 @@ def start_wsgi_server(port, addr='', registry=REGISTRY):


def generate_latest(registry=REGISTRY):
'''Returns the metrics from the registry in latest text format as a string.'''
"""Returns the metrics from the registry in latest text format as a string."""

def sample_line(s):
if s.labels:
def sample_line(line):
if line.labels:
labelstr = '{{{0}}}'.format(','.join(
['{0}="{1}"'.format(
k, v.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"'))
for k, v in sorted(s.labels.items())]))
k, v.replace('\\', r'\\').replace('\n', r'\n').replace('"', r'\"'))
for k, v in sorted(line.labels.items())]))
else:
labelstr = ''
timestamp = ''
if s.timestamp is not None:
if line.timestamp is not None:
# Convert to milliseconds.
timestamp = ' {0:d}'.format(int(float(s.timestamp) * 1000))
timestamp = ' {0:d}'.format(int(float(line.timestamp) * 1000))
return '{0}{1} {2}{3}\n'.format(
s.name, labelstr, floatToGoString(s.value), timestamp)
line.name, labelstr, floatToGoString(line.value), timestamp)

output = []
for metric in registry.collect():
Expand Down Expand Up @@ -121,7 +122,7 @@ def sample_line(s):
except Exception as exception:
exception.args = (exception.args or ('',)) + (metric,)
raise

for suffix, lines in sorted(om_samples.items()):
output.append('# TYPE {0}{1} gauge\n'.format(metric.name, suffix))
output.extend(lines)
Expand All @@ -134,7 +135,7 @@ def choose_encoder(accept_header):
if accepted.split(';')[0].strip() == 'application/openmetrics-text':
return (openmetrics.generate_latest,
openmetrics.CONTENT_TYPE_LATEST)
return (generate_latest, CONTENT_TYPE_LATEST)
return generate_latest, CONTENT_TYPE_LATEST


class MetricsHandler(BaseHTTPRequestHandler):
Expand Down Expand Up @@ -196,10 +197,10 @@ def start_http_server(port, addr='', registry=REGISTRY):


def write_to_textfile(path, registry):
'''Write metrics to the given path.
"""Write metrics to the given path.

This is intended for use with the Node exporter textfile collector.
The path must end in .prom for the textfile collector to process it.'''
The path must end in .prom for the textfile collector to process it."""
tmppath = '%s.%s.%s' % (path, os.getpid(), threading.current_thread().ident)
with open(tmppath, 'wb') as f:
f.write(generate_latest(registry))
Expand All @@ -208,9 +209,10 @@ def write_to_textfile(path, registry):


def default_handler(url, method, timeout, headers, data):
'''Default handler that implements HTTP/HTTPS connections.
"""Default handler that implements HTTP/HTTPS connections.

Used by the push_to_gateway functions. Can be re-used by other handlers."""

Used by the push_to_gateway functions. Can be re-used by other handlers.'''
def handle():
request = Request(url, data=data)
request.get_method = lambda: method
Expand All @@ -225,13 +227,14 @@ def handle():


def basic_auth_handler(url, method, timeout, headers, data, username=None, password=None):
'''Handler that implements HTTP/HTTPS connections with Basic Auth.
"""Handler that implements HTTP/HTTPS connections with Basic Auth.

Sets auth headers using supplied 'username' and 'password', if set.
Used by the push_to_gateway functions. Can be re-used by other handlers.'''
Used by the push_to_gateway functions. Can be re-used by other handlers."""

def handle():
'''Handler that implements HTTP Basic Auth.
'''
"""Handler that implements HTTP Basic Auth.
"""
if username is not None and password is not None:
auth_value = '{0}:{1}'.format(username, password).encode('utf-8')
auth_token = base64.b64encode(auth_value)
Expand All @@ -245,7 +248,7 @@ def handle():
def push_to_gateway(
gateway, job, registry, grouping_key=None, timeout=30,
handler=default_handler):
'''Push metrics to the given pushgateway.
"""Push metrics to the given pushgateway.

`gateway` the url for your push gateway. Either of the form
'http://pushgateway.local', or 'pushgateway.local'.
Expand Down Expand Up @@ -282,14 +285,14 @@ def push_to_gateway(
Message Body.

This overwrites all metrics with the same job and grouping_key.
This uses the PUT HTTP method.'''
This uses the PUT HTTP method."""
_use_gateway('PUT', gateway, job, registry, grouping_key, timeout, handler)


def pushadd_to_gateway(
gateway, job, registry, grouping_key=None, timeout=30,
handler=default_handler):
'''PushAdd metrics to the given pushgateway.
"""PushAdd metrics to the given pushgateway.

`gateway` the url for your push gateway. Either of the form
'http://pushgateway.local', or 'pushgateway.local'.
Expand All @@ -308,13 +311,13 @@ def pushadd_to_gateway(
for implementation requirements.

This replaces metrics with the same name, job and grouping_key.
This uses the POST HTTP method.'''
This uses the POST HTTP method."""
_use_gateway('POST', gateway, job, registry, grouping_key, timeout, handler)


def delete_from_gateway(
gateway, job, grouping_key=None, timeout=30, handler=default_handler):
'''Delete metrics from the given pushgateway.
"""Delete metrics from the given pushgateway.

`gateway` the url for your push gateway. Either of the form
'http://pushgateway.local', or 'pushgateway.local'.
Expand All @@ -332,7 +335,7 @@ def delete_from_gateway(
for implementation requirements.

This deletes metrics with the given job and grouping_key.
This uses the DELETE HTTP method.'''
This uses the DELETE HTTP method."""
_use_gateway('DELETE', gateway, job, None, grouping_key, timeout, handler)


Expand All @@ -359,7 +362,7 @@ def _use_gateway(method, gateway, job, registry, grouping_key, timeout, handler)


def instance_ip_grouping_key():
'''Grouping key with instance set to the IP Address of this host.'''
"""Grouping key with instance set to the IP Address of this host."""
with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
s.connect(('localhost', 0))
return {'instance': s.getsockname()[0]}
Loading