From 37a5c2d53d7b504dced44d1922b46f972088f1d3 Mon Sep 17 00:00:00 2001 From: Pavel Odintsov Date: Thu, 30 Aug 2018 19:00:37 +0100 Subject: [PATCH] Introduced metric description storage and improved Prometheus support --- pdns/dnsdist-web.cc | 105 +++++++++++++-------- pdns/dnsdist.cc | 2 + pdns/dnsdist.hh | 68 +++++++++++++ pdns/dnsdistdist/docs/guides/webserver.rst | 6 +- 4 files changed, 141 insertions(+), 40 deletions(-) diff --git a/pdns/dnsdist-web.cc b/pdns/dnsdist-web.cc index f1d11693f7..d9ed733413 100644 --- a/pdns/dnsdist-web.cc +++ b/pdns/dnsdist-web.cc @@ -128,7 +128,7 @@ static bool isAnAPIRequestAllowedWithWebAuth(const YaHTTP::Request& req) static bool isAStatsRequest(const YaHTTP::Request& req) { - return req.url.path == "/jsonstat" || req.url.path == "/prometheus"; + return req.url.path == "/jsonstat" || req.url.path == "/metrics"; } static bool compareAuthorization(const YaHTTP::Request& req, const string &expected_password, const string& expectedApiKey) @@ -386,70 +386,98 @@ static void connectionThread(int sock, ComboAddress remote, string password, str resp.status=404; } } - else if(req.url.path=="/prometheus") { + else if (req.url.path == "/metrics") { handleCORS(req, resp); - resp.status=200; + resp.status = 200; - ostringstream str; - for(const auto& e : g_stats.entries) { - string metricName = "dnsdist_main_" + std::get<0>(e); - boost::replace_all(metricName, "-", "_"); + std::ostringstream output; + for (const auto& e : g_stats.entries) { + std::string metricName = std::get<0>(e); + + // Prometheus suggest using '_' instead of '-' + std::string prometheusMetricName = "dnsdist_main_" + boost::replace_all_copy(metricName, "-", "_"); + + MetricDefinition metricDetails; + + if (!g_metricDefinitions.getMetricDetails(metricName, metricDetails)) { + warnlog("Do not have metric details for %s", metricName); + continue; + } // for these we have the help and types encoded in the sources: - str<<"# HELP "<(e)<<"\n"; - str<<"# TYPE "<(e)<<"\n"; - str<(&std::get<1>(e))) - str<<(*val)->load(); + output << "# HELP " << prometheusMetricName << " " << metricDetails.description << "\n"; + output << "# TYPE " << prometheusMetricName << " " << metricDetails.prometheusType << "\n"; + output << prometheusMetricName << " "; + + if (const auto& val = boost::get(&std::get<1>(e))) + output << (*val)->load(); else if (const auto& dval = boost::get(&std::get<1>(e))) - str<<**dval; + output << **dval; else - str<<(*boost::get(&std::get<1>(e)))(std::get<0>(e)); - str<<"\n"; + output << (*boost::get(&std::get<1>(e)))(std::get<0>(e)); + + output << "\n"; } + const auto states = g_dstates.getCopy(); const string statesbase = "dnsdist_main_servers_"; - for(const auto& state : states) { - string serverName = state->name.empty() ? (state->remote.toString() + ":" + std::to_string(state->remote.getPort())) : state->getName(); + + for (const auto& state : states) { + string serverName; + + if (state->name.empty()) + serverName = state->remote.toString() + ":" + std::to_string(state->remote.getPort()); + else + serverName = state->getName(); + boost::replace_all(serverName, ".", "_"); + const string label = "{server=\"" + serverName + "\"}"; - str<queries.load() <<"\n"; - str<reuseds.load() << "\n"; - str<latencyUsec/1000.0 << "\n"; - str<sendErrors.load() << "\n"; - str<outstanding.load() << "\n"; + output << statesbase << "queries" << label << " " << state->queries.load() << "\n"; + output << statesbase << "drops" << label << " " << state->reuseds.load() << "\n"; + output << statesbase << "latency" << label << " " << state->latencyUsec/1000.0 << "\n"; + output << statesbase << "senderrors" << label << " " << state->sendErrors.load() << "\n"; + output << statesbase << "outstanding" << label << " " << state->outstanding.load() << "\n"; } - for(const auto& front : g_frontends) { + + 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()); boost::replace_all(frontName, ".", "_"); string proto = (front->udpFD >= 0 ? "udp" : "tcp"); - str<<"dnsdist_main_frontend_queries{frontend=\""<queries.load() << "\n"; + + output << "dnsdist_main_frontend_queries{frontend=\"" << frontName << "\",proto=\"" << proto + << "\"} " << front->queries.load() << "\n"; } + const auto localPools = g_pools.getCopy(); const string cachebase = "dnsdist_pool_"; + for (const auto& entry : localPools) { string poolName = entry.first; boost::replace_all(poolName, ".", "_"); + if (poolName.empty()) { poolName = "_default_"; } const string label = "{pool=\"" + poolName + "\"}"; const std::shared_ptr pool = entry.second; - str<<"dnsdist_main_pools_servers"<servers.size() <<"\n"; + output << "dnsdist_main_pools_servers" << label << " " << pool->countServers(false) << "\n"; + if (pool->packetCache != nullptr) { const auto& cache = pool->packetCache; - str<getMaxEntries() << "\n"; - str<getEntriesCount() << "\n"; - str<getHits() << "\n"; - str<getMisses() << "\n"; - str<getDeferredInserts() << "\n"; - str<getDeferredLookups() << "\n"; - str<getLookupCollisions() << "\n"; - str<getInsertCollisions() << "\n"; - str<getTTLTooShorts() << "\n"; + + output << cachebase << "cache_size" <