]> granicus.if.org Git - pdns/commitdiff
dnsdist: Add more stats about DoH HTTP responses
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 14 Jun 2019 13:13:21 +0000 (15:13 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 18 Jun 2019 12:27:13 +0000 (14:27 +0200)
Add HTTP status code statistics, per HTTP version, and publish
all the DoH stats to the API and prometheus.

pdns/dnsdist-carbon.cc
pdns/dnsdist-console.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-web.cc
pdns/dnsdistdist/docs/reference/config.rst
pdns/dnsdistdist/doh.cc
pdns/doh.hh

index e3fc46fa176dc517dc760d0bf6411df6da9f1373..d6860aee377faa798d5361c59a4fe8ac4b6e9f31 100644 (file)
@@ -174,8 +174,20 @@ try
 
             vector<pair<const char*, const std::atomic<uint64_t>&>> v{
               {"http-connects", doh->d_httpconnects},
-              {"http1-queries", doh->d_http1queries},
-              {"http2-queries", doh->d_http2queries},
+              {"http1-queries", doh->d_http1Stats.d_nbQueries},
+              {"http2-queries", doh->d_http2Stats.d_nbQueries},
+              {"http1-200-responses", doh->d_http1Stats.d_nb200Responses},
+              {"http2-200-responses", doh->d_http2Stats.d_nb200Responses},
+              {"http1-400-responses", doh->d_http1Stats.d_nb400Responses},
+              {"http2-400-responses", doh->d_http2Stats.d_nb400Responses},
+              {"http1-403-responses", doh->d_http1Stats.d_nb403Responses},
+              {"http2-403-responses", doh->d_http2Stats.d_nb403Responses},
+              {"http1-500-responses", doh->d_http1Stats.d_nb500Responses},
+              {"http2-500-responses", doh->d_http2Stats.d_nb500Responses},
+              {"http1-502-responses", doh->d_http1Stats.d_nb502Responses},
+              {"http2-502-responses", doh->d_http2Stats.d_nb502Responses},
+              {"http1-other-responses", doh->d_http1Stats.d_nbOtherResponses},
+              {"http2-other-responses", doh->d_http2Stats.d_nbOtherResponses},
               {"tls10-queries", doh->d_tls10queries},
               {"tls11-queries", doh->d_tls11queries},
               {"tls12-queries", doh->d_tls12queries},
index 98813b5cb1a5454b44297fde5a82a1dd705864fe..75b3561afaa7ac99cab88ee87d9b514fee203967 100644 (file)
@@ -531,6 +531,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "showConsoleACL", true, "", "show our current console ACL set" },
   { "showDNSCryptBinds", true, "", "display the currently configured DNSCrypt binds" },
   { "showDOHFrontends", true, "", "list all the available DOH frontends" },
+  { "showDOHResponseCodes", true, "", "show the HTTP response code statistics for the DoH frontends"},
   { "showDynBlocks", true, "", "show dynamic blocks in force" },
   { "showPools", true, "", "show the available pools" },
   { "showPoolServerPolicy", true, "pool", "show server selection policy for this pool" },
index aab963cf6675544865fb5d86c8f1dd9f4a836bcd..be59c425b9e7a015db2adc2186c4a91624a6d825 100644 (file)
@@ -1710,7 +1710,7 @@ void setupLuaConfig(bool client)
           ret << (fmt % "#" % "Address" % "HTTP" % "HTTP/1" % "HTTP/2" % "TLS 1.0" % "TLS 1.1" % "TLS 1.2" % "TLS 1.3" % "TLS other" % "GET" % "POST" % "Bad" % "Errors" % "Valid") << endl;
           size_t counter = 0;
           for (const auto& ctx : g_dohlocals) {
-            ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_httpconnects % ctx->d_http1queries % ctx->d_http2queries % ctx->d_tls10queries % ctx->d_tls11queries % ctx->d_tls12queries % ctx->d_tls13queries % ctx->d_tlsUnknownqueries % ctx->d_getqueries % ctx->d_postqueries % ctx->d_badrequests % ctx->d_errorresponses % ctx->d_validresponses) << endl;
+            ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_httpconnects % ctx->d_http1Stats.d_nbQueries % ctx->d_http1Stats.d_nbQueries % ctx->d_tls10queries % ctx->d_tls11queries % ctx->d_tls12queries % ctx->d_tls13queries % ctx->d_tlsUnknownqueries % ctx->d_getqueries % ctx->d_postqueries % ctx->d_badrequests % ctx->d_errorresponses % ctx->d_validresponses) << endl;
             counter++;
           }
           g_outputBuffer = ret.str();
