]> granicus.if.org Git - pdns/commitdiff
implement dnsdist timeout searching in grepq and topSlow()
authorbert hubert <bert.hubert@netherlabs.nl>
Mon, 4 Jan 2016 07:08:25 +0000 (08:08 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Mon, 4 Jan 2016 07:08:25 +0000 (08:08 +0100)
pdns/dnsdist-lua.cc
pdns/dnsdist-lua2.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist.cc
pdns/dnsdist.hh

index 676ffce692a80787d0a7a31db962dd64af2802e8..daae1710404166cf64c3dd8e1d1947455085c16b 100644 (file)
@@ -65,6 +65,57 @@ std::shared_ptr<DNSRule> makeRule(const luadnsrule_t& var)
     return std::make_shared<NetmaskGroupRule>(nmg);
 }
 
+std::unordered_map<int, vector<boost::variant<string,double>>> getGenResponses(unsigned int top, boost::optional<int> labels, std::function<bool(const Rings::Response&)> pred) 
+{
+  setLuaNoSideEffect();
+  map<DNSName, int> counts;
+  unsigned int total=0;
+  {
+    std::lock_guard<std::mutex> 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 "<<total<<" responses, "<<counts.size()<<" different ones"<<endl;
+  vector<pair<int, DNSName>> 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<int, vector<boost::variant<string,double>>> 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<std::function<void(void)>> setupLua(bool client, const std::string& config)
 {
   g_launchWork= new vector<std::function<void(void)>>();
@@ -915,57 +966,18 @@ vector<std::function<void(void)>> setupLua(bool client, const std::string& confi
     });
 
   g_lua.writeFunction("getTopResponses", [](unsigned int top, unsigned int kind, boost::optional<int> labels) {
-      setLuaNoSideEffect();
-      map<DNSName, int> counts;
-      unsigned int total=0;
-      {
-       std::lock_guard<std::mutex> 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 "<<total<<" responses, "<<counts.size()<<" different ones"<<endl;
-      vector<pair<int, DNSName>> 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<int, vector<boost::variant<string,double>>> 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<int> 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", []() {
index 8bd81e2a63ca0ab4c667fb8d153856bba970fa0c..7d2b848c90b4af363f3ad46d064215070c25ac8f 100644 (file)
@@ -233,17 +233,23 @@ void moreLua()
   g_lua.writeFunction("grepq", [](const std::string& s, boost::optional<unsigned int> limit) {
       boost::optional<Netmask>  nm;
       boost::optional<DNSName> 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<struct timespec, string> 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<decltype(c.usec)>::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;
index ee25798cb8a16526559124241527e85b05c8d3fa..c989b62577a5f199f3432e15c001da8f26880967 100644 (file)
@@ -429,7 +429,7 @@ void* tcpClientThread(int pipefd)
         unsigned int udiff = 1000000.0*DiffTime(now,answertime);
         {
           std::lock_guard<std::mutex> 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();
index 43835eafa604d8aa38342e3086f9062335a7ca6c..54e71897caee7ed2947f5d34f72c0b1c96d42921 100644 (file)
@@ -271,7 +271,7 @@ void* responderThread(std::shared_ptr<DownstreamState> state)
       struct timespec ts;
       clock_gettime(CLOCK_MONOTONIC, &ts);
       std::lock_guard<std::mutex> 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<std::mutex> 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<unsigned int>::max(), 0, fake, dss->remote});
         }          
       }
     }
index 619dd8106d60d0ac79be7c95ed46be55c6a10538..382573150df3bc66361fad8903a91e6739ea110e 100644 (file)
@@ -231,6 +231,7 @@ struct Rings {
     unsigned int usec;
     unsigned int size;
     struct dnsheader dh;
+    ComboAddress ds; // who handled it
   };
   boost::circular_buffer<Response> respRing;
   std::mutex respMutex;