From: Mischan Toosarani-Hausberger Date: Mon, 1 Jun 2020 20:26:51 +0000 (+0200) Subject: Implemented prometheus metrics-endpoint for auth X-Git-Tag: dnsdist-1.5.0-rc3~22^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dec696100c09254b5a2021dc4082b43259dd0a24;p=thirdparty%2Fpdns.git Implemented prometheus metrics-endpoint for auth --- diff --git a/docs/http-api/index.rst b/docs/http-api/index.rst index ae62df5c74..decfd4dc26 100644 --- a/docs/http-api/index.rst +++ b/docs/http-api/index.rst @@ -21,6 +21,276 @@ The following webserver related configuration items are available: * :ref:`setting-webserver-allow-from`: Netmasks that are allowed to connect to the webserver * :ref:`setting-webserver-max-bodysize`: Maximum request/response body size in megabytes + +Metrics Endpoint +---------------- + +The webserver exposes a metrics-endpoint that follows the `prometheus exposition-format `_ on path ``/metrics``. + +The metrics listed are equivalent to the variables section on the index-page of the webserver (prefixed with ``pdns_auth_`` and replacing dashes with underscores). + +A simple ``GET`` request will return a response similar to the following: + +.. http:get:: /metrics + + HTTP/1.1 200 OK + Connection: close + Content-Length: 12044 + Content-Type: text/plain + Server: PowerDNS/0.0.19015.0.master.ge719aae4e8 + + # HELP pdns_auth_corrupt_packets Number of corrupt packets received + # TYPE pdns_auth_corrupt_packets counter + pdns_auth_corrupt_packets 0 + # HELP pdns_auth_deferred_cache_inserts Amount of cache inserts that were deferred because of maintenance + # TYPE pdns_auth_deferred_cache_inserts counter + pdns_auth_deferred_cache_inserts 0 + # HELP pdns_auth_deferred_cache_lookup Amount of cache lookups that were deferred because of maintenance + # TYPE pdns_auth_deferred_cache_lookup counter + pdns_auth_deferred_cache_lookup 0 + # HELP pdns_auth_deferred_packetcache_inserts Amount of packet cache inserts that were deferred because of maintenance + # TYPE pdns_auth_deferred_packetcache_inserts counter + pdns_auth_deferred_packetcache_inserts 0 + # HELP pdns_auth_deferred_packetcache_lookup Amount of packet cache lookups that were deferred because of maintenance + # TYPE pdns_auth_deferred_packetcache_lookup counter + pdns_auth_deferred_packetcache_lookup 0 + # HELP pdns_auth_dnsupdate_answers DNS update packets successfully answered. + # TYPE pdns_auth_dnsupdate_answers counter + pdns_auth_dnsupdate_answers 0 + # HELP pdns_auth_dnsupdate_changes DNS update changes to records in total. + # TYPE pdns_auth_dnsupdate_changes counter + pdns_auth_dnsupdate_changes 0 + # HELP pdns_auth_dnsupdate_queries DNS update packets received. + # TYPE pdns_auth_dnsupdate_queries counter + pdns_auth_dnsupdate_queries 0 + # HELP pdns_auth_dnsupdate_refused DNS update packets that are refused. + # TYPE pdns_auth_dnsupdate_refused counter + pdns_auth_dnsupdate_refused 0 + # HELP pdns_auth_incoming_notifications NOTIFY packets received. + # TYPE pdns_auth_incoming_notifications counter + pdns_auth_incoming_notifications 0 + # HELP pdns_auth_overload_drops Queries dropped because backends overloaded + # TYPE pdns_auth_overload_drops counter + pdns_auth_overload_drops 0 + # HELP pdns_auth_packetcache_hit Number of hits on the packet cache + # TYPE pdns_auth_packetcache_hit counter + pdns_auth_packetcache_hit 0 + # HELP pdns_auth_packetcache_miss Number of misses on the packet cache + # TYPE pdns_auth_packetcache_miss counter + pdns_auth_packetcache_miss 0 + # HELP pdns_auth_packetcache_size Number of entries in the packet cache + # TYPE pdns_auth_packetcache_size counter + pdns_auth_packetcache_size 0 + # HELP pdns_auth_query_cache_hit Number of hits on the query cache + # TYPE pdns_auth_query_cache_hit counter + pdns_auth_query_cache_hit 0 + # HELP pdns_auth_query_cache_miss Number of misses on the query cache + # TYPE pdns_auth_query_cache_miss counter + pdns_auth_query_cache_miss 0 + # HELP pdns_auth_query_cache_size Number of entries in the query cache + # TYPE pdns_auth_query_cache_size counter + pdns_auth_query_cache_size 0 + # HELP pdns_auth_rd_queries Number of recursion desired questions + # TYPE pdns_auth_rd_queries counter + pdns_auth_rd_queries 0 + # HELP pdns_auth_recursing_answers Number of recursive answers sent out + # TYPE pdns_auth_recursing_answers counter + pdns_auth_recursing_answers 0 + # HELP pdns_auth_recursing_questions Number of questions sent to recursor + # TYPE pdns_auth_recursing_questions counter + pdns_auth_recursing_questions 0 + # HELP pdns_auth_recursion_unanswered Number of packets unanswered by configured recursor + # TYPE pdns_auth_recursion_unanswered counter + pdns_auth_recursion_unanswered 0 + # HELP pdns_auth_security_status Security status based on regular polling + # TYPE pdns_auth_security_status counter + pdns_auth_security_status 0 + # HELP pdns_auth_servfail_packets Number of times a server-failed packet was sent out + # TYPE pdns_auth_servfail_packets counter + pdns_auth_servfail_packets 0 + # HELP pdns_auth_signatures Number of DNSSEC signatures made + # TYPE pdns_auth_signatures counter + pdns_auth_signatures 0 + # HELP pdns_auth_tcp_answers Number of answers sent out over TCP + # TYPE pdns_auth_tcp_answers counter + pdns_auth_tcp_answers 0 + # HELP pdns_auth_tcp_answers_bytes Total size of answers sent out over TCP + # TYPE pdns_auth_tcp_answers_bytes counter + pdns_auth_tcp_answers_bytes 0 + # HELP pdns_auth_tcp_queries Number of TCP queries received + # TYPE pdns_auth_tcp_queries counter + pdns_auth_tcp_queries 0 + # HELP pdns_auth_tcp4_answers Number of IPv4 answers sent out over TCP + # TYPE pdns_auth_tcp4_answers counter + pdns_auth_tcp4_answers 0 + # HELP pdns_auth_tcp4_answers_bytes Total size of answers sent out over TCPv4 + # TYPE pdns_auth_tcp4_answers_bytes counter + pdns_auth_tcp4_answers_bytes 0 + # HELP pdns_auth_tcp4_queries Number of IPv4 TCP queries received + # TYPE pdns_auth_tcp4_queries counter + pdns_auth_tcp4_queries 0 + # HELP pdns_auth_tcp6_answers Number of IPv6 answers sent out over TCP + # TYPE pdns_auth_tcp6_answers counter + pdns_auth_tcp6_answers 0 + # HELP pdns_auth_tcp6_answers_bytes Total size of answers sent out over TCPv6 + # TYPE pdns_auth_tcp6_answers_bytes counter + pdns_auth_tcp6_answers_bytes 0 + # HELP pdns_auth_tcp6_queries Number of IPv6 TCP queries received + # TYPE pdns_auth_tcp6_queries counter + pdns_auth_tcp6_queries 0 + # HELP pdns_auth_timedout_packets Number of packets which weren't answered within timeout set + # TYPE pdns_auth_timedout_packets counter + pdns_auth_timedout_packets 0 + # HELP pdns_auth_udp_answers Number of answers sent out over UDP + # TYPE pdns_auth_udp_answers counter + pdns_auth_udp_answers 0 + # HELP pdns_auth_udp_answers_bytes Total size of answers sent out over UDP + # TYPE pdns_auth_udp_answers_bytes counter + pdns_auth_udp_answers_bytes 0 + # HELP pdns_auth_udp_do_queries Number of UDP queries received with DO bit + # TYPE pdns_auth_udp_do_queries counter + pdns_auth_udp_do_queries 0 + # HELP pdns_auth_udp_queries Number of UDP queries received + # TYPE pdns_auth_udp_queries counter + pdns_auth_udp_queries 0 + # HELP pdns_auth_udp4_answers Number of IPv4 answers sent out over UDP + # TYPE pdns_auth_udp4_answers counter + pdns_auth_udp4_answers 0 + # HELP pdns_auth_udp4_answers_bytes Total size of answers sent out over UDPv4 + # TYPE pdns_auth_udp4_answers_bytes counter + pdns_auth_udp4_answers_bytes 0 + # HELP pdns_auth_udp4_queries Number of IPv4 UDP queries received + # TYPE pdns_auth_udp4_queries counter + pdns_auth_udp4_queries 0 + # HELP pdns_auth_udp6_answers Number of IPv6 answers sent out over UDP + # TYPE pdns_auth_udp6_answers counter + pdns_auth_udp6_answers 0 + # HELP pdns_auth_udp6_answers_bytes Total size of answers sent out over UDPv6 + # TYPE pdns_auth_udp6_answers_bytes counter + pdns_auth_udp6_answers_bytes 0 + # HELP pdns_auth_udp6_queries Number of IPv6 UDP queries received + # TYPE pdns_auth_udp6_queries counter + pdns_auth_udp6_queries 0 + # HELP pdns_auth_cpu_iowait Time spent waiting for I/O to complete by the whole system, in units of USER_HZ + # TYPE pdns_auth_cpu_iowait counter + pdns_auth_cpu_iowait 2739 + # HELP pdns_auth_cpu_steal Stolen time, which is the time spent by the whole system in other operating systems when running in a virtualized environment, in units of USER_HZ + # TYPE pdns_auth_cpu_steal counter + pdns_auth_cpu_steal 0 + # HELP pdns_auth_fd_usage Number of open filedescriptors + # TYPE pdns_auth_fd_usage gauge + pdns_auth_fd_usage 26 + # HELP pdns_auth_key_cache_size Number of entries in the key cache + # TYPE pdns_auth_key_cache_size gauge + pdns_auth_key_cache_size 0 + # HELP pdns_auth_latency Average number of microseconds needed to answer a question + # TYPE pdns_auth_latency gauge + pdns_auth_latency 0 + # HELP pdns_auth_meta_cache_size Number of entries in the metadata cache + # TYPE pdns_auth_meta_cache_size gauge + pdns_auth_meta_cache_size 0 + # HELP pdns_auth_open_tcp_connections Number of currently open TCP connections + # TYPE pdns_auth_open_tcp_connections gauge + pdns_auth_open_tcp_connections 0 + # HELP pdns_auth_qsize_q Number of questions waiting for database attention + # TYPE pdns_auth_qsize_q gauge + pdns_auth_qsize_q 0 + # HELP pdns_auth_real_memory_usage Actual unique use of memory in bytes (approx) + # TYPE pdns_auth_real_memory_usage gauge + pdns_auth_real_memory_usage 133189632 + # HELP pdns_auth_ring_logmessages_capacity Maximum number of entries in the logmessages ring + # TYPE pdns_auth_ring_logmessages_capacity counter + pdns_auth_ring_logmessages_capacity 10000 + # HELP pdns_auth_ring_logmessages_size Number of entries in the logmessages ring + # TYPE pdns_auth_ring_logmessages_size counter + pdns_auth_ring_logmessages_size 7 + # HELP pdns_auth_ring_noerror_queries_capacity Maximum number of entries in the noerror-queries ring + # TYPE pdns_auth_ring_noerror_queries_capacity counter + pdns_auth_ring_noerror_queries_capacity 10000 + # HELP pdns_auth_ring_noerror_queries_size Number of entries in the noerror-queries ring + # TYPE pdns_auth_ring_noerror_queries_size counter + pdns_auth_ring_noerror_queries_size 0 + # HELP pdns_auth_ring_nxdomain_queries_capacity Maximum number of entries in the nxdomain-queries ring + # TYPE pdns_auth_ring_nxdomain_queries_capacity counter + pdns_auth_ring_nxdomain_queries_capacity 10000 + # HELP pdns_auth_ring_nxdomain_queries_size Number of entries in the nxdomain-queries ring + # TYPE pdns_auth_ring_nxdomain_queries_size counter + pdns_auth_ring_nxdomain_queries_size 0 + # HELP pdns_auth_ring_queries_capacity Maximum number of entries in the queries ring + # TYPE pdns_auth_ring_queries_capacity counter + pdns_auth_ring_queries_capacity 10000 + # HELP pdns_auth_ring_queries_size Number of entries in the queries ring + # TYPE pdns_auth_ring_queries_size counter + pdns_auth_ring_queries_size 0 + # HELP pdns_auth_ring_remotes_capacity Maximum number of entries in the remotes ring + # TYPE pdns_auth_ring_remotes_capacity counter + pdns_auth_ring_remotes_capacity 10000 + # HELP pdns_auth_ring_remotes_corrupt_capacity Maximum number of entries in the remotes-corrupt ring + # TYPE pdns_auth_ring_remotes_corrupt_capacity counter + pdns_auth_ring_remotes_corrupt_capacity 10000 + # HELP pdns_auth_ring_remotes_corrupt_size Number of entries in the remotes-corrupt ring + # TYPE pdns_auth_ring_remotes_corrupt_size counter + pdns_auth_ring_remotes_corrupt_size 0 + # HELP pdns_auth_ring_remotes_size Number of entries in the remotes ring + # TYPE pdns_auth_ring_remotes_size counter + pdns_auth_ring_remotes_size 0 + # HELP pdns_auth_ring_remotes_unauth_capacity Maximum number of entries in the remotes-unauth ring + # TYPE pdns_auth_ring_remotes_unauth_capacity counter + pdns_auth_ring_remotes_unauth_capacity 10000 + # HELP pdns_auth_ring_remotes_unauth_size Number of entries in the remotes-unauth ring + # TYPE pdns_auth_ring_remotes_unauth_size counter + pdns_auth_ring_remotes_unauth_size 0 + # HELP pdns_auth_ring_servfail_queries_capacity Maximum number of entries in the servfail-queries ring + # TYPE pdns_auth_ring_servfail_queries_capacity counter + pdns_auth_ring_servfail_queries_capacity 10000 + # HELP pdns_auth_ring_servfail_queries_size Number of entries in the servfail-queries ring + # TYPE pdns_auth_ring_servfail_queries_size counter + pdns_auth_ring_servfail_queries_size 0 + # HELP pdns_auth_ring_unauth_queries_capacity Maximum number of entries in the unauth-queries ring + # TYPE pdns_auth_ring_unauth_queries_capacity counter + pdns_auth_ring_unauth_queries_capacity 10000 + # HELP pdns_auth_ring_unauth_queries_size Number of entries in the unauth-queries ring + # TYPE pdns_auth_ring_unauth_queries_size counter + pdns_auth_ring_unauth_queries_size 0 + # HELP pdns_auth_signature_cache_size Number of entries in the signature cache + # TYPE pdns_auth_signature_cache_size gauge + pdns_auth_signature_cache_size 0 + # HELP pdns_auth_sys_msec Number of msec spent in system time + # TYPE pdns_auth_sys_msec counter + pdns_auth_sys_msec 56 + # HELP pdns_auth_udp_in_errors UDP 'in' errors + # TYPE pdns_auth_udp_in_errors counter + pdns_auth_udp_in_errors 151 + # HELP pdns_auth_udp_noport_errors UDP 'noport' errors + # TYPE pdns_auth_udp_noport_errors counter + pdns_auth_udp_noport_errors 9 + # HELP pdns_auth_udp_recvbuf_errors UDP 'recvbuf' errors + # TYPE pdns_auth_udp_recvbuf_errors counter + pdns_auth_udp_recvbuf_errors 0 + # HELP pdns_auth_udp_sndbuf_errors UDP 'sndbuf' errors + # TYPE pdns_auth_udp_sndbuf_errors counter + pdns_auth_udp_sndbuf_errors 9 + # HELP pdns_auth_uptime Uptime of process in seconds + # TYPE pdns_auth_uptime counter + pdns_auth_uptime 672 + # HELP pdns_auth_user_msec Number of msec spent in user time + # TYPE pdns_auth_user_msec counter + pdns_auth_user_msec 48 + + +Prometheus can then be configured to scrape metrics from this endpoint using a simple job description like the following: + +.. prometheus scrape-job:: + + scrape_configs: + - job_name: 'pdns_auth' + scrape_interval: 1m + static_configs: + - targets: ['pdns_auth_host:pdns_auth_ws_port'] + +Further details can be gathered from the `prometheus docs `_. + + Enabling the API ---------------- diff --git a/pdns/common_startup.cc b/pdns/common_startup.cc index f5a777c143..1c67740d22 100644 --- a/pdns/common_startup.cc +++ b/pdns/common_startup.cc @@ -333,9 +333,9 @@ void declareStats(void) S.declare("tcp6-queries","Number of IPv6 TCP queries received"); S.declare("tcp6-answers","Number of IPv6 answers sent out over TCP"); - S.declare("open-tcp-connections","Number of currently open TCP connections", getTCPConnectionCount);; + S.declare("open-tcp-connections","Number of currently open TCP connections", getTCPConnectionCount, StatType::gauge); - S.declare("qsize-q","Number of questions waiting for database attention", getQCount); + S.declare("qsize-q","Number of questions waiting for database attention", getQCount, StatType::gauge); S.declare("dnsupdate-queries", "DNS update packets received."); S.declare("dnsupdate-answers", "DNS update packets successfully answered."); @@ -344,31 +344,31 @@ void declareStats(void) S.declare("incoming-notifications", "NOTIFY packets received."); - S.declare("uptime", "Uptime of process in seconds", uptimeOfProcess); - S.declare("real-memory-usage", "Actual unique use of memory in bytes (approx)", getRealMemoryUsage); - S.declare("special-memory-usage", "Actual unique use of memory in bytes (approx)", getSpecialMemoryUsage); - S.declare("fd-usage", "Number of open filedescriptors", getOpenFileDescriptors); + S.declare("uptime", "Uptime of process in seconds", uptimeOfProcess, StatType::counter); + S.declare("real-memory-usage", "Actual unique use of memory in bytes (approx)", getRealMemoryUsage, StatType::gauge); + S.declare("special-memory-usage", "Actual unique use of memory in bytes (approx)", getSpecialMemoryUsage, StatType::gauge); + S.declare("fd-usage", "Number of open filedescriptors", getOpenFileDescriptors, StatType::gauge); #ifdef __linux__ - S.declare("udp-recvbuf-errors", "UDP 'recvbuf' errors", udpErrorStats); - S.declare("udp-sndbuf-errors", "UDP 'sndbuf' errors", udpErrorStats); - S.declare("udp-noport-errors", "UDP 'noport' errors", udpErrorStats); - S.declare("udp-in-errors", "UDP 'in' errors", udpErrorStats); + S.declare("udp-recvbuf-errors", "UDP 'recvbuf' errors", udpErrorStats, StatType::counter); + S.declare("udp-sndbuf-errors", "UDP 'sndbuf' errors", udpErrorStats, StatType::counter); + S.declare("udp-noport-errors", "UDP 'noport' errors", udpErrorStats, StatType::counter); + S.declare("udp-in-errors", "UDP 'in' errors", udpErrorStats, StatType::counter); #endif - S.declare("sys-msec", "Number of msec spent in system time", getSysUserTimeMsec); - S.declare("user-msec", "Number of msec spent in user time", getSysUserTimeMsec); + S.declare("sys-msec", "Number of msec spent in system time", getSysUserTimeMsec, StatType::counter); + S.declare("user-msec", "Number of msec spent in user time", getSysUserTimeMsec, StatType::counter); #ifdef __linux__ - S.declare("cpu-iowait", "Time spent waiting for I/O to complete by the whole system, in units of USER_HZ", getCPUIOWait); - S.declare("cpu-steal", "Stolen time, which is the time spent by the whole system in other operating systems when running in a virtualized environment, in units of USER_HZ", getCPUSteal); + S.declare("cpu-iowait", "Time spent waiting for I/O to complete by the whole system, in units of USER_HZ", getCPUIOWait, StatType::counter); + S.declare("cpu-steal", "Stolen time, which is the time spent by the whole system in other operating systems when running in a virtualized environment, in units of USER_HZ", getCPUSteal, StatType::counter); #endif - S.declare("meta-cache-size", "Number of entries in the metadata cache", DNSSECKeeper::dbdnssecCacheSizes); - S.declare("key-cache-size", "Number of entries in the key cache", DNSSECKeeper::dbdnssecCacheSizes); - S.declare("signature-cache-size", "Number of entries in the signature cache", signatureCacheSize); + S.declare("meta-cache-size", "Number of entries in the metadata cache", DNSSECKeeper::dbdnssecCacheSizes, StatType::gauge); + S.declare("key-cache-size", "Number of entries in the key cache", DNSSECKeeper::dbdnssecCacheSizes, StatType::gauge); + S.declare("signature-cache-size", "Number of entries in the signature cache", signatureCacheSize, StatType::gauge); S.declare("servfail-packets","Number of times a server-failed packet was sent out"); - S.declare("latency","Average number of microseconds needed to answer a question", getLatency); + S.declare("latency","Average number of microseconds needed to answer a question", getLatency, StatType::gauge); S.declare("timedout-packets","Number of packets which weren't answered within timeout set"); S.declare("security-status", "Security status based on regular polling"); S.declareDNSNameQTypeRing("queries","UDP Queries Received"); diff --git a/pdns/statbag.cc b/pdns/statbag.cc index 9d89d15b77..3dd5a8de12 100644 --- a/pdns/statbag.cc +++ b/pdns/statbag.cc @@ -97,18 +97,25 @@ string StatBag::getDescrip(const string &item) return d_keyDescrips[item]; } +StatType StatBag::getStatType(const string &item) +{ + exists(item); + return d_statTypes[item]; +} + void StatBag::declare(const string &key, const string &descrip) { auto i=make_unique(0); d_stats[key]=std::move(i); d_keyDescrips[key]=descrip; + d_statTypes[key]=StatType::counter; } -void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func) +void StatBag::declare(const string &key, const string &descrip, StatBag::func_t func, StatType statType) { - d_funcstats[key]=func; d_keyDescrips[key]=descrip; + d_statTypes[key]=statType; } @@ -237,8 +244,8 @@ vector >StatRing::get() const void StatBag::registerRingStats(const string& name) { - declare("ring-" + name + "-size", "Number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast(getRingEntriesCount(name)); }); - declare("ring-" + name + "-capacity", "Maximum number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast(getRingSize(name)); }); + declare("ring-" + name + "-size", "Number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast(getRingEntriesCount(name)); }, StatType::counter); + declare("ring-" + name + "-capacity", "Maximum number of entries in the " + name + " ring", [this,name](const std::string&) { return static_cast(getRingSize(name)); }, StatType::counter); } void StatBag::declareRing(const string &name, const string &help, unsigned int size) diff --git a/pdns/statbag.hh b/pdns/statbag.hh index 982f739dfb..3026912590 100644 --- a/pdns/statbag.hh +++ b/pdns/statbag.hh @@ -62,12 +62,17 @@ private: string d_help; }; +enum class StatType : uint8_t { + counter = 1, + gauge = 2, +}; //! use this to gather and query statistics class StatBag { map> d_stats; map d_keyDescrips; + map d_statTypes; map >d_rings; map >d_comboRings; map > >d_dnsnameqtyperings; @@ -83,7 +88,7 @@ public: StatBag(); //!< Naked constructor. You need to declare keys before this class becomes useful ~StatBag(); void declare(const string &key, const string &descrip=""); //!< Before you can store or access a key, you need to declare it - void declare(const string &key, const string &descrip, func_t func); //!< Before you can store or access a key, you need to declare it + void declare(const string &key, const string &descrip, func_t func, StatType statType); //!< Before you can store or access a key, you need to declare it void declareRing(const string &name, const string &title, unsigned int size=10000); void declareComboRing(const string &name, const string &help, unsigned int size=10000); @@ -131,6 +136,7 @@ public: string directory(); //!< Returns a list of all data stored vector getEntries(); //!< returns a vector with datums (items) string getDescrip(const string &item); //!< Returns the description of this datum/item + StatType getStatType(const string &item); //!< Returns the stats type for the metrics endpoint void exists(const string &key); //!< call this function to throw an exception in case a key does not exist inline void deposit(const string &key, int value); //!< increment the statistics behind this key by value amount inline void inc(const string &key); //!< increase this key's value by one diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index de5fa00840..864a1b586e 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -2253,6 +2253,35 @@ static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) { }); } +static std::ostream& operator<<(std::ostream& os, StatType statType) +{ + switch (statType) + { + case StatType::counter: return os << "counter"; + case StatType::gauge: return os << "gauge"; + }; + return os << static_cast(statType); +} + +static void prometheusMetrics(HttpRequest* req, HttpResponse* resp) { + if (req->method != "GET") + throw HttpMethodNotAllowedException(); + + std::ostringstream output; + for (const auto &metricName : S.getEntries()) { + // Prometheus suggest using '_' instead of '-' + std::string prometheusMetricName = "pdns_auth_" + boost::replace_all_copy(metricName, "-", "_"); + + output << "# HELP " << prometheusMetricName << " " << S.getDescrip(metricName) << "\n"; + output << "# TYPE " << prometheusMetricName << " " << S.getStatType(metricName) << "\n"; + output << prometheusMetricName << " " << S.read(metricName) << "\n"; + } + + resp->body = output.str(); + resp->headers["Content-Type"] = "text/plain"; + resp->status = 200; +} + void AuthWebServer::cssfunction(HttpRequest* req, HttpResponse* resp) { resp->headers["Cache-Control"] = "max-age=86400"; @@ -2317,6 +2346,7 @@ void AuthWebServer::webThread() if (::arg().mustDo("webserver")) { d_ws->registerWebHandler("/style.css", std::bind(&AuthWebServer::cssfunction, this, std::placeholders::_1, std::placeholders::_2)); d_ws->registerWebHandler("/", std::bind(&AuthWebServer::indexfunction, this, std::placeholders::_1, std::placeholders::_2)); + d_ws->registerWebHandler("/metrics", prometheusMetrics); } d_ws->go(); }