]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/ws-recursor.cc
Merge pull request #9073 from pieterlexis/runtime-dirs-virtual-hosting
[thirdparty/pdns.git] / pdns / ws-recursor.cc
index fefb03bb06bd4ba2ae2e0ced85d3484cef59567c..a074460c2f1f587191feefbaff1c052194981273 100644 (file)
@@ -30,6 +30,7 @@
 #include <iostream>
 #include "iputils.hh"
 #include "rec_channel.hh"
+#include "rec_metrics.hh"
 #include "arguments.hh"
 #include "misc.hh"
 #include "syncres.hh"
@@ -381,9 +382,9 @@ static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) {
   DNSName canon = apiNameToDNSName(req->getvars["domain"]);
   bool subtree = (req->getvars.count("subtree") > 0 && req->getvars["subtree"].compare("true") == 0);
 
-  int count = broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon, subtree));
-  count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, canon, subtree));
-  count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon, subtree));
+  int count = broadcastAccFunction<uint64_t>(std::bind(pleaseWipeCache, canon, subtree, 0xffff));
+  count += broadcastAccFunction<uint64_t>(std::bind(pleaseWipePacketCache, canon, subtree, 0xffff));
+  count += broadcastAccFunction<uint64_t>(std::bind(pleaseWipeAndCountNegCache, canon, subtree));
   resp->setBody(Json::object {
     { "count", count },
     { "result", "Flushed cache." }
@@ -403,8 +404,8 @@ static void apiServerRPZStats(HttpRequest* req, HttpResponse* resp) {
     auto zone = luaconf->dfe.getZone(i);
     if (zone == nullptr)
       continue;
-    auto name = zone->getName();
-    auto stats = getRPZZoneStats(*name);
+    const auto& name = zone->getName();
+    auto stats = getRPZZoneStats(name);
     if (stats == nullptr)
       continue;
     Json::object zoneInfo = {
@@ -415,11 +416,55 @@ static void apiServerRPZStats(HttpRequest* req, HttpResponse* resp) {
       {"last_update", (double)stats->d_lastUpdate},
       {"serial", (double)stats->d_serial},
     };
-    ret[*name] = zoneInfo;
+    ret[name] = zoneInfo;
   }
   resp->setBody(ret);
 }
 
+
+static void prometheusMetrics(HttpRequest *req, HttpResponse *resp) {
+    static MetricDefinitionStorage s_metricDefinitions;
+
+    if (req->method != "GET")
+        throw HttpMethodNotAllowedException();
+
+    registerAllStats();
+
+
+    std::ostringstream output;
+    typedef map <string, string> varmap_t;
+    varmap_t varmap = getAllStatsMap(
+            StatComponent::API); // Argument controls blacklisting of any stats. So stats-api-blacklist will be used to block returned stats.
+    for (const auto &tup :  varmap) {
+        std::string metricName = tup.first;
+
+        // Prometheus suggest using '_' instead of '-'
+        std::string prometheusMetricName = "pdns_recursor_" + boost::replace_all_copy(metricName, "-", "_");
+
+        MetricDefinition metricDetails;
+
+        if (s_metricDefinitions.getMetricDetails(metricName, metricDetails)) {
+          std::string prometheusTypeName = s_metricDefinitions.getPrometheusStringMetricType(
+                  metricDetails.prometheusType);
+
+          if (prometheusTypeName.empty()) {
+            continue;
+          }
+
+          // for these we have the help and types encoded in the sources:
+          output << "# HELP " << prometheusMetricName << " " << metricDetails.description << "\n";
+          output << "# TYPE " << prometheusMetricName << " " << prometheusTypeName << "\n";
+        }
+        output << prometheusMetricName << " " << tup.second << "\n";
+    }
+
+    resp->body = output.str();
+    resp->headers["Content-Type"] = "text/plain";
+    resp->status = 200;
+
+}
+
+
 #include "htmlfiles.h"
 
 static void serveStuff(HttpRequest* req, HttpResponse* resp)
@@ -455,7 +500,7 @@ RecursorWebServer::RecursorWebServer(FDMultiplexer* fdm)
 {
   registerAllStats();
 
-  d_ws = new AsyncWebServer(fdm, arg()["webserver-address"], arg().asNum("webserver-port"));
+  d_ws = std::unique_ptr<AsyncWebServer>(new AsyncWebServer(fdm, arg()["webserver-address"], arg().asNum("webserver-port")));
   d_ws->setApiKey(arg()["api-key"]);
   d_ws->setPassword(arg()["webserver-password"]);
   d_ws->setLogLevel(arg()["webserver-loglevel"]);
@@ -467,7 +512,7 @@ RecursorWebServer::RecursorWebServer(FDMultiplexer* fdm)
   d_ws->bind();
 
   // legacy dispatch
-  d_ws->registerApiHandler("/jsonstat", boost::bind(&RecursorWebServer::jsonstat, this, _1, _2), true);
+  d_ws->registerApiHandler("/jsonstat", std::bind(&RecursorWebServer::jsonstat, this, std::placeholders::_1, std::placeholders::_2), true);
   d_ws->registerApiHandler("/api/v1/servers/localhost/cache/flush", &apiServerCacheFlush);
   d_ws->registerApiHandler("/api/v1/servers/localhost/config/allow-from", &apiServerConfigAllowFrom);
   d_ws->registerApiHandler("/api/v1/servers/localhost/config", &apiServerConfig);
@@ -483,6 +528,7 @@ RecursorWebServer::RecursorWebServer(FDMultiplexer* fdm)
   for(const auto& u : g_urlmap) 
     d_ws->registerWebHandler("/"+u.first, serveStuff);
   d_ws->registerWebHandler("/", serveStuff);
+  d_ws->registerWebHandler("/metrics", prometheusMetrics);
   d_ws->go();
 }
 
@@ -618,7 +664,7 @@ void AsyncServerNewConnectionMT(void *p) {
 void AsyncServer::asyncWaitForConnections(FDMultiplexer* fdm, const newconnectioncb_t& callback)
 {
   d_asyncNewConnectionCallback = callback;
-  fdm->addReadFD(d_server_socket.getHandle(), boost::bind(&AsyncServer::newConnection, this));
+  fdm->addReadFD(d_server_socket.getHandle(), std::bind(&AsyncServer::newConnection, this));
 }
 
 void AsyncServer::newConnection()
@@ -697,5 +743,5 @@ void AsyncWebServer::go() {
   auto server = std::dynamic_pointer_cast<AsyncServer>(d_server);
   if (!server)
     return;
-  server->asyncWaitForConnections(d_fdm, boost::bind(&AsyncWebServer::serveConnection, this, _1));
+  server->asyncWaitForConnections(d_fdm, std::bind(&AsyncWebServer::serveConnection, this, std::placeholders::_1));
 }