@@ -1724,6 +1724,40 @@ void setupLuaConfig(bool client)
 #endif
       });
 
+    g_lua.writeFunction("showDOHResponseCodes", []() {
+#ifdef HAVE_DNS_OVER_HTTPS
+        setLuaNoSideEffect();
+        try {
+          ostringstream ret;
+          boost::format fmt("%-3d %-20.20s %-15d %-15d %-15d %-15d %-15d %-15d");
+          g_outputBuffer = "\n- HTTP/1:\n\n";
+          ret << (fmt % "#" % "Address" % "200" % "400" % "403" % "500" % "502" % "Others" ) << endl;
+          size_t counter = 0;
+          for (const auto& ctx : g_dohlocals) {
+            ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_http1Stats.d_nb200Responses % ctx->d_http1Stats.d_nb400Responses % ctx->d_http1Stats.d_nb403Responses % ctx->d_http1Stats.d_nb500Responses % ctx->d_http1Stats.d_nb502Responses % ctx->d_http1Stats.d_nbOtherResponses) << endl;
+            counter++;
+          }
+          g_outputBuffer += ret.str();
+          ret.str("");
+
+          g_outputBuffer += "\n- HTTP/2:\n\n";
+          ret << (fmt % "#" % "Address" % "200" % "400" % "403" % "500" % "502" % "Others" ) << endl;
+          counter = 0;
+          for (const auto& ctx : g_dohlocals) {
+            ret << (fmt % counter % ctx->d_local.toStringWithPort() % ctx->d_http2Stats.d_nb200Responses % ctx->d_http2Stats.d_nb400Responses % ctx->d_http2Stats.d_nb403Responses % ctx->d_http2Stats.d_nb500Responses % ctx->d_http2Stats.d_nb502Responses % ctx->d_http2Stats.d_nbOtherResponses) << endl;
+            counter++;
+          }
+          g_outputBuffer += ret.str();
+        }
+        catch(const std::exception& e) {
+          g_outputBuffer = e.what();
+          throw;
+        }
+#else
+        g_outputBuffer="DNS over HTTPS support is not present!\n";
+#endif
+      });
+
     g_lua.writeFunction("getDOHFrontend", [](size_t index) {
         std::shared_ptr<DOHFrontend> result = nullptr;
 #ifdef HAVE_DNS_OVER_HTTPS
index a31c1a924ae5714739744472dc048754567ce0cd..1f2ba5711ac12e2fe562141ac3f2724ebb180c23 100644 (file)
@@ -523,23 +523,137 @@ static void connectionThread(int sock, ComboAddress remote)
           output << statesbase << "tcpavgconnduration"     << label << " " << state->tcpAvgConnectionDuration   << "\n";
         }
 
+        const string frontsbase = "dnsdist_frontend_";
+        output << "# HELP " << frontsbase << "queries " << "Amount of queries received by this frontend" << "\n";
+        output << "# TYPE " << frontsbase << "queries " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tcpdiedreadingquery " << "Amount of TCP connections terminated while reading the query from the client" << "\n";
+        output << "# TYPE " << frontsbase << "tcpdiedreadingquery " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tcpdiedsendingresponse " << "Amount of TCP connections terminated while sending a response to the client" << "\n";
+        output << "# TYPE " << frontsbase << "tcpdiedsendingresponse " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tcpgaveup " << "Amount of TCP connections terminated after too many attemps to get a connection to the backend" << "\n";
+        output << "# TYPE " << frontsbase << "tcpgaveup " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tcpclientimeouts " << "Amount of TCP connections terminated by a timeout while reading from the client" << "\n";
+        output << "# TYPE " << frontsbase << "tcpclientimeouts " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tcpdownstreamimeouts " << "Amount of TCP connections terminated by a timeout while reading from the backend" << "\n";
+        output << "# TYPE " << frontsbase << "tcpdownstreamimeouts " << "counter" << "\n";
+        output << "# HELP " << frontsbase << "tcpcurrentconnections " << "Amount of current incoming TCP connections from clients" << "\n";
+        output << "# TYPE " << frontsbase << "tcpcurrentconnections " << "gauge" << "\n";
+        output << "# HELP " << frontsbase << "tcpavgqueriesperconnection " << "The average number of queries per TCP connection" << "\n";
+        output << "# TYPE " << frontsbase << "tcpavgqueriesperconnection " << "gauge" << "\n";
+        output << "# HELP " << frontsbase << "tcpavgconnectionduration " << "The average duration of a TCP connection (ms)" << "\n";
+        output << "# TYPE " << frontsbase << "tcpavgconnectionduration " << "gauge" << "\n";
+
         std::map<std::string,uint64_t> frontendDuplicates;
         for (const auto& front : g_frontends) {
           if (front->udpFD == -1 && front->tcpFD == -1)
             continue;
 
           string frontName = front->local.toString() + ":" + std::to_string(front->local.getPort());
-          string proto = (front->udpFD >= 0 ? "udp" : "tcp");
+          const string proto = front->getType();
           string fullName = frontName + "_" + proto;
           auto dupPair = frontendDuplicates.insert({fullName, 1});
           if (!dupPair.second) {
             frontName = frontName + "_" + std::to_string(dupPair.first->second);
             ++(dupPair.first->second);
           }
+          const std::string label = boost::str(boost::format("{frontend=\"%1%\",proto=\"%2%\"} ")
+            % frontName % proto);
+
+          output << frontsbase << "queries" << label << front->queries.load() << "\n";
+          output << frontsbase << "tcpdiedreadingquery" << label << front->tcpDiedReadingQuery.load() << "\n";
+          output << frontsbase << "tcpdiedsendingresponse" << label << front->tcpDiedSendingResponse.load() << "\n";
+          output << frontsbase << "tcpgaveup" << label << front->tcpGaveUp.load() << "\n";
+          output << frontsbase << "tcpclientimeouts" << label << front->tcpClientTimeouts.load() << "\n";
+          output << frontsbase << "tcpdownstreamtimeouts" << label << front->tcpDownstreamTimeouts.load() << "\n";
+          output << frontsbase << "tcpcurrentconnections" << label << front->tcpCurrentConnections.load() << "\n";
+          output << frontsbase << "tcpavgqueriesperconnection" << label << front->tcpAvgQueriesPerConnection.load() << "\n";
+          output << frontsbase << "tcpavgconnectionduration" << label << front->tcpAvgConnectionDuration.load() << "\n";
+        }
 
-          output << "dnsdist_frontend_queries{frontend=\"" << frontName << "\",proto=\"" << proto
-              << "\"} " << front->queries.load() << "\n";
+        const string dohfrontsbase = "dnsdist_doh_frontend_";
+        output << "# HELP " << dohfrontsbase << "http_connects " << "Number of TCP connections establoshed to this frontend" << "\n";
+        output << "# TYPE " << dohfrontsbase << "queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "tls10_queries " << "Number of valid DNS queries received via TLS 1.0" << "\n";
+        output << "# TYPE " << dohfrontsbase << "tls10_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "tls11_queries " << "Number of valid DNS queries received via TLS 1.1" << "\n";
+        output << "# TYPE " << dohfrontsbase << "tls11_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "tls12_queries " << "Number of valid DNS queries received via TLS 1.2" << "\n";
+        output << "# TYPE " << dohfrontsbase << "tls12_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "tls13_queries " << "Number of valid DNS queries received via TLS 1.3" << "\n";
+        output << "# TYPE " << dohfrontsbase << "tls13_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "tlsunknown_queries " << "Number of valid DNS queries received via an unknown TLS version" << "\n";
+        output << "# TYPE " << dohfrontsbase << "tlsunknown_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "get_queries " << "Number of valid DNS queries received via GET" << "\n";
+        output << "# TYPE " << dohfrontsbase << "get_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "post_queries " << "Number of valid DNS queries received via POST" << "\n";
+        output << "# TYPE " << dohfrontsbase << "post_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "bad_requests " << "Number of requests that could not be converted to a DNS query" << "\n";
+        output << "# TYPE " << dohfrontsbase << "bad_requests " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "error_responses " << "Number of responses sent by dnsdist indicating an error" << "\n";
+        output << "# TYPE " << dohfrontsbase << "error_responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "valid_responses " << "Number of valid responses sent by dnsdist" << "\n";
+        output << "# TYPE " << dohfrontsbase << "valid_responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_queries " << "Number of queries received over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_nb200responses " << "Number of responses with a 200 status code sent over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_nb200responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_nb400responses " << "Number of responses with a 400 status code sent over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_nb400responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_nb403responses " << "Number of responses with a 403 status code sent over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_nb403responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_nb500responses " << "Number of responses with a 500 status code sent over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_nb500responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_nb502responses " << "Number of responses with a 502 status code sent over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_nb502responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http1_nbotherresponses " << "Number of responses with an other status code sent over HTTP/1.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http1_nbotherresponses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_queries " << "Number of queries received over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_queries " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_nb200responses " << "Number of responses with a 200 status code sent over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_nb200responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_nb400responses " << "Number of responses with a 400 status code sent over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_nb400responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_nb403responses " << "Number of responses with a 403 status code sent over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_nb403responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_nb500responses " << "Number of responses with a 500 status code sent over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_nb500responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_nb502responses " << "Number of responses with a 502 status code sent over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_nb502responses " << "counter" << "\n";
+        output << "# HELP " << dohfrontsbase << "http2_nbotherresponses " << "Number of responses with an other status code sent over HTTP/2.x" << "\n";
+        output << "# TYPE " << dohfrontsbase << "http2_nbotherresponses " << "counter" << "\n";
+
+#ifdef HAVE_DNS_OVER_HTTPS
+        for(const auto& doh : g_dohlocals) {
+          const std::string label = boost::str(boost::format("{address=\"%1%\"} ") % doh->d_local.toStringWithPort());
+
+          output << dohfrontsbase << "http_connects" << label << doh->d_httpconnects << "\n";
+          output << dohfrontsbase << "tls10_queries" << label << doh->d_tls10queries << "\n";
+          output << dohfrontsbase << "tls11_queries" << label << doh->d_tls11queries << "\n";
+          output << dohfrontsbase << "tls12_queries" << label << doh->d_tls12queries << "\n";
+          output << dohfrontsbase << "tls13_queries" << label << doh->d_tls13queries << "\n";
+          output << dohfrontsbase << "tlsunknown_queries" << label << doh->d_tlsUnknownqueries << "\n";
+          output << dohfrontsbase << "get_queries" << label << doh->d_getqueries << "\n";
+          output << dohfrontsbase << "post_queries" << label << doh->d_postqueries << "\n";
+          output << dohfrontsbase << "bad_requests" << label << doh->d_badrequests << "\n";
+          output << dohfrontsbase << "error_responses" << label << doh->d_errorresponses << "\n";
+          output << dohfrontsbase << "valid_responses" << label << doh->d_validresponses << "\n";
+
+          output << dohfrontsbase << "http1_queries" << label << doh->d_http1Stats.d_nbQueries << "\n";
+          output << dohfrontsbase << "http1_nb200responses" << label << doh->d_http1Stats.d_nb200Responses << "\n";
+          output << dohfrontsbase << "http1_nb400responses" << label << doh->d_http1Stats.d_nb400Responses << "\n";
+          output << dohfrontsbase << "http1_nb403responses" << label << doh->d_http1Stats.d_nb403Responses << "\n";
+          output << dohfrontsbase << "http1_nb500responses" << label << doh->d_http1Stats.d_nb500Responses << "\n";
+          output << dohfrontsbase << "http1_nb502responses" << label << doh->d_http1Stats.d_nb502Responses << "\n";
+          output << dohfrontsbase << "http1_nbotherresponses" << label << doh->d_http1Stats.d_nbOtherResponses << "\n";
+          output << dohfrontsbase << "http2_queries" << label << doh->d_http2Stats.d_nbQueries << "\n";
+          output << dohfrontsbase << "http2_nb200responses" << label << doh->d_http2Stats.d_nb200Responses << "\n";
+          output << dohfrontsbase << "http2_nb400responses" << label << doh->d_http2Stats.d_nb400Responses << "\n";
+          output << dohfrontsbase << "http2_nb403responses" << label << doh->d_http2Stats.d_nb403Responses << "\n";
+          output << dohfrontsbase << "http2_nb500responses" << label << doh->d_http2Stats.d_nb500Responses << "\n";
+          output << dohfrontsbase << "http2_nb502responses" << label << doh->d_http2Stats.d_nb502Responses << "\n";
+          output << dohfrontsbase << "http2_nbotherresponses" << label << doh->d_http2Stats.d_nbOtherResponses << "\n";
         }
+#endif /* HAVE_DNS_OVER_HTTPS */
 
         auto localPools = g_pools.getLocal();
         const string cachebase = "dnsdist_pool_";
@@ -652,6 +766,45 @@ static void connectionThread(int sock, ComboAddress remote)
         frontends.push_back(frontend);
       }
 
