]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_Prometheus.py
dnsdist: Add regression tests for the new cache-miss rules chain
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Prometheus.py
CommitLineData
116b2602 1#!/usr/bin/env python
13291274 2import os
116b2602
RG
3import requests
4import subprocess
13291274 5import unittest
630eb526 6from dnsdisttests import DNSDistTest, pickAvailablePort
116b2602 7
13291274 8@unittest.skipIf('SKIP_PROMETHEUS_TESTS' in os.environ, 'Prometheus tests are disabled')
116b2602
RG
9class TestPrometheus(DNSDistTest):
10
11 _webTimeout = 2.0
630eb526 12 _webServerPort = pickAvailablePort()
116b2602 13 _webServerBasicAuthPassword = 'secret'
2c0392a5 14 _webServerBasicAuthPasswordHashed = '$scrypt$ln=10,p=1,r=8$6DKLnvUYEeXWh3JNOd3iwg==$kSrhdHaRbZ7R74q3lGBqO1xetgxRxhmWzYJ2Qvfm7JM='
116b2602 15 _webServerAPIKey = 'apisecret'
2c0392a5 16 _webServerAPIKeyHashed = '$scrypt$ln=10,p=1,r=8$9v8JxDfzQVyTpBkTbkUqYg==$bDQzAOHeK1G9UvTPypNhrX48w974ZXbFPtRKS34+aso='
412f99ef 17 _config_params = ['_testServerPort', '_webServerPort', '_webServerBasicAuthPasswordHashed', '_webServerAPIKeyHashed']
116b2602
RG
18 _config_template = """
19 newServer{address="127.0.0.1:%s"}
fa7e8b5d 20 webserver("127.0.0.1:%s")
cfe95ada 21 setWebserverConfig({password="%s", apiKey="%s"})
525f14f0
RG
22 pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
23 getPool(""):setCache(pc)
e78fc5bd
RG
24
25 -- test custom metrics as well
26 declareMetric('custom-metric1', 'counter', 'Custom counter')
27 incMetric('custom-metric1')
28 declareMetric('custom-metric2', 'gauge', 'Custom gauge')
29 -- and custom names
30 declareMetric('custom-metric3', 'counter', 'Custom counter', 'custom_prometheus_name')
116b2602
RG
31 """
32
33 def checkPrometheusContentBasic(self, content):
34 for line in content.splitlines():
35 if line.startswith('# HELP'):
36 tokens = line.split(' ')
37 self.assertGreaterEqual(len(tokens), 4)
38 elif line.startswith('# TYPE'):
39 tokens = line.split(' ')
4bfebc93 40 self.assertEqual(len(tokens), 4)
116b2602
RG
41 self.assertIn(tokens[3], ['counter', 'gauge', 'histogram'])
42 elif not line.startswith('#'):
43 tokens = line.split(' ')
4bfebc93 44 self.assertEqual(len(tokens), 2)
e78fc5bd 45 if not line.startswith('dnsdist_') and not line.startswith('custom_prometheus_name'):
116b2602
RG
46 raise AssertionError('Expecting prometheus metric to be prefixed by \'dnsdist_\', got: "%s"' % (line))
47
e78fc5bd
RG
48 def checkMetric(self, content, name, expectedType, expectedValue):
49 typeFound = False
50 helpFound = False
51 valueFound = False
52 for line in content.splitlines():
53 if name in str(line):
54 tokens = line.split(' ')
55 if line.startswith('# HELP'):
56 self.assertGreaterEqual(len(tokens), 4)
57 if tokens[2] == name:
58 helpFound = True
59 elif line.startswith('# TYPE'):
60 self.assertEqual(len(tokens), 4)
61 if tokens[2] == name:
62 typeFound = True
63 self.assertEqual(tokens[3], expectedType)
64 elif not line.startswith('#'):
65 self.assertEqual(len(tokens), 2)
66 if tokens[0] == name:
67 valueFound = True
68 self.assertEqual(int(tokens[1]), expectedValue)
69
70 self.assertTrue(typeFound)
71 self.assertTrue(helpFound)
72 self.assertTrue(valueFound)
73
116b2602
RG
74 def checkPrometheusContentPromtool(self, content):
75 output = None
76 try:
77 testcmd = ['promtool', 'check', 'metrics']
78 process = subprocess.Popen(testcmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
79 output = process.communicate(input=content)
80 except subprocess.CalledProcessError as exc:
81 raise AssertionError('%s failed (%d): %s' % (testcmd, process.returncode, process.output))
82
83 # commented out because promtool returns 3 because of the "_total" suffix warnings
84 #if process.returncode != 0:
85 # raise AssertionError('%s failed (%d): %s' % (testcmd, process.returncode, output))
86
87 for line in output[0].splitlines():
88 if line.endswith(b"should have \"_total\" suffix"):
89 continue
90 raise AssertionError('%s returned an unexpected output. Faulty line is "%s", complete content is "%s"' % (testcmd, line, output))
91
92 def testMetrics(self):
93 """
94 Prometheus: Retrieve metrics
95 """
96 url = 'http://127.0.0.1:' + str(self._webServerPort) + '/metrics'
97 r = requests.get(url, auth=('whatever', self._webServerBasicAuthPassword), timeout=self._webTimeout)
98 self.assertTrue(r)
4bfebc93 99 self.assertEqual(r.status_code, 200)
116b2602
RG
100 self.checkPrometheusContentBasic(r.text)
101 self.checkPrometheusContentPromtool(r.content)
e78fc5bd
RG
102 self.checkMetric(r.text, 'dnsdist_custom_metric1', 'counter', 1)
103 self.checkMetric(r.text, 'dnsdist_custom_metric2', 'gauge', 0)
104 self.checkMetric(r.text, 'custom_prometheus_name', 'counter', 0)