From 2d11d1b280115e10d1a32108a609c662325ead9f Mon Sep 17 00:00:00 2001 From: bert hubert Date: Mon, 4 Jan 2016 08:08:25 +0100 Subject: [PATCH] implement dnsdist timeout searching in grepq and topSlow() --- pdns/dnsdist-lua.cc | 104 ++++++++++++++++++++++++------------------- pdns/dnsdist-lua2.cc | 33 +++++++++----- pdns/dnsdist-tcp.cc | 2 +- pdns/dnsdist.cc | 7 ++- pdns/dnsdist.hh | 1 + 5 files changed, 86 insertions(+), 61 deletions(-) diff --git a/pdns/dnsdist-lua.cc b/pdns/dnsdist-lua.cc index 676ffce69..daae17104 100644 --- a/pdns/dnsdist-lua.cc +++ b/pdns/dnsdist-lua.cc @@ -65,6 +65,57 @@ std::shared_ptr makeRule(const luadnsrule_t& var) return std::make_shared(nmg); } +std::unordered_map>> getGenResponses(unsigned int top, boost::optional labels, std::function pred) +{ + setLuaNoSideEffect(); + map counts; + unsigned int total=0; + { + std::lock_guard lock(g_rings.respMutex); + if(!labels) { + for(const auto& a : g_rings.respRing) { + if(!pred(a)) + continue; + counts[a.name]++; + total++; + } + } + else { + unsigned int lab = *labels; + for(auto a : g_rings.respRing) { + if(!pred(a)) + continue; + + a.name.trimToLabels(lab); + counts[a.name]++; + total++; + } + + } + } + // cout<<"Looked at "<> rcounts; + rcounts.reserve(counts.size()); + for(const auto& c : counts) + rcounts.push_back(make_pair(c.second, c.first)); + + sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, + const decltype(rcounts)::value_type& b) { + return b.first < a.first; + }); + + std::unordered_map>> ret; + unsigned int count=1, rest=0; + for(const auto& rc : rcounts) { + if(count==top+1) + rest+=rc.first; + else + ret.insert({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}}); + } + ret.insert({count, {"Rest", rest, 100.0*rest/total}}); + return ret; +} + vector> setupLua(bool client, const std::string& config) { g_launchWork= new vector>(); @@ -915,57 +966,18 @@ vector> setupLua(bool client, const std::string& confi }); g_lua.writeFunction("getTopResponses", [](unsigned int top, unsigned int kind, boost::optional labels) { - setLuaNoSideEffect(); - map counts; - unsigned int total=0; - { - std::lock_guard lock(g_rings.respMutex); - if(!labels) { - for(const auto& a : g_rings.respRing) { - if(a.dh.rcode!=kind) - continue; - counts[a.name]++; - total++; - } - } - else { - unsigned int lab = *labels; - for(auto a : g_rings.respRing) { - if(a.dh.rcode!=kind) - continue; - - a.name.trimToLabels(lab); - counts[a.name]++; - total++; - } - - } - } - // cout<<"Looked at "<> rcounts; - rcounts.reserve(counts.size()); - for(const auto& c : counts) - rcounts.push_back(make_pair(c.second, c.first)); + return getGenResponses(top, labels, [kind](const Rings::Response& r) { return r.dh.rcode == kind; }); + }); - sort(rcounts.begin(), rcounts.end(), [](const decltype(rcounts)::value_type& a, - const decltype(rcounts)::value_type& b) { - return b.first < a.first; - }); + g_lua.executeCode(R"(function topResponses(top, kind, labels) top = top or 10; kind = kind or 0; for k,v in ipairs(getTopResponses(top, kind, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); - std::unordered_map>> ret; - unsigned int count=1, rest=0; - for(const auto& rc : rcounts) { - if(count==top+1) - rest+=rc.first; - else - ret.insert({count++, {rc.second.toString(), rc.first, 100.0*rc.first/total}}); - } - ret.insert({count, {"Rest", rest, 100.0*rest/total}}); - return ret; + g_lua.writeFunction("getSlowResponses", [](unsigned int top, unsigned int msec, boost::optional labels) { + return getGenResponses(top, labels, [msec](const Rings::Response& r) { return r.usec > msec*1000; }); }); - g_lua.executeCode(R"(function topResponses(top, kind, labels) top = top or 10; kind = kind or 0; for k,v in ipairs(getTopResponses(top, kind, labels)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); + + g_lua.executeCode(R"(function topSlow(top, msec, labels) top = top or 10; msec = msec or 500; for k,v in ipairs(getSlowResponses(top, msec)) do show(string.format("%4d %-40s %4d %4.1f%%",k,v[1],v[2],v[3])) end end)"); g_lua.writeFunction("showResponseLatency", []() { diff --git a/pdns/dnsdist-lua2.cc b/pdns/dnsdist-lua2.cc index 8bd81e2a6..7d2b848c9 100644 --- a/pdns/dnsdist-lua2.cc +++ b/pdns/dnsdist-lua2.cc @@ -233,17 +233,23 @@ void moreLua() g_lua.writeFunction("grepq", [](const std::string& s, boost::optional limit) { boost::optional nm; boost::optional dn; + unsigned int msec=0; try { nm = Netmask(s); } catch(...) { - try { dn=DNSName(s); } - catch(...) - { - g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask"; - return; - } + if(boost::ends_with(s,"ms") && sscanf(s.c_str(), "%ums", &msec)) { + ; + } + else { + try { dn=DNSName(s); } + catch(...) + { + g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask"; + return; + } + } } decltype(g_rings.queryRing) qr; @@ -270,13 +276,13 @@ void moreLua() std::multimap out; - boost::format fmt("%-7.1f %-47s %-5d %-25s %-5s %-4.1f %-2s %-2s %-2s %s\n"); - g_outputBuffer+= (fmt % "Time" % "Client" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str(); + boost::format fmt("%-7.1f %-47s %-12s %-5d %-25s %-5s %-4.1f %-2s %-2s %-2s %s\n"); + g_outputBuffer+= (fmt % "Time" % "Client" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str(); for(const auto& c : qr) { - if((nm && nm->match(c.requestor)) || (dn && c.name.isPartOf(*dn))) { + if((nm && nm->match(c.requestor)) || (dn && c.name.isPartOf(*dn)) ) { QType qt(c.qtype); - out.insert(make_pair(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % htons(c.dh.id) % c.name.toString() % qt.getName() % "" % (c.dh.tc ? "TC" : "") % (c.dh.rd? "RD" : "") % (c.dh.aa? "AA" : "") % "Question").str() )) ; + out.insert(make_pair(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % "" % htons(c.dh.id) % c.name.toString() % qt.getName() % "" % (c.dh.tc ? "TC" : "") % (c.dh.rd? "RD" : "") % (c.dh.aa? "AA" : "") % "Question").str() )) ; if(limit && *limit==++num) break; @@ -287,13 +293,16 @@ void moreLua() string extra; for(const auto& c : rr) { - if((nm && nm->match(c.requestor)) || (dn && c.name.isPartOf(*dn))) { + if((nm && nm->match(c.requestor)) || (dn && c.name.isPartOf(*dn)) || (msec && (c.usec/1000 > msec)) ) { QType qt(c.qtype); if(!c.dh.rcode) extra=". " +std::to_string(htons(c.dh.ancount))+ " answers"; else extra.clear(); - out.insert(make_pair(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % htons(c.dh.id) % c.name.toString() % qt.getName() % (c.usec/1000.0) % (c.dh.tc ? "TC" : "") % (c.dh.rd? "RD" : "") % (c.dh.aa? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str() )) ; + if(c.usec != std::numeric_limits::max()) + out.insert(make_pair(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % c.ds.toStringWithPort() % htons(c.dh.id) % c.name.toString() % qt.getName() % (c.usec/1000.0) % (c.dh.tc ? "TC" : "") % (c.dh.rd? "RD" : "") % (c.dh.aa? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str() )) ; + else + out.insert(make_pair(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % c.ds.toStringWithPort() % htons(c.dh.id) % c.name.toString() % qt.getName() % "T.O" % (c.dh.tc ? "TC" : "") % (c.dh.rd? "RD" : "") % (c.dh.aa? "AA" : "") % (RCode::to_s(c.dh.rcode) + extra)).str() )) ; if(limit && *limit==++num) break; diff --git a/pdns/dnsdist-tcp.cc b/pdns/dnsdist-tcp.cc index ee25798cb..c989b6257 100644 --- a/pdns/dnsdist-tcp.cc +++ b/pdns/dnsdist-tcp.cc @@ -429,7 +429,7 @@ void* tcpClientThread(int pipefd) unsigned int udiff = 1000000.0*DiffTime(now,answertime); { std::lock_guard lock(g_rings.respMutex); - g_rings.respRing.push_back({answertime, ci.remote, qname, qtype, (unsigned int)udiff, (unsigned int)responseLen, *dh}); + g_rings.respRing.push_back({answertime, ci.remote, qname, qtype, (unsigned int)udiff, (unsigned int)responseLen, *dh, ds->remote}); } largerQuery.clear(); diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 43835eafa..54e71897c 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -271,7 +271,7 @@ void* responderThread(std::shared_ptr state) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); std::lock_guard lock(g_rings.respMutex); - g_rings.respRing.push_back({ts, ids->origRemote, ids->qname, ids->qtype, (unsigned int)udiff, (unsigned int)got, *dh}); + g_rings.respRing.push_back({ts, ids->origRemote, ids->qname, ids->qtype, (unsigned int)udiff, (unsigned int)got, *dh, state->remote}); } if(dh->rcode == RCode::ServFail) g_stats.servfailResponses++; @@ -836,7 +836,10 @@ void* maintThread() struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); std::lock_guard lock(g_rings.respMutex); - g_rings.respRing.push_back({ts, ids.origRemote, ids.qname, ids.qtype, 0, 2000000, 0}); + struct dnsheader fake; + memset(&fake, 0, sizeof(fake)); + fake.id = ids.origID; + g_rings.respRing.push_back({ts, ids.origRemote, ids.qname, ids.qtype, std::numeric_limits::max(), 0, fake, dss->remote}); } } } diff --git a/pdns/dnsdist.hh b/pdns/dnsdist.hh index 619dd8106..382573150 100644 --- a/pdns/dnsdist.hh +++ b/pdns/dnsdist.hh @@ -231,6 +231,7 @@ struct Rings { unsigned int usec; unsigned int size; struct dnsheader dh; + ComboAddress ds; // who handled it }; boost::circular_buffer respRing; std::mutex respMutex; -- 2.40.0