]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Make recording queries/responses in the ringbuffers optional
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 16 Aug 2022 15:07:14 +0000 (17:07 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 26 Aug 2022 08:18:30 +0000 (10:18 +0200)
pdns/dnsdist-console.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-rings.cc
pdns/dnsdist-rings.hh
pdns/dnsdist.cc
pdns/dnsdistdist/dnsdist-backend.cc
pdns/dnsdistdist/docs/reference/config.rst

index 40415a4ae3e12cb331a82efb4cfc42865487c51e..0f9998e05040cd7124b0a96cc22f7938942d76f0 100644 (file)
@@ -686,6 +686,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "setQueryCount", true, "bool", "set whether queries should be counted" },
   { "setQueryCountFilter", true, "func", "filter queries that would be counted, where `func` is a function with parameter `dq` which decides whether a query should and how it should be counted" },
   { "setRingBuffersLockRetries", true, "n", "set the number of attempts to get a non-blocking lock to a ringbuffer shard before blocking" },
+  { "setRingBuffersOptions", true, "{ lockRetries=int, recordQueries=true, recordResponses=true }", "set ringbuffer options" },
   { "setRingBuffersSize", true, "n [, numberOfShards]", "set the capacity of the ringbuffers used for live traffic inspection to `n`, and optionally the number of shards to use to `numberOfShards`" },
   { "setRoundRobinFailOnNoServer", true, "value", "By default the roundrobin load-balancing policy will still try to select a backend even if all backends are currently down. Setting this to true will make the policy fail and return that no server is available instead" },
   { "setRules", true, "list of rules", "replace the current rules with the supplied list of pairs of DNS Rules and DNS Actions (see `newRuleAction()`)" },
index d77ddf51cb576e4169265f6c19431905d6c4a015..c81cb6cbdecd37cae51e81810b65e98deaa71652 100644 (file)
@@ -2017,6 +2017,27 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     g_rings.setNumberOfLockRetries(retries);
   });
 
+  luaCtx.writeFunction("setRingBuffersOptions", [](const LuaAssociativeTable<boost::variant<bool, uint64_t>>& options) {
+    setLuaSideEffect();
+    if (g_configurationDone) {
+      errlog("setRingBuffersOptions() cannot be used at runtime!");
+      g_outputBuffer = "setRingBuffersOptions() cannot be used at runtime!\n";
+      return;
+    }
+    if (options.count("lockRetries") > 0) {
+      auto retries = boost::get<uint64_t>(options.at("lockRetries"));
+      g_rings.setNumberOfLockRetries(retries);
+    }
+    if (options.count("recordQueries") > 0) {
+      auto record = boost::get<bool>(options.at("recordQueries"));
+      g_rings.setRecordQueries(record);
+    }
+    if (options.count("recordResponses") > 0) {
+      auto record = boost::get<bool>(options.at("recordResponses"));
+      g_rings.setRecordResponses(record);
+    }
+  });
+
   luaCtx.writeFunction("setWHashedPertubation", [](uint64_t perturb) {
     setLuaSideEffect();
     checkParameterBound("setWHashedPertubation", perturb, std::numeric_limits<uint32_t>::max());
index fabbd4d04352baf701deec8b1cb90c00842cd20d..5485b33869f22b7f86e52d3fc349e0290bd30c50 100644 (file)
@@ -48,8 +48,12 @@ void Rings::init()
   /* resize all the rings */
   for (auto& shard : d_shards) {
     shard = std::make_unique<Shard>();
-    shard->queryRing.lock()->set_capacity(d_capacity / d_numberOfShards);
-    shard->respRing.lock()->set_capacity(d_capacity / d_numberOfShards);
+    if (shouldRecordQueries()) {
+      shard->queryRing.lock()->set_capacity(d_capacity / d_numberOfShards);
+    }
+    if (shouldRecordResponses()) {
+      shard->respRing.lock()->set_capacity(d_capacity / d_numberOfShards);
+    }
   }
 
   /* we just recreated the shards so they are now empty */
@@ -66,6 +70,16 @@ void Rings::setNumberOfLockRetries(size_t retries)
   }
 }
 
