From 26b86deb9d41bc820eff3101aca5fc11e5df94de Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 16 Dec 2016 16:51:12 +0100 Subject: [PATCH] dnsdist: Add an optional `seconds` parameter to `statNodeRespRing()` By default `statNodeRespRing()` applies the visitor function to every entry in the response rings. When passed a non-zero `seconds` parameter, it will only apply it to entries added in the last `seconds` seconds. --- pdns/dnsdist-lua2.cc | 19 ++++- regression-tests.dnsdist/test_Advanced.py | 87 +++++++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/pdns/dnsdist-lua2.cc b/pdns/dnsdist-lua2.cc index 2a2e5bb12..24797e6ea 100644 --- a/pdns/dnsdist-lua2.cc +++ b/pdns/dnsdist-lua2.cc @@ -84,12 +84,25 @@ map filterScore(const map statvisitor_t; -void statNodeRespRing(statvisitor_t visitor) +static void statNodeRespRing(statvisitor_t visitor, unsigned int seconds) { + struct timespec cutoff, now; + gettime(&now); + if (seconds) { + cutoff = now; + cutoff.tv_sec -= seconds; + } + std::lock_guard lock(g_rings.respMutex); StatNode root; for(const auto& c : g_rings.respRing) { + if (now < c.when) + continue; + + if (seconds && c.when < cutoff) + continue; + root.submit(c.name, c.dh.rcode, c.requestor); } StatNode::Stat node; @@ -355,7 +368,9 @@ void moreLua(bool client) g_lua.registerMember("nxdomains", &StatNode::Stat::nxdomains); g_lua.registerMember("queries", &StatNode::Stat::queries); - g_lua.writeFunction("statNodeRespRing", statNodeRespRing); + g_lua.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional seconds) { + statNodeRespRing(visitor, seconds ? *seconds : 0); + }); g_lua.writeFunction("getTopBandwidth", [](unsigned int top) { setLuaNoSideEffect(); diff --git a/regression-tests.dnsdist/test_Advanced.py b/regression-tests.dnsdist/test_Advanced.py index c0ae43d81..eb35ed0a3 100644 --- a/regression-tests.dnsdist/test_Advanced.py +++ b/regression-tests.dnsdist/test_Advanced.py @@ -1,6 +1,8 @@ #!/usr/bin/env python +import base64 from datetime import datetime, timedelta import os +import string import time import dns from dnsdisttests import DNSDistTest @@ -1243,3 +1245,88 @@ class TestAdvancedLuaDO(DNSDistTest): self.assertTrue(receivedResponse) doResponse.id = receivedResponse.id self.assertEquals(receivedResponse, doResponse) + +class TestStatNodeRespRingSince(DNSDistTest): + + _consoleKey = DNSDistTest.generateConsoleKey() + _consoleKeyB64 = base64.b64encode(_consoleKey) + _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort'] + _config_template = """ + setKey("%s") + controlSocket("127.0.0.1:%s") + s1 = newServer{address="127.0.0.1:%s"} + s1:setUp() + function visitor(node, self, childstat) + table.insert(nodesSeen, node.fullname) + end + """ + + def testStatNodeRespRingSince(self): + """ + Advanced: StatNodeRespRing with optional since parameter + + """ + name = 'statnodesince.advanced.tests.powerdns.com.' + query = dns.message.make_query(name, 'A', 'IN') + response = dns.message.make_response(query) + rrset = dns.rrset.from_text(name, + 1, + dns.rdataclass.IN, + dns.rdatatype.A, + '127.0.0.1') + response.answer.append(rrset) + + (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) + self.assertTrue(receivedQuery) + self.assertTrue(receivedResponse) + receivedQuery.id = query.id + self.assertEquals(query, receivedQuery) + self.assertEquals(response, receivedResponse) + + self.sendConsoleCommand("nodesSeen = {}") + self.sendConsoleCommand("statNodeRespRing(visitor)") + nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str") + nodes = string.strip(nodes, "\n") + self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com. +advanced.tests.powerdns.com. +tests.powerdns.com. +powerdns.com. +com.""") + + self.sendConsoleCommand("nodesSeen = {}") + self.sendConsoleCommand("statNodeRespRing(visitor, 0)") + nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str") + nodes = string.strip(nodes, "\n") + self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com. +advanced.tests.powerdns.com. +tests.powerdns.com. +powerdns.com. +com.""") + + time.sleep(5) + + self.sendConsoleCommand("nodesSeen = {}") + self.sendConsoleCommand("statNodeRespRing(visitor)") + nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str") + nodes = string.strip(nodes, "\n") + self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com. +advanced.tests.powerdns.com. +tests.powerdns.com. +powerdns.com. +com.""") + + self.sendConsoleCommand("nodesSeen = {}") + self.sendConsoleCommand("statNodeRespRing(visitor, 5)") + nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str") + nodes = string.strip(nodes, "\n") + self.assertEquals(nodes, """""") + + self.sendConsoleCommand("nodesSeen = {}") + self.sendConsoleCommand("statNodeRespRing(visitor, 10)") + nodes = self.sendConsoleCommand("str = '' for key,value in pairs(nodesSeen) do str = str..value..\"\\n\" end return str") + nodes = string.strip(nodes, "\n") + self.assertEquals(nodes, """statnodesince.advanced.tests.powerdns.com. +advanced.tests.powerdns.com. +tests.powerdns.com. +powerdns.com. +com.""") -- 2.40.0