Skip to content

Instantly share code, notes, and snippets.

@wyattjoh
Last active September 19, 2016 15:12
Show Gist options
  • Save wyattjoh/4a8592f5602b6acc9e8a0a0b6c18e8e6 to your computer and use it in GitHub Desktop.
Save wyattjoh/4a8592f5602b6acc9e8a0a0b6c18e8e6 to your computer and use it in GitHub Desktop.
Datadog Prometheus Check
from checks import AgentCheck
import re
import requests
rx0 = re.compile(r'^# TYPE \S+ (\S+)$')
rx1 = re.compile(r'(\w+)(?:{(\S+)})? ([-+]?\d*\.\d+|\d+)')
rx2 = re.compile(r'(\w+)="(\S*?)",?')
class PrometheusCheck(AgentCheck):
# generates the match pattern to determine if we should submit this metric
def get_pattern(self, patterns):
if patterns and len(patterns) > 0:
valid_patterns = '|'.join(patterns)
return re.compile(r'^(?:' + valid_patterns + ')')
return False
# retrieves the metric function from the given type of prometheus metric
def get_metric_func(self, metric_type):
# if it's a gauge, we'll use the gauge!
if metric_type == 'gauge': return self.gauge
# if it's a counter, we'll use count!
elif metric_type == 'counter': return self.count
# ATM, we aren't concerned with the other values
else: return False
# implemented as a part of the AgentCheck class
def check(self, instance):
name = instance['name']
url = instance['url']
pattern = self.get_pattern(instance['patterns'])
r = requests.get(url, stream=True)
# this is our handle for the function to use to record the metric in
# question
metric_func = False
for line in r.iter_lines():
# skip if there is nothing to process
if not line: continue
# determine the metric type
if line.startswith("#"):
m0 = rx0.match(line)
if m0:
# seems this is a TYPE line, let's see what kind of metric
# this is so we can get the function to call to send this
# off to dd
metric_type = m0.groups()[0]
metric_func = self.get_metric_func(metric_type)
# regardless, this isn't a data line, so let's restart
continue
# this is a data line, let's check it out
if metric_func:
# extract the values from it
m1 = rx1.match(line)
if m1:
g1 = m1.groups()
if pattern and not pattern.match(g1[0]):
continue
# create the metric name from it
metric = '{0}.{1}'.format(name, g1[0])
# and parse the float value
value = float(g1[2])
# default is no tags
tags = None
# and if there are tags
if g1[1] is not None:
# extract them
m2 = rx2.findall(g1[1])
# and set them on the tag object
tags = ['{0}:{1}'.format(tag[0], tag[1]) for tag in m2]
# and record it using the metric func
metric_func(metric, value, tags=tags)
if __name__ == '__main__':
check, instances = PrometheusCheck.from_yaml('/etc/dd-agent/conf.d/prometheus.yaml')
for instance in instances:
print "\nRunning the check against url: %s" % (instance['url'])
check.check(instance)
if check.has_events():
print 'Events: %s' % (check.get_events())
print 'Metrics: %s' % (check.get_metrics())
init_config:
min_collection_interval: 20
instances:
- url: http://localhost:9180/metrics
name: caddy
patterns:
- http
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment