BIND 10 #2155: Collect query/response statistics items in Auth module
BIND 10 Development
do-not-reply at isc.org
Sun Oct 7 10:35:42 UTC 2012
#2155: Collect query/response statistics items in Auth module
-------------------------------------+-------------------------------------
Reporter: | Owner: y-aharen
y-aharen | Status: reviewing
Type: | Milestone:
enhancement | Sprint-20121009
Priority: | Resolution:
medium | Sensitive: 0
Component: | Sub-Project: DNS
b10-auth | Estimated Difficulty: 5
Keywords: | Total Hours: 0
Defect Severity: N/A |
Feature Depending on Ticket: |
Add Hours to Ticket: 0 |
Internal?: 0 |
-------------------------------------+-------------------------------------
Changes (by vorner):
* owner: vorner => y-aharen
Comment:
Hello
I'm glad the biggest issue was sorted out. However, some more issues still
remain or new ones appear.
The headers in EXTRA_DIST look unusual. I know it may be reasonable
solution, since there's no compiled code and no library, but maybe a
comment to the makefile would be good.
The note about SIG(0) still applies:
{{{
// statistics: check TSIG attributes
// SIG(0) is currently not implemented in Auth
}}}
It seems the SIG(0) is some kind of signing algorithm or something? But if
so, it is unclear how it relates to the surrounding code and why it is
important for the statistics code that it is not implemented in Auth.
Also, what is the reason for this bit of code having a separate block
around it?
{{{#!c++
// note: This can only be reliable after TSIG check succeeds.
{
ConstEDNSPtr edns = message.getEDNS();
if (edns != NULL) {
stats_attrs.setQueryEDNS(true, edns->getVersion() == 0);
stats_attrs.setQueryDO(edns->getDNSSECAwareness());
}
}
}}}
In this bit of code, how is it possible for the qptr to be NULL? If it is
NULL, what does that mean? And if it can't, should we assert for it
instead?
{{{#!c++
const QuestionIterator qiter = response.beginQuestion();
if (qiter != response.endQuestion()) {
// get the first and only question section
const QuestionPtr qptr = *qiter;
if (qptr != NULL) {
}}}
In this code, should we distinguish NXDOMAIN as well as NXRRSET?
{{{#!c++
if (rcode == Rcode::NOERROR_CODE) {
if (answer_rrs > 0) {
// QrySuccess
server_qr_counter_.inc(QR_QRYSUCCESS);
} else {
if (is_aa_set) {
// QryNxrrset
server_qr_counter_.inc(QR_QRYNXRRSET);
} else {
// QryReferral
server_qr_counter_.inc(QR_QRYREFERRAL);
}
}
} else if (rcode == Rcode::REFUSED_CODE) {
// AuthRej
server_qr_counter_.inc(QR_QRYREJECT);
}
}}}
There are magic constants in the code. Maybe they should be defined as
constants somewhere. Also, the comments like „qtype 0..257“ are really
useless. They say the obvious thing about the code, exactly what is
written there, but don't clarify anything about the reason for the code or
such.:
{{{#!c++
if (qtype < 258) {
// qtype 0..257
qtype_type = QRQTypeToQRCounterType[qtype];
} else if (qtype < 32768) {
// qtype 258..32767
qtype_type = QR_QTYPE_OTHER;
} else if (qtype < 32770) {
// qtype 32768..32769
qtype_type = QR_QTYPE_TA + (qtype - 32768);
} else {
// qtype 32770..65535
qtype_type = QR_QTYPE_OTHER;
}
}}}
{{{#!c++
if (rcode < 23) {
// rcode 0..22
}}}
I smell something bad if I see code like this. This is very long and easy
to make the number of lines wrong in one way or another. And, when you do
it wrong, nothing breaks, you just get wrong answers:
{{{#!c++
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
QR_QTYPE_OTHER,
}}}
It would be better to build the array from bunch of position-value pairs
(omitting the OTHER ones, that'd be there in case no pair would have that
position). Or even better, just from the list of „special“ types (like A
and SOA and so on) and pull the positions from the dns++ library.
The test functions `checkAllRcodeCountersZeroExcept` and
`checkAllRcodeCountersZero` look very similar. Would it be possible to
share the code between them somehow? Maybe implement the
`checkAllRcodeCountersZero` as a call to `checkAllRcodeCountersZero` with
some random RCode and 0?
I don't understand the purpose of this function. What does it do? Maybe
comment it?
{{{#!c++
void
expectCounterItem(ConstElementPtr stats,
const std::string& item, const int expected) {
ConstElementPtr value(Element::create(0));
if (item == "queries.udp" || item == "queries.tcp" || expected != 0) {
ASSERT_TRUE(stats->find(item, value)) << " Item: " << item;
value = stats->find(item);
EXPECT_EQ(expected, value->intValue()) << " Item: " << item;
} else {
ASSERT_FALSE(stats->find(item, value)) << " Item: " << item <<
std::endl << " Value: " << value->intValue();
}
}
}}}
This comment seems wrong, `request.tcp` is both in incremented and not
incremented. Should the first line say `request.udp`?
{{{#!c++
// After processing the UDP query, these counters should be incremented:
// request.tcp, opcode.query, qtype.ns, rcode.refused, response
// and these counters should not be incremented:
// request.tcp
}}}
Also, the same test as above and most of the similar check one value less
than what is being listed in the comments. Is it forgotten, or is it some
trick I don't see?
May I suggest removing useless code, like empty constructors and
destructors?
{{{#!c++
CountersTest() : counters() {}
~CountersTest() {}
}}}
{{{#!c++
Counters::~Counters() {}
}}}
{{{#!c++
inline QRAttributes::~QRAttributes()
{}
}}}
{{{#!c++
inline Counter::~Counter() {}
}}}
{{{#!c++
inline ~ConstIterator() {}
}}}
{{{#!c++
inline CounterDictionary::~CounterDictionary() {}
}}}
Also, the canonical way to inline methods is not the `inline` keyword, but
having them inside the class definition itself, like this:
{{{#!c++
class Class {
public:
void thisMethodGetsInlined() {
...
}
};
}}}
Does this function return false every time? Is there any use of the return
value then?
{{{#!c++
bool
checkCountersAllZeroExcept(const isc::data::ConstElementPtr counters,
const std::set<std::string>& except_for) {
}}}
The constructor and `reset` method of `QRAttributes` look very similar.
Would it be better to just call reset from the constructor?
I think these are auto-generated by compiler when needed:
{{{#!c++
inline ConstIterator& operator=(const ConstIterator& source) {
iterator_ = source.iterator_;
return (*this);
}
inline ConstIterator(const ConstIterator& source) :
iterator_(source.iterator_)
{}
}}}
--
Ticket URL: <http://bind10.isc.org/ticket/2155#comment:13>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list