return ret;
}
-typedef std::function<void(const StatNode&, const StatNode::Stat&, const StatNode::Stat&)> statvisitor_t;
+using statvisitor_t = std::function<void(const StatNode&, const StatNode::Stat&, const StatNode::Stat&)>;
static void statNodeRespRing(statvisitor_t visitor, uint64_t seconds)
{
auto rl = shard->respRing.lock();
for(const auto& c : *rl) {
- if (now < c.when)
+ if (now < c.when){
continue;
+ }
- if (seconds && c.when < cutoff)
+ if (seconds && c.when < cutoff) {
continue;
+ }
+
+ bool hit = c.ds.sin4.sin_family == 0;
+ if (!hit && c.ds.isIPv4() && c.ds.sin4.sin_addr.s_addr == 0 && c.ds.sin4.sin_port == 0) {
+ hit = true;
+ }
- root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, boost::none);
+ root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, hit, boost::none);
}
}
luaCtx.registerMember("noerrors", &StatNode::Stat::noerrors);
luaCtx.registerMember("drops", &StatNode::Stat::drops);
luaCtx.registerMember("bytes", &StatNode::Stat::bytes);
+ luaCtx.registerMember("hits", &StatNode::Stat::hits);
luaCtx.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional<uint64_t> seconds) {
statNodeRespRing(visitor, seconds ? *seconds : 0U);
}
if (suffixMatchRuleMatches) {
- root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, boost::none);
+ bool hit = c.ds.sin4.sin_family == 0;
+ if (!hit && c.ds.isIPv4() && c.ds.sin4.sin_addr.s_addr == 0 && c.ds.sin4.sin_port == 0) {
+ hit = true;
+ }
+
+ root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, hit, boost::none);
}
}
}
return node->self.bytes;
}
+uint64_t dnsdist_ffi_stat_node_get_hits(const dnsdist_ffi_stat_node_t* node)
+{
+ return node->self.hits;
+}
+
unsigned int dnsdist_ffi_stat_node_get_labels_count(const dnsdist_ffi_stat_node_t* node)
{
return node->node.labelsCount;
return node->children.bytes;
}
+uint64_t dnsdist_ffi_stat_node_get_children_hits(const dnsdist_ffi_stat_node_t* node)
+{
+ return node->children.hits;
+}
+
void dnsdist_ffi_state_node_set_reason(dnsdist_ffi_stat_node_t* node, const char* reason, size_t reasonSize)
{
node->reason = std::string(reason, reasonSize);
uint64_t dnsdist_ffi_stat_node_get_servfails_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_drops_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_bytes(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+ uint64_t dnsdist_ffi_stat_node_get_hits(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
unsigned int dnsdist_ffi_stat_node_get_labels_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
void dnsdist_ffi_stat_node_get_full_name_raw(const dnsdist_ffi_stat_node_t* node, const char** name, size_t* nameSize) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_children_servfails_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_children_drops_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_children_bytes_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+ uint64_t dnsdist_ffi_stat_node_get_children_hits(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
void dnsdist_ffi_state_node_set_reason(dnsdist_ffi_stat_node_t* node, const char* reason, size_t reasonSize) __attribute__ ((visibility ("default")));
}
rem.sin4.sin_port=0;
if(doServFailTree)
- root.submit(qname, header.rcode, pr.d_len, rem);
+ root.submit(qname, header.rcode, pr.d_len, false, rem);
}
if(!qd.d_qcount || qd.d_qcount == qd.d_answercount) {
childstat.servfails += s.servfails;
childstat.drops += s.drops;
childstat.bytes += s.bytes;
+ childstat.hits += s.hits;
if(children.size()>1024 && !silent) {
cout<<string(depth, ' ')<<name<<": too many to print"<<endl;
childstat.nxdomains<<" nxdomains, "<<
childstat.servfails<<" servfails, "<<
childstat.drops<<" drops, "<<
- childstat.bytes<<" bytes"<<endl;
+ childstat.bytes<<" bytes, "<<
+ childstat.hits<<" hits"<<endl;
newstat+=childstat;
}
-void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote)
+void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, bool hit, boost::optional<const ComboAddress&> remote)
{
// cerr<<"FIRST submit called on '"<<domain<<"'"<<endl;
std::vector<string> tmp = domain.getRawLabels();
}
auto last = tmp.end() - 1;
- children[*last].submit(last, tmp.begin(), "", rcode, bytes, remote, 1);
+ children[*last].submit(last, tmp.begin(), "", rcode, bytes, remote, 1, hit);
}
/* www.powerdns.com. ->
www.powerdns.com.
*/
-void StatNode::submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count)
+void StatNode::submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count, bool hit)
{
// cerr<<"Submit called for domain='"<<domain<<"': ";
// for(const std::string& n : labels)
// cerr<<"Hit the end, set our fullname to '"<<fullname<<"'"<<endl<<endl;
s.queries++;
s.bytes += bytes;
- if(rcode<0)
+ if (rcode < 0) {
s.drops++;
- else if(rcode==0)
+ }
+ else if (rcode == RCode::NoError) {
s.noerrors++;
- else if(rcode==2)
+ }
+ else if (rcode == RCode::ServFail) {
s.servfails++;
- else if(rcode==3)
+ }
+ else if (rcode == RCode::NXDomain) {
s.nxdomains++;
+ }
if (remote) {
s.remotes[*remote]++;
}
+
+ if (hit) {
+ ++s.hits;
+ }
}
else {
if (fullname.empty()) {
}
// cerr<<"Not yet end, set our fullname to '"<<fullname<<"', recursing"<<endl;
--end;
- children[*end].submit(end, begin, fullname, rcode, bytes, remote, count+1);
+ children[*end].submit(end, begin, fullname, rcode, bytes, remote, count+1, hit);
}
}
struct Stat
{
- Stat(): queries(0), noerrors(0), nxdomains(0), servfails(0), drops(0), bytes(0)
+ Stat()
{
}
- uint64_t queries, noerrors, nxdomains, servfails, drops, bytes;
+
+ uint64_t queries{0};
+ uint64_t noerrors{0};
+ uint64_t nxdomains{0};
+ uint64_t servfails{0};
+ uint64_t drops{0};
+ uint64_t bytes{0};
+ uint64_t hits{0};
+ using remotes_t = std::map<ComboAddress,int,ComboAddress::addressOnlyLessThan>;
+ remotes_t remotes;
Stat& operator+=(const Stat& rhs) {
- queries+=rhs.queries;
- noerrors+=rhs.noerrors;
- nxdomains+=rhs.nxdomains;
- servfails+=rhs.servfails;
- drops+=rhs.drops;
- bytes+=rhs.bytes;
+ queries += rhs.queries;
+ noerrors += rhs.noerrors;
+ nxdomains += rhs.nxdomains;
+ servfails += rhs.servfails;
+ drops += rhs.drops;
+ bytes += rhs.bytes;
+ hits += rhs.hits;
- for(const remotes_t::value_type& rem : rhs.remotes) {
- remotes[rem.first]+=rem.second;
+ for (const remotes_t::value_type& rem : rhs.remotes) {
+ remotes[rem.first] += rem.second;
}
return *this;
}
- typedef std::map<ComboAddress,int,ComboAddress::addressOnlyLessThan> remotes_t;
- remotes_t remotes;
};
+ using visitor_t = std::function<void(const StatNode*, const Stat& selfstat, const Stat& childstat)>;
+ using children_t = std::map<std::string, StatNode, CIStringCompare>;
+
Stat s;
std::string name;
std::string fullname;
uint8_t labelsCount{0};
- void submit(const DNSName& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote);
-
+ void submit(const DNSName& domain, int rcode, unsigned int bytes, bool hit, boost::optional<const ComboAddress&> remote);
Stat print(unsigned int depth=0, Stat newstat=Stat(), bool silent=false) const;
- typedef std::function<void(const StatNode*, const Stat& selfstat, const Stat& childstat)> visitor_t;
void visit(visitor_t visitor, Stat& newstat, unsigned int depth=0) const;
bool empty() const
{
return children.empty() && s.remotes.empty();
}
- typedef std::map<std::string,StatNode, CIStringCompare> children_t;
children_t children;
private:
- void submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count);
+ void submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count, bool hit);
};