]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.dnsdist/test_Metrics.py
Merge pull request #13756 from rgacogne/ddist-xsk-doc-typos
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Metrics.py
1 #!/usr/bin/env python
2
3 import os
4 import requests
5 import socket
6 import threading
7 import unittest
8 import dns
9 from dnsdisttests import DNSDistTest, pickAvailablePort
10
11 class RuleMetricsTest(object):
12
13 _config_template = """
14 addTLSLocal("127.0.0.1:%s", "%s", "%s", { provider="openssl" })
15 addDOHLocal("127.0.0.1:%s", "%s", "%s", { "/"})
16
17 newServer{address="127.0.0.1:%s", pool={'', 'cache'}}
18 webserver("127.0.0.1:%s")
19 setWebserverConfig({apiKey="%s"})
20
21 addAction('rcode-nxdomain.metrics.tests.powerdns.com', RCodeAction(DNSRCode.NXDOMAIN))
22 addAction('rcode-refused.metrics.tests.powerdns.com', RCodeAction(DNSRCode.REFUSED))
23 addAction('rcode-servfail.metrics.tests.powerdns.com', RCodeAction(DNSRCode.SERVFAIL))
24
25 pc = newPacketCache(100)
26 getPool('cache'):setCache(pc)
27 addAction('cache.metrics.tests.powerdns.com', PoolAction('cache'))
28 """
29 _webTimeout = 2.0
30 _webServerPort = pickAvailablePort()
31 _webServerAPIKey = 'apisecret'
32 _webServerAPIKeyHashed = '$scrypt$ln=10,p=1,r=8$9v8JxDfzQVyTpBkTbkUqYg==$bDQzAOHeK1G9UvTPypNhrX48w974ZXbFPtRKS34+aso='
33 _serverKey = 'server.key'
34 _serverCert = 'server.chain'
35 _serverName = 'tls.tests.dnsdist.org'
36 _caCert = 'ca.pem'
37 _tlsServerPort = pickAvailablePort()
38 _dohServerPort = pickAvailablePort()
39 _dohBaseURL = ("https://%s:%d/" % (_serverName, _dohServerPort))
40 _config_params = ['_tlsServerPort', '_serverCert', '_serverKey', '_dohServerPort', '_serverCert', '_serverKey', '_testServerPort', '_webServerPort', '_webServerAPIKeyHashed']
41
42 @classmethod
43 def setUpClass(cls):
44 cls.startResponders()
45 cls.startDNSDist()
46 cls.setUpSockets()
47 cls.waitForTCPSocket('127.0.0.1', cls._webServerPort)
48 print("Launching tests..")
49
50 def getMetric(self, name):
51 headers = {'x-api-key': self._webServerAPIKey}
52 url = 'http://127.0.0.1:' + str(self._webServerPort) + '/api/v1/servers/localhost'
53 r = requests.get(url, headers=headers, timeout=self._webTimeout)
54 self.assertTrue(r)
55 self.assertEqual(r.status_code, 200)
56 self.assertTrue(r.json())
57 content = r.json()
58 stats = content['statistics']
59 self.assertIn(name, stats)
60 return int(stats[name])
61
62 def getPoolMetric(self, poolName, metricName):
63 headers = {'x-api-key': self._webServerAPIKey}
64 url = 'http://127.0.0.1:' + str(self._webServerPort) + '/api/v1/servers/localhost/pool?name=' + poolName
65 r = requests.get(url, headers=headers, timeout=self._webTimeout)
66 self.assertTrue(r)
67 self.assertEqual(r.status_code, 200)
68 self.assertTrue(r.json())
69 content = r.json()
70 stats = content['stats']
71 self.assertIn(metricName, stats)
72 return int(stats[metricName])
73
74 def testRCodeIncreaseMetrics(self):
75 """
76 Metrics: Check that metrics are correctly updated for RCodeAction
77 """
78 rcodes = [
79 ( 'nxdomain', dns.rcode.NXDOMAIN ),
80 ( 'refused', dns.rcode.REFUSED ),
81 ( 'servfail', dns.rcode.SERVFAIL )
82 ]
83 servfailBackendResponses = self.getMetric('servfail-responses')
84
85 for (name, rcode) in rcodes:
86 qname = 'rcode-' + name + '.metrics.tests.powerdns.com.'
87 query = dns.message.make_query(qname, 'A', 'IN')
88 # dnsdist set RA = RD for spoofed responses
89 query.flags &= ~dns.flags.RD
90 expectedResponse = dns.message.make_response(query)
91 expectedResponse.set_rcode(rcode)
92
93 ruleMetricBefore = self.getMetric('rule-' + name)
94 if name != 'refused':
95 frontendMetricBefore = self.getMetric('frontend-' + name)
96
97 for method in ("sendUDPQuery", "sendTCPQuery"):
98 sender = getattr(self, method)
99 (_, receivedResponse) = sender(query, response=None, useQueue=False)
100 self.assertEqual(receivedResponse, expectedResponse)
101
102 self.assertEqual(self.getMetric('rule-' + name), ruleMetricBefore + 2)
103 if name != 'refused':
104 self.assertEqual(self.getMetric('frontend-' + name), frontendMetricBefore + 2)
105
106 # self-generated responses should not increase this metric
107 self.assertEqual(self.getMetric('servfail-responses'), servfailBackendResponses)
108
109 def testCacheMetrics(self):
110 """
111 Metrics: Check that metrics are correctly updated for cache misses and hits
112 """
113
114 for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHQueryWrapper"):
115 qname = method + '.cache.metrics.tests.powerdns.com.'
116 query = dns.message.make_query(qname, 'A', 'IN')
117 # dnsdist set RA = RD for spoofed responses
118 query.flags &= ~dns.flags.RD
119 response = dns.message.make_response(query)
120 rrset = dns.rrset.from_text(qname,
121 3600,
122 dns.rdataclass.IN,
123 dns.rdatatype.A,
124 '127.0.0.1')
125 response.answer.append(rrset)
126
127 responsesBefore = self.getMetric('responses')
128 cacheHitsBefore = self.getMetric('cache-hits')
129 cacheMissesBefore = self.getMetric('cache-misses')
130 poolCacheHitsBefore = self.getPoolMetric('cache', 'cacheHits')
131 poolCacheMissesBefore = self.getPoolMetric('cache', 'cacheMisses')
132
133 sender = getattr(self, method)
134 # first time, cache miss
135 (receivedQuery, receivedResponse) = sender(query, response)
136 receivedQuery.id = query.id
137 self.assertEqual(query, receivedQuery)
138 self.assertEqual(receivedResponse, response)
139 # second time, hit
140 (_, receivedResponse) = sender(query, response=None, useQueue=False)
141 self.assertEqual(receivedResponse, response)
142
143 self.assertEqual(self.getMetric('responses'), responsesBefore + 2)
144 self.assertEqual(self.getMetric('cache-hits'), cacheHitsBefore + 1)
145 self.assertEqual(self.getMetric('cache-misses'), cacheMissesBefore + 1)
146 self.assertEqual(self.getPoolMetric('cache', 'cacheHits'), poolCacheHitsBefore + 1)
147 self.assertEqual(self.getPoolMetric('cache', 'cacheMisses'), poolCacheMissesBefore + 1)
148
149 def testServFailMetrics(self):
150 """
151 Metrics: Check that servfail metrics are correctly updated for server failures
152 """
153
154 for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHQueryWrapper"):
155 qname = method + '.servfail.cache.metrics.tests.powerdns.com.'
156 query = dns.message.make_query(qname, 'A', 'IN')
157 # dnsdist set RA = RD for spoofed responses
158 query.flags &= ~dns.flags.RD
159 response = dns.message.make_response(query)
160 response.set_rcode(dns.rcode.SERVFAIL)
161
162 frontendBefore = self.getMetric('frontend-servfail')
163 servfailBefore = self.getMetric('servfail-responses')
164 ruleBefore = self.getMetric('rule-servfail')
165
166 sender = getattr(self, method)
167 # first time, cache miss
168 (receivedQuery, receivedResponse) = sender(query, response)
169 receivedQuery.id = query.id
170 self.assertEqual(query, receivedQuery)
171 self.assertEqual(receivedResponse, response)
172 # second time, hit
173 (_, receivedResponse) = sender(query, response=None, useQueue=False)
174 self.assertEqual(receivedResponse, response)
175
176 self.assertEqual(self.getMetric('frontend-servfail'), frontendBefore + 2)
177 self.assertEqual(self.getMetric('servfail-responses'), servfailBefore + 1)
178 self.assertEqual(self.getMetric('rule-servfail'), ruleBefore)
179
180 class TestRuleMetricsDefault(RuleMetricsTest, DNSDistTest):
181 None
182
183 class TestRuleMetricsRecvmmsg(RuleMetricsTest, DNSDistTest):
184 # test the metrics with recvmmsg/sendmmsg support enabled as well
185 _config_template = RuleMetricsTest._config_template + """
186 setUDPMultipleMessagesVectorSize(10)
187 """