+      Json::array dohs;
+#ifdef HAVE_DNS_OVER_HTTPS
+      {
+        num = 0;
+        for(const auto& doh : g_dohlocals) {
+          Json::object obj{
+            { "id", num++ },
+            { "address", doh->d_local.toStringWithPort() },
+            { "http-connects", (double) doh->d_httpconnects },
+            { "http1-queries", (double) doh->d_http1Stats.d_nbQueries },
+            { "http2-queries", (double) doh->d_http2Stats.d_nbQueries },
+            { "http1-200-responses", (double) doh->d_http1Stats.d_nb200Responses },
+            { "http2-200-responses", (double) doh->d_http2Stats.d_nb200Responses },
+            { "http1-400-responses", (double) doh->d_http1Stats.d_nb400Responses },
+            { "http2-400-responses", (double) doh->d_http2Stats.d_nb400Responses },
+            { "http1-403-responses", (double) doh->d_http1Stats.d_nb403Responses },
+            { "http2-403-responses", (double) doh->d_http2Stats.d_nb403Responses },
+            { "http1-500-responses", (double) doh->d_http1Stats.d_nb500Responses },
+            { "http2-500-responses", (double) doh->d_http2Stats.d_nb500Responses },
+            { "http1-502-responses", (double) doh->d_http1Stats.d_nb502Responses },
+            { "http2-502-responses", (double) doh->d_http2Stats.d_nb502Responses },
+            { "http1-other-responses", (double) doh->d_http1Stats.d_nbOtherResponses },
+            { "http2-other-responses", (double) doh->d_http2Stats.d_nbOtherResponses },
+            { "tls10-queries", (double) doh->d_tls10queries },
+            { "tls11-queries", (double) doh->d_tls11queries },
+            { "tls12-queries", (double) doh->d_tls12queries },
+            { "tls13-queries", (double) doh->d_tls13queries },
+            { "tls-unknown-queries", (double) doh->d_tlsUnknownqueries },
+            { "get-queries", (double) doh->d_getqueries },
+            { "post-queries", (double) doh->d_postqueries },
+            { "bad-requests", (double) doh->d_badrequests },
+            { "error-responses", (double) doh->d_errorresponses },
+            { "valid-responses", (double) doh->d_validresponses }
+          };
+          dohs.push_back(obj);
+        }
+      }
+#endif /* HAVE_DNS_OVER_HTTPS */
+
       Json::array pools;
       auto localPools = g_pools.getLocal();
       num=0;