+void Rings::setRecordQueries(bool record)
+{
+  d_recordQueries = record;
+}
+
+void Rings::setRecordResponses(bool record)
+{
+  d_recordResponses = record;
+}
+
 size_t Rings::numDistinctRequestors()
 {
   std::set<ComboAddress, ComboAddress::addressOnlyLessThan> s;
index 2f66e5689d89c1d94035acf62f564eecfe7df4d6..c8b0d32dd0c4771312cff2b6a3493fc02559201f 100644 (file)
@@ -82,6 +82,8 @@ struct Rings {
   void init();
 
   void setNumberOfLockRetries(size_t retries);
+  void setRecordQueries(bool);
+  void setRecordResponses(bool);
 
   size_t getNumberOfShards() const
   {
@@ -186,6 +188,16 @@ struct Rings {
      only useful for debugging purposes */
   size_t loadFromFile(const std::string& filepath, const struct timespec& now);
 
+  bool shouldRecordQueries() const
+  {
+    return d_recordQueries;
+  }
+
+  bool shouldRecordResponses() const
+  {
+    return d_recordResponses;
+  }
+
   std::vector<std::unique_ptr<Shard> > d_shards;
   pdns::stat_t d_blockingQueryInserts;
   pdns::stat_t d_blockingResponseInserts;
@@ -240,6 +252,8 @@ private:
   size_t d_numberOfShards;
   size_t d_nbLockTries = 5;
   bool d_keepLockingStats{false};
+  bool d_recordQueries{true};
+  bool d_recordResponses{true};
 };
 
 extern Rings g_rings;
index d82a205eb7aef5b150d61460b645f87eb2b6b08b..dcbfc9e1c62f04494c647eab28144c677f70c499 100644 (file)
@@ -606,9 +606,11 @@ void handleResponseSent(const IDState& ids, double udiff, const ComboAddress& cl
 
 void handleResponseSent(const DNSName& qname, const QType& qtype, double udiff, const ComboAddress& client, const ComboAddress& backend, unsigned int size, const dnsheader& cleartextDH, dnsdist::Protocol outgoingProtocol, dnsdist::Protocol incomingProtocol)
 {
-  struct timespec ts;
-  gettime(&ts);
-  g_rings.insertResponse(ts, client, qname, qtype, static_cast<unsigned int>(udiff), size, cleartextDH, backend, outgoingProtocol);
+  if (g_rings.shouldRecordResponses()) {
+    struct timespec ts;
+    gettime(&ts);
+    g_rings.insertResponse(ts, client, qname, qtype, static_cast<unsigned int>(udiff), size, cleartextDH, backend, outgoingProtocol);
+  }
 
   switch (cleartextDH.rcode) {
   case RCode::NXDomain:
@@ -914,7 +916,9 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
 
 static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const struct timespec& now)
 {
-  g_rings.insertQuery(now, *dq.remote, *dq.qname, dq.qtype, dq.getData().size(), *dq.getHeader(), dq.getProtocol());
+  if (g_rings.shouldRecordQueries()) {
+    g_rings.insertQuery(now, *dq.remote, *dq.qname, dq.qtype, dq.getData().size(), *dq.getHeader(), dq.getProtocol());
+  }
 
   if (g_qcount.enabled) {
     string qname = (*dq.qname).toLogString();
index 005eaa3b8175d06bb63e85ed2b8011a42fab343c..dfebb8efcadeff9cc5cf53fffb1a355e6a2fc66b 100644 (file)
@@ -339,14 +339,16 @@ void DownstreamState::handleTimeout(IDState& ids)
            d_config.remote.toStringWithPort(), getName(),
            ids.qname.toLogString(), QType(ids.qtype).toString(), ids.origRemote.toStringWithPort());
 
-  struct timespec ts;
-  gettime(&ts);
+  if (g_rings.shouldRecordResponses()) {
+    struct timespec ts;
+    gettime(&ts);
 
-  struct dnsheader fake;
-  memset(&fake, 0, sizeof(fake));
-  fake.id = ids.origID;
+    struct dnsheader fake;
+    memset(&fake, 0, sizeof(fake));
+    fake.id = ids.origID;
 
-  g_rings.insertResponse(ts, ids.origRemote, ids.qname, ids.qtype, std::numeric_limits<unsigned int>::max(), 0, fake, d_config.remote, getProtocol());
+    g_rings.insertResponse(ts, ids.origRemote, ids.qname, ids.qtype, std::numeric_limits<unsigned int>::max(), 0, fake, d_config.remote, getProtocol());
+  }
 }
 
 void DownstreamState::handleTimeouts()
index c7e11ee224a66d8840f9b6d800b162e1dd55cf9f..eb9117b8a5de062a3c0563d9b08283dbb0ecf258 100644 (file)
@@ -507,6 +507,20 @@ Ringbuffers
 
   :param int num: The maximum number of attempts. Defaults to 5 if there is more than one shard, 0 otherwise.
 
+.. function:: setRingBuffersOptions(options)
+
+  .. versionadded:: 1.8.0
+
+  Set the rings buffers configuration
+
+  :param table options: A table with key: value pairs with options.
+
+  Options:
+
+  * ``lockRetries``: int - Set the number of shards to attempt to lock without blocking before giving up and simply blocking while waiting for the next shard to be available. Default to 5 if there is more than one shard, 0 otherwise
+  * ``recordQueries``: boolean - Whether to record queries in the ring buffers. Default is true. Note that :func:`grepq`, several top* commands (:func:`topClients`, :func:`topQueries`, ...) and the :doc:`Dynamic Blocks <../guides/dynblocks>` require this to be enabled.
+  * ``recordResponses``: boolean - Whether to record responses in the ring buffers. Default is true. Note that :func:`grepq`, several top* commands (:func:`topResponses`, :func:`topSlow`, ...) and the :doc:`Dynamic Blocks <../guides/dynblocks>` require this to be enabled.
+
 .. function:: setRingBuffersSize(num [, numberOfShards])
 
   .. versionchanged:: 1.6.0