From: Otto Moerbeek Date: Wed, 28 Oct 2020 09:39:23 +0000 (+0100) Subject: Allow to specify a name that is used for Prometheus export only. X-Git-Tag: dnsdist-1.6.0-alpha0~30^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=57c5fefb0f2d97e072f8a9e34a30729e6c24b52b;p=thirdparty%2Fpdns.git Allow to specify a name that is used for Prometheus export only. This can be used to specify names that are structured using Prometheus conventions. If no name Prometheus name is given, do a more thorough conversion to a name Prometheus likes by replacng any non-alnum char by an underscore. --- diff --git a/pdns/lua-recursor4.cc b/pdns/lua-recursor4.cc index 0fdf23772e..7ddd538e9e 100644 --- a/pdns/lua-recursor4.cc +++ b/pdns/lua-recursor4.cc @@ -354,8 +354,8 @@ void RecursorLua4::postPrepareContext() d_pd.push_back({"now", &g_now}); - d_lw->writeFunction("getMetric", [](const std::string& str) { - return DynMetric{getDynMetric(str)}; + d_lw->writeFunction("getMetric", [](const std::string& str, boost::optional prometheusName) { + return DynMetric{getDynMetric(str, prometheusName ? *prometheusName : "")}; }); d_lw->registerFunction("inc", &DynMetric::inc); diff --git a/pdns/rec_channel.hh b/pdns/rec_channel.hh index 09c8f1def5..3862bfeed5 100644 --- a/pdns/rec_channel.hh +++ b/pdns/rec_channel.hh @@ -72,7 +72,7 @@ public: enum class StatComponent { API, Carbon, RecControl, SNMP }; -std::map getAllStatsMap(StatComponent component); +std::map getAllStatsMap(StatComponent component, bool prometheusName = false); extern std::mutex g_carbon_config_lock; std::vector >* pleaseGetQueryRing(); std::vector >* pleaseGetServfailQueryRing(); @@ -83,7 +83,7 @@ std::vector* pleaseGetBogusRemotes(); std::vector* pleaseGetLargeAnswerRemotes(); std::vector* pleaseGetTimeouts(); DNSName getRegisteredName(const DNSName& dom); -std::atomic* getDynMetric(const std::string& str); +std::atomic* getDynMetric(const std::string& str, const std::string& prometheusName); optional getStatByName(const std::string& name); bool isStatBlacklisted(StatComponent component, const std::string& name); void blacklistStat(StatComponent component, const string& name); diff --git a/pdns/rec_channel_rec.cc b/pdns/rec_channel_rec.cc index a192962a23..7278d4eec1 100644 --- a/pdns/rec_channel_rec.cc +++ b/pdns/rec_channel_rec.cc @@ -43,7 +43,12 @@ static map d_get32bitpointers; static map*> d_getatomics; static map > d_get64bitmembers; static std::mutex d_dynmetricslock; -static map* > d_dynmetrics; +struct dynmetrics { + std::atomic *d_ptr; + std::string d_prometheusName; +}; + +static map d_dynmetrics; static std::map> s_blacklistedStats; @@ -82,16 +87,24 @@ static void addGetStat(const string& name, function f ) d_get64bitmembers[name]=f; } -std::atomic* getDynMetric(const std::string& str) +std::atomic* getDynMetric(const std::string& str, const std::string& prometheusName) { std::lock_guard l(d_dynmetricslock); auto f = d_dynmetrics.find(str); if(f != d_dynmetrics.end()) - return f->second; + return f->second.d_ptr; - auto ret = new std::atomic(); + std::string name(str); + if (!prometheusName.empty()) { + name = prometheusName; + } else { + std::replace_if(name.begin(), name.end(), [](char c){ + return !isalnum(static_cast(c));}, '_'); + } + + auto ret = dynmetrics{new std::atomic(), name}; d_dynmetrics[str]= ret; - return ret; + return ret.d_ptr; } static optional get(const string& name) @@ -106,9 +119,9 @@ static optional get(const string& name) return d_get64bitmembers.find(name)->second(); std::lock_guard l(d_dynmetricslock); - auto f =rplookup(d_dynmetrics, name); - if(f) - return (*f)->load(); + auto f = rplookup(d_dynmetrics, name); + if (f) + return f->d_ptr->load(); return ret; } @@ -118,7 +131,7 @@ optional getStatByName(const std::string& name) return get(name); } -map getAllStatsMap(StatComponent component) +map getAllStatsMap(StatComponent component, bool prometheusNames) { map ret; const auto& blacklistMap = s_blacklistedStats.at(component); @@ -144,7 +157,8 @@ map getAllStatsMap(StatComponent component) std::lock_guard l(d_dynmetricslock); for(const auto& a : d_dynmetrics) { if (blacklistMap.count(a.first) == 0) { - ret.insert({a.first, std::to_string(*a.second)}); + ret.insert({prometheusNames ? a.second.d_prometheusName : a.first, + std::to_string(*a.second.d_ptr)}); } } } diff --git a/pdns/recursordist/docs/lua-scripting/statistics.rst b/pdns/recursordist/docs/lua-scripting/statistics.rst index b37c1a3756..eafbf1be52 100644 --- a/pdns/recursordist/docs/lua-scripting/statistics.rst +++ b/pdns/recursordist/docs/lua-scripting/statistics.rst @@ -14,12 +14,16 @@ Create a custom metric with: myMetric=getMetric("myspecialmetric") -.. function:: getMetric(name) -> Metric +.. function:: getMetric(name [, prometheusName]) -> Metric Returns the :class:`Metric` object with the name ``name``, creating the metric if it does not exist. :param str name: The metric to retrieve + .. versionadded:: 4.5.0 + + :param string prometheusName: The optional Prometheus specific name. + .. class:: Metric Represents a custom metric diff --git a/pdns/ws-recursor.cc b/pdns/ws-recursor.cc index 68feb47e1a..68755465bd 100644 --- a/pdns/ws-recursor.cc +++ b/pdns/ws-recursor.cc @@ -437,13 +437,14 @@ static void prometheusMetrics(HttpRequest *req, HttpResponse *resp) { std::ostringstream output; typedef map 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. + + // Argument controls blacklisting of any stats. So + // stats-api-blacklist will be used to block returned stats. + // Second arg tells to use the prometheus names. + varmap_t varmap = getAllStatsMap(StatComponent::API, true); 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, "-", "_"); + std::string prometheusMetricName = "pdns_recursor_" + metricName; MetricDefinition metricDetails;