@@ -725,7 +878,8 @@ static void connectionThread(int sock, ComboAddress remote)
         { "cache-hit-response-rules", cacheHitResponseRules},
         { "self-answered-response-rules", selfAnsweredResponseRules},
         { "acl", acl},
-        { "local", localaddresses}
+        { "local", localaddresses},
+        { "dohFrontends", dohs }
       };
       resp.headers["Content-Type"] = "application/json";
       resp.body=my_json.dump();
index 34f876e7ba7a216a3091459a77d38f9f39a0e5e5..6140b8e014951f072c220c268881e0d081895ed3 100644 (file)
@@ -778,6 +778,12 @@ Status, Statistics and More
 
   Print the list of all availables DNS over HTTPS frontends.
 
+.. function:: showDOHResponseCodes()
+
+  .. versionadded:: 1.4.0
+
+  Print the HTTP response codes statistics for all availables DNS over HTTPS frontends.
+
 .. function:: showResponseLatency()
 
   Show a plot of the response time latency distribution
index 4e585d4afa58c96b7c2ef445bf6368a8cd8bdc9f..c6b9924c20d15974cb2dd9b508ae062f18684b29 100644 (file)
@@ -264,11 +264,64 @@ static int processDOHQuery(DOHUnit* du)
   return 0;
 }
 
