#include "iputils.hh"
#include "lock.hh"
#include "noinitvector.hh"
+#include "stat_t.hh"
struct DNSQuestion;
std::vector<CacheShard> d_shards;
- std::atomic<uint64_t> d_deferredLookups{0};
- std::atomic<uint64_t> d_deferredInserts{0};
- std::atomic<uint64_t> d_hits{0};
- std::atomic<uint64_t> d_misses{0};
- std::atomic<uint64_t> d_insertCollisions{0};
- std::atomic<uint64_t> d_lookupCollisions{0};
- std::atomic<uint64_t> d_ttlTooShorts{0};
+ pdns::stat_t d_deferredLookups{0};
+ pdns::stat_t d_deferredInserts{0};
+ pdns::stat_t d_hits{0};
+ pdns::stat_t d_misses{0};
+ pdns::stat_t d_insertCollisions{0};
+ pdns::stat_t d_lookupCollisions{0};
+ pdns::stat_t d_ttlTooShorts{0};
size_t d_maxEntries;
uint32_t d_expungeIndex{0};
time_t now=time(0);
for(const auto& e : g_stats.entries) {
str<<namespace_name<<"."<<hostname<<"."<<instance_name<<"."<<e.first<<' ';
- if(const auto& val = boost::get<DNSDistStats::stat_t*>(&e.second))
+ if(const auto& val = boost::get<pdns::stat_t*>(&e.second))
str<<(*val)->load();
else if (const auto& dval = boost::get<double*>(&e.second))
str<<**dval;
++(dupPair.first->second);
}
- vector<pair<const char*, const std::atomic<uint64_t>&>> v{
+ vector<pair<const char*, const pdns::stat_t&>> v{
{"http-connects", doh->d_httpconnects},
{"http1-queries", doh->d_http1Stats.d_nbQueries},
{"http2-queries", doh->d_http2Stats.d_nbQueries},
boost::format flt(" %9.1f");
for(const auto& e : entries) {
string second;
- if(const auto& val = boost::get<DNSDistStats::stat_t*>(&e.second))
+ if(const auto& val = boost::get<pdns::stat_t*>(&e.second))
second=std::to_string((*val)->load());
else if (const auto& dval = boost::get<double*>(&e.second))
second=(flt % (**dval)).str();
setLuaNoSideEffect();
std::unordered_map<string,uint64_t> res;
for(const auto& entry : g_stats.entries) {
- if(const auto& val = boost::get<DNSDistStats::stat_t*>(&entry.second))
+ if(const auto& val = boost::get<pdns::stat_t*>(&entry.second))
res[entry.first] = (*val)->load();
}
return res;
#include "circular_buffer.hh"
#include "dnsname.hh"
#include "iputils.hh"
+#include "stat_t.hh"
struct Rings {
size_t loadFromFile(const std::string& filepath, const struct timespec& now);
std::vector<std::unique_ptr<Shard> > d_shards;
- std::atomic<uint64_t> d_blockingQueryInserts;
- std::atomic<uint64_t> d_blockingResponseInserts;
- std::atomic<uint64_t> d_deferredQueryInserts;
- std::atomic<uint64_t> d_deferredResponseInserts;
+ pdns::stat_t d_blockingQueryInserts;
+ pdns::stat_t d_blockingResponseInserts;
+ pdns::stat_t d_deferredQueryInserts;
+ pdns::stat_t d_deferredResponseInserts;
private:
size_t getShardId()
return SNMP_ERR_GENERR;
}
- if (const auto& val = boost::get<DNSDistStats::stat_t*>(&it->second)) {
+ if (const auto& val = boost::get<pdns::stat_t*>(&it->second)) {
return DNSDistSNMPAgent::setCounter64Value(requests, (*val)->load());
}
return SNMP_ERR_GENERR;
}
-static void registerCounter64Stat(const char* name, const oid statOID[], size_t statOIDLength, DNSDistStats::stat_t* ptr)
+static void registerCounter64Stat(const char* name, const oid statOID[], size_t statOIDLength, pdns::stat_t* ptr)
{
if (statOIDLength != OID_LENGTH(queriesOID)) {
errlog("Invalid OID for SNMP Counter64 statistic %s", name);
output << "# TYPE " << prometheusMetricName << " " << prometheusTypeName << "\n";
output << prometheusMetricName << " ";
- if (const auto& val = boost::get<DNSDistStats::stat_t*>(&std::get<1>(e)))
+ if (const auto& val = boost::get<pdns::stat_t*>(&std::get<1>(e)))
output << (*val)->load();
else if (const auto& dval = boost::get<double*>(&std::get<1>(e)))
output << **dval;
for (const auto& e : g_stats.entries) {
if (e.first == "special-memory-usage")
continue; // Too expensive for get-all
- if(const auto& val = boost::get<DNSDistStats::stat_t*>(&e.second))
+ if(const auto& val = boost::get<pdns::stat_t*>(&e.second))
obj.insert({e.first, (double)(*val)->load()});
else if (const auto& dval = boost::get<double*>(&e.second))
obj.insert({e.first, (**dval)});
if (item.first == "special-memory-usage")
continue; // Too expensive for get-all
- if(const auto& val = boost::get<DNSDistStats::stat_t*>(&item.second)) {
+ if(const auto& val = boost::get<pdns::stat_t*>(&item.second)) {
doc.push_back(Json::object {
{ "type", "StatisticItem" },
{ "name", item.first },
On the C++ side, both could be inherited from a class Rule and a class Action,
on the Lua side we can't do that. */
-using std::atomic;
using std::thread;
bool g_verbose;
}
boost::optional<uint64_t> g_maxTCPClientThreads{boost::none};
-std::atomic<uint16_t> g_cacheCleaningDelay{60};
-std::atomic<uint16_t> g_cacheCleaningPercentage{100};
+pdns::stat16_t g_cacheCleaningDelay{60};
+pdns::stat16_t g_cacheCleaningPercentage{100};
static void maintThread()
{
#include "config.h"
#include "ext/luawrapper/include/LuaContext.hpp"
-#include <atomic>
#include <mutex>
#include <string>
#include <thread>
#include "tcpiohandler.hh"
#include "uuid-utils.hh"
#include "proxy-protocol.hh"
+#include "stat_t.hh"
void carbonDumpThread();
uint64_t uptimeOfProcess(const std::string& str);
extern uint64_t getLatencyCount(const std::string&);
+using pdns::stat_t;
+
struct DNSDistStats
{
-#define CPU_LEVEL1_DCACHE_LINESIZE 64 // Until we know better via configure/getconf
-
- class stat_t {
- public:
- typedef uint64_t base_t;
- typedef std::atomic<base_t> atomic_t;
- stat_t() : stat_t(0) {
- }
- stat_t(const base_t x) {
- new(&counter) atomic_t(x);
- }
- ~stat_t() {
- reinterpret_cast<atomic_t *>(&counter)->~atomic_t();
- }
- stat_t(const stat_t&) = delete;
- base_t operator++(int) {
- return (*reinterpret_cast<atomic_t *>(&counter))++;
- }
- base_t operator++() {
- return ++(*reinterpret_cast<atomic_t *>(&counter));
- }
- base_t operator+=(const stat_t& v) {
- return (*reinterpret_cast<atomic_t *>(&counter)) += *reinterpret_cast<const atomic_t *>(&v.counter);
- }
- base_t load() const {
- return reinterpret_cast<const atomic_t *>(&counter)->load();
- }
- operator base_t() const {
- return reinterpret_cast<const atomic_t *>(&counter)->load();
- }
- //const atomic_t& operator()() { return *reinterpret_cast<const atomic_t*>(&counter); }
- private:
- typename std::aligned_storage<sizeof(base_t), CPU_LEVEL1_DCACHE_LINESIZE>::type counter;
- };
-
stat_t responses{0};
stat_t servfailResponses{0};
stat_t queries{0};
std::shared_ptr<TLSFrontend> tlsFrontend{nullptr};
std::shared_ptr<DOHFrontend> dohFrontend{nullptr};
std::string interface;
- std::atomic<uint64_t> queries{0};
- mutable std::atomic<uint64_t> responses{0};
- std::atomic<uint64_t> tcpDiedReadingQuery{0};
- std::atomic<uint64_t> tcpDiedSendingResponse{0};
- std::atomic<uint64_t> tcpGaveUp{0};
- std::atomic<uint64_t> tcpClientTimeouts{0};
- std::atomic<uint64_t> tcpDownstreamTimeouts{0};
- std::atomic<uint64_t> tcpCurrentConnections{0};
- std::atomic<uint64_t> tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption
- std::atomic<uint64_t> tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket
- std::atomic<uint64_t> tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired)
- std::atomic<uint64_t> tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one
- std::atomic<uint64_t> tls10queries{0}; // valid DNS queries received via TLSv1.0
- std::atomic<uint64_t> tls11queries{0}; // valid DNS queries received via TLSv1.1
- std::atomic<uint64_t> tls12queries{0}; // valid DNS queries received via TLSv1.2
- std::atomic<uint64_t> tls13queries{0}; // valid DNS queries received via TLSv1.3
- std::atomic<uint64_t> tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version
- std::atomic<double> tcpAvgQueriesPerConnection{0.0};
+ stat_t queries{0};
+ mutable stat_t responses{0};
+ stat_t tcpDiedReadingQuery{0};
+ stat_t tcpDiedSendingResponse{0};
+ stat_t tcpGaveUp{0};
+ stat_t tcpClientTimeouts{0};
+ stat_t tcpDownstreamTimeouts{0};
+ stat_t tcpCurrentConnections{0};
+ stat_t tlsNewSessions{0}; // A new TLS session has been negotiated, no resumption
+ stat_t tlsResumptions{0}; // A TLS session has been resumed, either via session id or via a TLS ticket
+ stat_t tlsUnknownTicketKey{0}; // A TLS ticket has been presented but we don't have the associated key (might have expired)
+ stat_t tlsInactiveTicketKey{0}; // A TLS ticket has been successfully resumed but the key is no longer active, we should issue a new one
+ stat_t tls10queries{0}; // valid DNS queries received via TLSv1.0
+ stat_t tls11queries{0}; // valid DNS queries received via TLSv1.1
+ stat_t tls12queries{0}; // valid DNS queries received via TLSv1.2
+ stat_t tls13queries{0}; // valid DNS queries received via TLSv1.3
+ stat_t tlsUnknownqueries{0}; // valid DNS queries received via unknown TLS version
+ pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0};
/* in ms */
- std::atomic<double> tcpAvgConnectionDuration{0.0};
+ pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0};
size_t d_maxInFlightQueriesPerConn{1};
int udpFD{-1};
int tcpFD{-1};
class TCPClientCollection {
std::vector<int> d_tcpclientthreads;
- std::atomic<uint64_t> d_numthreads{0};
- std::atomic<uint64_t> d_pos{0};
- std::atomic<uint64_t> d_queued{0};
+ stat_t d_numthreads{0};
+ stat_t d_pos{0};
+ stat_t d_queued{0};
const uint64_t d_maxthreads{0};
std::mutex d_mutex;
int d_singlePipe[2];
QType checkType{QType::A};
uint16_t checkClass{QClass::IN};
std::atomic<uint64_t> idOffset{0};
- std::atomic<uint64_t> sendErrors{0};
- std::atomic<uint64_t> outstanding{0};
- std::atomic<uint64_t> reuseds{0};
- std::atomic<uint64_t> queries{0};
- std::atomic<uint64_t> responses{0};
+ stat_t sendErrors{0};
+ stat_t outstanding{0};
+ stat_t reuseds{0};
+ stat_t queries{0};
+ stat_t responses{0};
struct {
- std::atomic<uint64_t> sendErrors{0};
- std::atomic<uint64_t> reuseds{0};
- std::atomic<uint64_t> queries{0};
+ stat_t sendErrors{0};
+ stat_t reuseds{0};
+ stat_t queries{0};
} prev;
- std::atomic<uint64_t> tcpDiedSendingQuery{0};
- std::atomic<uint64_t> tcpDiedReadingResponse{0};
- std::atomic<uint64_t> tcpGaveUp{0};
- std::atomic<uint64_t> tcpReadTimeouts{0};
- std::atomic<uint64_t> tcpWriteTimeouts{0};
- std::atomic<uint64_t> tcpCurrentConnections{0};
- std::atomic<double> tcpAvgQueriesPerConnection{0.0};
+ stat_t tcpDiedSendingQuery{0};
+ stat_t tcpDiedReadingResponse{0};
+ stat_t tcpGaveUp{0};
+ stat_t tcpReadTimeouts{0};
+ stat_t tcpWriteTimeouts{0};
+ stat_t tcpCurrentConnections{0};
+ pdns::stat_t_trait<double> tcpAvgQueriesPerConnection{0.0};
/* in ms */
- std::atomic<double> tcpAvgConnectionDuration{0.0};
+ pdns::stat_t_trait<double> tcpAvgConnectionDuration{0.0};
size_t socketsOffset{0};
size_t d_maxInFlightQueriesPerConn{1};
double queryLoad{0.0};
}
virtual bool matches(const DNSQuestion* dq) const =0;
virtual string toString() const = 0;
- mutable std::atomic<uint64_t> d_matches{0};
+ mutable stat_t d_matches{0};
};
struct ServerPool
extern size_t g_maxTCPQueriesPerConn;
extern size_t g_maxTCPConnectionDuration;
extern size_t g_maxTCPConnectionsPerClient;
-extern std::atomic<uint16_t> g_cacheCleaningDelay;
-extern std::atomic<uint16_t> g_cacheCleaningPercentage;
+extern pdns::stat16_t g_cacheCleaningDelay;
+extern pdns::stat16_t g_cacheCleaningPercentage;
extern uint32_t g_staleCacheEntriesTTL;
extern bool g_apiReadWrite;
extern std::string g_apiConfigDirectory;
sodcrypto.cc sodcrypto.hh \
sstuff.hh \
statnode.cc statnode.hh \
+ stat_t.hh \
svc-records.cc svc-records.hh \
tcpiohandler-mplexer.hh \
tcpiohandler.cc tcpiohandler.hh \
sodcrypto.cc \
sstuff.hh \
statnode.cc statnode.hh \
+ stat_t.hh \
svc-records.cc svc-records.hh \
test-base64_cc.cc \
test-delaypipe_hh.cc \
--- /dev/null
+../stat_t.hh
\ No newline at end of file
#include "iputils.hh"
#include "libssl.hh"
#include "noinitvector.hh"
+#include "stat_t.hh"
struct DOHServerConfig;
uint32_t d_idleTimeout{30}; // HTTP idle timeout in seconds
std::vector<std::string> d_urls;
- std::atomic<uint64_t> d_httpconnects{0}; // number of TCP/IP connections established
- std::atomic<uint64_t> d_getqueries{0}; // valid DNS queries received via GET
- std::atomic<uint64_t> d_postqueries{0}; // valid DNS queries received via POST
- std::atomic<uint64_t> d_badrequests{0}; // request could not be converted to dns query
- std::atomic<uint64_t> d_errorresponses{0}; // dnsdist set 'error' on response
- std::atomic<uint64_t> d_redirectresponses{0}; // dnsdist set 'redirect' on response
- std::atomic<uint64_t> d_validresponses{0}; // valid responses sent out
+ pdns::stat_t d_httpconnects{0}; // number of TCP/IP connections established
+ pdns::stat_t d_getqueries{0}; // valid DNS queries received via GET
+ pdns::stat_t d_postqueries{0}; // valid DNS queries received via POST
+ pdns::stat_t d_badrequests{0}; // request could not be converted to dns query
+ pdns::stat_t d_errorresponses{0}; // dnsdist set 'error' on response
+ pdns::stat_t d_redirectresponses{0}; // dnsdist set 'redirect' on response
+ pdns::stat_t d_validresponses{0}; // 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};
+ pdns::stat_t d_nbQueries{0}; // valid DNS queries received
+ pdns::stat_t d_nb200Responses{0};
+ pdns::stat_t d_nb400Responses{0};
+ pdns::stat_t d_nb403Responses{0};
+ pdns::stat_t d_nb500Responses{0};
+ pdns::stat_t d_nb502Responses{0};
+ pdns::stat_t d_nbOtherResponses{0};
};
HTTPVersionStats d_http1Stats;
--- /dev/null
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#pragma once
+
+#define CPU_LEVEL1_DCACHE_LINESIZE 64 // Until we know better via configure/getconf
+
+namespace pdns {
+ template <typename T>
+ class stat_t_trait {
+ public:
+ typedef T base_t;
+ typedef std::atomic<base_t> atomic_t;
+
+ stat_t_trait() : stat_t_trait(base_t(0)) {
+ }
+ stat_t_trait(const base_t x) {
+ new(&counter) atomic_t(x);
+ }
+ ~stat_t_trait() {
+ reinterpret_cast<atomic_t *>(&counter)->~atomic_t();
+ }
+ stat_t_trait(const stat_t_trait&) = delete;
+ base_t operator++(int) {
+ return (*reinterpret_cast<atomic_t *>(&counter))++;
+ }
+ base_t operator++() {
+ return ++(*reinterpret_cast<atomic_t *>(&counter));
+ }
+ base_t operator--(int) {
+ return (*reinterpret_cast<atomic_t *>(&counter))--;
+ }
+ base_t operator--() {
+ return --(*reinterpret_cast<atomic_t *>(&counter));
+ }
+ base_t operator+=(const stat_t_trait& v) {
+ return *reinterpret_cast<atomic_t *>(&counter) += *reinterpret_cast<const atomic_t *>(&v.counter);
+ }
+ base_t operator-=(const stat_t_trait& v) {
+ return *reinterpret_cast<atomic_t *>(&counter) -= *reinterpret_cast<const atomic_t *>(&v.counter);
+ }
+ base_t load() const {
+ return reinterpret_cast<const atomic_t *>(&counter)->load();
+ }
+ void store(base_t v) {
+ reinterpret_cast<atomic_t *>(&counter)->store(v);
+ }
+ operator base_t() const {
+ return reinterpret_cast<const atomic_t *>(&counter)->load();
+ }
+
+ private:
+ typename std::aligned_storage<sizeof(base_t), CPU_LEVEL1_DCACHE_LINESIZE>::type counter;
+ };
+
+ typedef stat_t_trait<uint64_t> stat_t;
+ typedef stat_t_trait<uint32_t> stat32_t;
+ typedef stat_t_trait<uint16_t> stat16_t;
+}