+static void on_response_ready_cb(struct st_h2o_filter_t *self, h2o_req_t *req, h2o_ostream_t **slot)
+{
+  if (req == nullptr) {
+    return;
+  }
+
+  DOHServerConfig* dsc = reinterpret_cast<DOHServerConfig*>(req->conn->ctx->storage.entries[0].data);
+
+  DOHFrontend::HTTPVersionStats* stats = nullptr;
+  if (req->version < 0x200) {
+    /* HTTP 1.x */
+    stats = &dsc->df->d_http1Stats;
+  }
+  else {
+    /* HTTP 2.0 */
+    stats = &dsc->df->d_http2Stats;
+  }
+
+  switch (req->res.status) {
+  case 200:
+    ++stats->d_nb200Responses;
+    break;
+  case 400:
+    ++stats->d_nb400Responses;
+    break;
+  case 403:
+    ++stats->d_nb403Responses;
+    break;
+  case 500:
+    ++stats->d_nb500Responses;
+    break;
+  case 502:
+    ++stats->d_nb502Responses;
+    break;
+  default:
+    ++stats->d_nbOtherResponses;
+    break;
+  }
+
+  h2o_setup_next_ostream(req, slot);
+}
+
 static h2o_pathconf_t *register_handler(h2o_hostconf_t *hostconf, const char *path, int (*on_req)(h2o_handler_t *, h2o_req_t *))
 {
   h2o_pathconf_t *pathconf = h2o_config_register_path(hostconf, path, 0);
+  if (pathconf == nullptr) {
+    return pathconf;
+  }
+  h2o_filter_t *filter = h2o_create_filter(pathconf, sizeof(*filter));
+  if (filter) {
+    filter->on_setup_ostream = on_response_ready_cb;
+  }
+
   h2o_handler_t *handler = h2o_create_handler(pathconf, sizeof(*handler));
-  handler->on_req = on_req;
+  if (handler != nullptr) {
+    handler->on_req = on_req;
+  }
+
   return pathconf;
 }
 
@@ -354,9 +407,9 @@ try
   if (h2o_memis(req->method.base, req->method.len, H2O_STRLIT("POST"))) {
     ++dsc->df->d_postqueries;
     if(req->version >= 0x0200)
-      ++dsc->df->d_http2queries;
+      ++dsc->df->d_http2Stats.d_nbQueries;
     else
-      ++dsc->df->d_http1queries;
+      ++dsc->df->d_http1Stats.d_nbQueries;
 
     std::string query;
     query.reserve(req->entity.len + 512);
@@ -393,9 +446,9 @@ try
       else {
         ++dsc->df->d_getqueries;
         if(req->version >= 0x0200)
-          ++dsc->df->d_http2queries;
+          ++dsc->df->d_http2Stats.d_nbQueries;
         else
-          ++dsc->df->d_http1queries;
+          ++dsc->df->d_http1Stats.d_nbQueries;
 
         doh_dispatch_query(dsc, self, req, std::move(decoded), local, remote);
       }
index 2fa36fa8e32f3c49363d202baef2304e774e7c1e..d6bea0bb04a4312a1f08dbf3d830c8207710b5e0 100644 (file)
@@ -16,8 +16,6 @@ struct DOHFrontend
   std::vector<std::string> d_urls;
 
   std::atomic<uint64_t> d_httpconnects;   // number of TCP/IP connections established
-  std::atomic<uint64_t> d_http1queries;   // valid DNS queries received via HTTP1
-  std::atomic<uint64_t> d_http2queries;   // valid DNS queries received via HTTP2
   std::atomic<uint64_t> d_tls10queries;   // valid DNS queries received via TLSv1.0
   std::atomic<uint64_t> d_tls11queries;   // valid DNS queries received via TLSv1.1
   std::atomic<uint64_t> d_tls12queries;   // valid DNS queries received via TLSv1.2
@@ -30,6 +28,20 @@ struct DOHFrontend
   std::atomic<uint64_t> d_errorresponses; // dnsdist set 'error' on response
   std::atomic<uint64_t> d_validresponses; // valid responses sent out
 
+  struct HTTPVersionStats
+  {
+    std::atomic<uint64_t> d_nbQueries{0}; // valid DNS queries received
+    std::atomic<uint64_t> d_nb200Responses{0};
+    std::atomic<uint64_t> d_nb400Responses{0};
+    std::atomic<uint64_t> d_nb403Responses{0};
+    std::atomic<uint64_t> d_nb500Responses{0};
+    std::atomic<uint64_t> d_nb502Responses{0};
+    std::atomic<uint64_t> d_nbOtherResponses{0};
+  };
+
+  HTTPVersionStats d_http1Stats;
+  HTTPVersionStats d_http2Stats;
+
 #ifndef HAVE_DNS_OVER_HTTPS
   void setup()
   {