Commit 3e5d5787 authored by Franciszek Gorski's avatar Franciszek Gorski Committed by Marcin Siodelski

[755-Kea-DHCP-servers-observations-should-be-reset] resolve threads

parent c331f010
......@@ -52,20 +52,21 @@ for a list of statistics-oriented commands.
Statistics Lifecycle
====================
It is useful to understand how the Statistics Manager module works.
Since Kea 1.7.0 when the server starts operation, the manager contains
all statistics related to runned type of DHCP server, initialized with
default value. If the ``statistic-get-all`` command is executed at that point,
a list with these statistics is returned. Once the server performs an operation
that causes a statistic to change, the related statistic will be created or updated.
In general, once a statistic is recorded even once, it is kept in the manager
until explicitly removed, by ``statistic-remove`` or ``statistic-remove-all``
In Kea 1.6.0 version and earlier, when the Kea server is started some
of the statistics are initially not returned. For example, the ``pkt4-received``
statistic is not initialized until the first DHCP packet is received.
In the later Kea versions, this behavior has been changed and all of the
statistics supported by the servers is initialized upon the servers' startup
and should be returned in response to the commands such as
``statistic-get-all``. The runtime statistics concerning DHCP packets
processed is initially set to 0 and is not retained across the server
restarts.
In general, once a statistic is initialized it is held in the manager until
explicitly removed, by ``statistic-remove`` or ``statistic-remove-all``
being called, or when the server is shut down.
Per-subnet statistics are explicitly removed when reconfiguration takes place.
Statistics are considered runtime properties, so they are not retained
after server restart.
Removing a statistic that is updated frequently makes little sense, as
it will be re-added when the server code next records that statistic.
The ``statistic-remove`` and ``statistic-remove-all`` commands are
......@@ -86,7 +87,8 @@ Commands for Manipulating Statistics
There are several commands defined that can be used for accessing
(-get), resetting to zero or a neutral value (-reset), or removing a
statistic completely (-remove). We can change the statistics time based
limit (-sample-age-set) and size based limit (-sample-count-set).
limit (-sample-age-set) and size based limit (-sample-count-set) which
control how long or how many samples of the given statistic are retained.
The difference between reset and remove is somewhat subtle.
The reset command sets the value of the statistic to zero or a neutral value,
so after this operation, the statistic will have a value of 0 (integer),
......
......@@ -69,6 +69,7 @@
#include <boost/shared_ptr.hpp>
#include <iomanip>
#include <set>
using namespace isc;
using namespace isc::asiolink;
......@@ -107,25 +108,28 @@ struct Dhcp4Hooks {
hook_index_host4_identifier_ = HooksManager::registerHook("host4_identifier");
}
};
/// Set of all statistics observed in DHCPv4 server
std::set<std::string> dhcp4_statistics = {
"pkt4-received",
"pkt4-discover-received",
"pkt4-offer-received",
"pkt4-request-received",
"pkt4-ack-received",
"pkt4-nak-received",
"pkt4-release-received",
"pkt4-decline-received",
"pkt4-inform-received",
"pkt4-unknown-received",
"pkt4-sent",
"pkt4-offer-sent",
"pkt4-ack-sent",
"pkt4-nak-sent",
"pkt4-parse-failed",
"pkt4-receive-drop"
};
/// List of statistics which is initialized to 0 during the DHCPv4
/// server startup.
std::set<std::string> dhcp4_statistics = {
"pkt4-received",
"pkt4-discover-received",
"pkt4-offer-received",
"pkt4-request-received",
"pkt4-ack-received",
"pkt4-nak-received",
"pkt4-release-received",
"pkt4-decline-received",
"pkt4-inform-received",
"pkt4-unknown-received",
"pkt4-sent",
"pkt4-offer-sent",
"pkt4-ack-sent",
"pkt4-nak-sent",
"pkt4-parse-failed",
"pkt4-receive-drop"
};
} // end of anonymous namespace
// Declare a Hooks object. As this is outside any function or method, it
......@@ -153,7 +157,6 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
isc_throw(BadValue, "query value must not be NULL when"
" creating an instance of the Dhcpv4Exchange");
}
// Create response message.
initResponse();
// Select subnet for the query message.
......@@ -505,11 +508,10 @@ Dhcpv4Srv::Dhcpv4Srv(uint16_t server_port, uint16_t client_port,
}
void Dhcpv4Srv::setPacketStatisticsDefaults() {
std::set<std::string>::iterator it;
isc::stats::StatsMgr& stats_mgr = isc::stats::StatsMgr::instance();
// Iterate over set of observed statistics
for (it = dhcp4_statistics.begin(); it != dhcp4_statistics.end(); ++it) {
for (auto it = dhcp4_statistics.begin(); it != dhcp4_statistics.end(); ++it) {
// Initialize them with default value 0
stats_mgr.setValue((*it), static_cast<int64_t>(0));
}
......
......@@ -234,9 +234,6 @@ public:
/// @brief Destructor. Used during DHCPv4 service shutdown.
virtual ~Dhcpv4Srv();
/// @brief This function set to defaults all statistics starting with pkt4-.
void setPacketStatisticsDefaults();
/// @brief Checks if the server is running in a test mode.
///
/// @return true if the server is running in the test mode,
......@@ -655,6 +652,14 @@ protected:
/// server's response.
void processClientName(Dhcpv4Exchange& ex);
/// @brief This function sets statistics related to DHCPv4 packets processing
/// to their initial values.
///
/// All of the statistics observed by the DHCPv4 server and with the names
/// like "pkt4-" are reset to 0. This function must be invoked in the class
/// constructor.
void setPacketStatisticsDefaults();
/// @brief this is a prefix added to the content of vendor-class option
///
/// If incoming packet has a vendor class option, its content is
......
......@@ -552,41 +552,39 @@ TEST_F(CtrlChannelDhcpv4SrvTest, controlChannelStats) {
sendUnixCommand("{ \"command\" : \"statistic-get-all\", "
" \"arguments\": {}}", response);
std::set<std::string> initial_stats = {
"pkt4-received",
"pkt4-discover-received",
"pkt4-offer-received",
"pkt4-request-received",
"pkt4-ack-received",
"pkt4-nak-received",
"pkt4-release-received",
"pkt4-decline-received",
"pkt4-inform-received",
"pkt4-unknown-received",
"pkt4-sent",
"pkt4-offer-sent",
"pkt4-ack-sent",
"pkt4-nak-sent",
"pkt4-parse-failed",
"pkt4-receive-drop"
};
// preparing the schema which check if all statistics are set to zero
std::string stats_get_all = "{ \"arguments\": { "
"\"pkt4-ack-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-ack-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-ack-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-ack-sent")
->getInteger().second) + "\" ] ], "
"\"pkt4-decline-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-decline-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-discover-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-discover-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-inform-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-inform-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-nak-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-nak-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-nak-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-nak-sent")
->getInteger().second) + "\" ] ], "
"\"pkt4-offer-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-offer-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-offer-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-offer-sent")
->getInteger().second) + "\" ] ], "
"\"pkt4-parse-failed\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-parse-failed")
->getInteger().second) + "\" ] ], "
"\"pkt4-receive-drop\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-receive-drop")
->getInteger().second) + "\" ] ], "
"\"pkt4-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-release-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-release-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-request-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-request-received")
->getInteger().second) + "\" ] ], "
"\"pkt4-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-sent")
->getInteger().second) + "\" ] ], "
"\"pkt4-unknown-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt4-unknown-received")
->getInteger().second) + "\" ] ] }, "
"\"result\": 0 }";
std::ostringstream s;
s << "{ \"arguments\": { ";
for (auto st = initial_stats.begin(); st != initial_stats.end();) {
s << "\"" << *st << "\": [ [ 0, \"";
s << isc::util::ptimeToText(StatsMgr::instance().getObservation(*st)->getInteger().second);
s << "\" ] ]";
if (++st != initial_stats.end()) {
s << ", ";
}
}
s << " }, \"result\": 0 }";
auto stats_get_all = s.str();
EXPECT_EQ(stats_get_all, response);
......
......@@ -78,6 +78,7 @@
#include <iomanip>
#include <fstream>
#include <sstream>
#include <set>
using namespace isc;
using namespace isc::asiolink;
......@@ -172,28 +173,30 @@ createStatusCode(const Pkt6& pkt, const Option6IA& ia, const uint16_t status_cod
return (option_status);
}
/// Set of all statistics observed in DHCPv6 server
std::set<std::string> dhcp6_statistics = {
"pkt6-received",
"pkt6-solicit-received",
"pkt6-advertise-received",
"pkt6-request-received",
"pkt6-reply-received",
"pkt6-renew-received",
"pkt6-rebind-received",
"pkt6-decline-received",
"pkt6-release-received",
"pkt6-infrequest-received",
"pkt6-dhcpv4-query-received",
"pkt6-dhcpv4-response-received",
"pkt6-unknown-received",
"pkt6-sent",
"pkt6-advertise-sent",
"pkt6-reply-sent",
"pkt6-dhcpv4-response-sent",
"pkt6-parse-failed",
"pkt6-receive-drop"
};
/// List of statistics which is initialized to 0 during the DHCPv6
/// server startup.
std::set<std::string> dhcp6_statistics = {
"pkt6-received",
"pkt6-solicit-received",
"pkt6-advertise-received",
"pkt6-request-received",
"pkt6-reply-received",
"pkt6-renew-received",
"pkt6-rebind-received",
"pkt6-decline-received",
"pkt6-release-received",
"pkt6-infrequest-received",
"pkt6-dhcpv4-query-received",
"pkt6-dhcpv4-response-received",
"pkt6-unknown-received",
"pkt6-sent",
"pkt6-advertise-sent",
"pkt6-reply-sent",
"pkt6-dhcpv4-response-sent",
"pkt6-parse-failed",
"pkt6-receive-drop"
};
}; // anonymous namespace
namespace isc {
......@@ -246,11 +249,10 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t server_port, uint16_t client_port)
}
void Dhcpv6Srv::setPacketStatisticsDefaults() {
std::set<std::string>::iterator it;
isc::stats::StatsMgr& stats_mgr = isc::stats::StatsMgr::instance();
// Iterate over set of observed statistics
for (it = dhcp6_statistics.begin(); it != dhcp6_statistics.end(); ++it) {
for (auto it = dhcp6_statistics.begin(); it != dhcp6_statistics.end(); ++it) {
// Initialize them with default value 0
stats_mgr.setValue((*it), static_cast<int64_t>(0));
}
......
......@@ -89,9 +89,6 @@ public:
/// @brief Destructor. Used during DHCPv6 service shutdown.
virtual ~Dhcpv6Srv();
/// @brief This function set to defaults all statistics starting with pkt6-.
void setPacketStatisticsDefaults();
/// @brief Checks if the server is running in unit test mode.
///
/// @return true if the server is running in unit test mode,
......@@ -204,6 +201,14 @@ public:
protected:
/// @brief This function sets statistics related to DHCPv6 packets processing
/// to their initial values.
///
/// All of the statistics observed by the DHCPv6 server and with the names
/// like "pkt6-" are reset to 0. This function must be invoked in the class
/// constructor.
void setPacketStatisticsDefaults();
/// @brief Compare received server id with our server id
///
/// Checks if the server id carried in a query from a client matches
......
......@@ -1134,47 +1134,41 @@ TEST_F(CtrlChannelDhcpv6SrvTest, controlChannelStats) {
sendUnixCommand("{ \"command\" : \"statistic-get-all\", "
" \"arguments\": {}}", response);
// preparing the schema which check if all statistics are set to zero
std::string stats_get_all = "{ \"arguments\": { "
"\"pkt6-advertise-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-advertise-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-advertise-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-advertise-sent")
->getInteger().second) + "\" ] ], "
"\"pkt6-decline-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-decline-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-dhcpv4-query-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-dhcpv4-query-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-dhcpv4-response-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-dhcpv4-response-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-dhcpv4-response-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-dhcpv4-response-sent")
->getInteger().second) + "\" ] ], "
"\"pkt6-infrequest-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-infrequest-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-parse-failed\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-parse-failed")
->getInteger().second) + "\" ] ], "
"\"pkt6-rebind-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-rebind-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-receive-drop\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-receive-drop")
->getInteger().second) + "\" ] ], "
"\"pkt6-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-release-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-release-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-renew-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-renew-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-reply-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-reply-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-reply-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-reply-sent")
->getInteger().second) + "\" ] ], "
"\"pkt6-request-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-request-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-sent\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-sent")
->getInteger().second) + "\" ] ], "
"\"pkt6-solicit-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-solicit-received")
->getInteger().second) + "\" ] ], "
"\"pkt6-unknown-received\": [ [ 0, \"" + isc::util::ptimeToText(StatsMgr::instance().getObservation("pkt6-unknown-received")
->getInteger().second) + "\" ] ] }, "
"\"result\": 0 }";
std::set<std::string> initial_stats = {
"pkt6-received",
"pkt6-solicit-received",
"pkt6-advertise-received",
"pkt6-request-received",
"pkt6-reply-received",
"pkt6-renew-received",
"pkt6-rebind-received",
"pkt6-decline-received",
"pkt6-release-received",
"pkt6-infrequest-received",
"pkt6-dhcpv4-query-received",
"pkt6-dhcpv4-response-received",
"pkt6-unknown-received",
"pkt6-sent",
"pkt6-advertise-sent",
"pkt6-reply-sent",
"pkt6-dhcpv4-response-sent",
"pkt6-parse-failed",
"pkt6-receive-drop"
};
std::ostringstream s;
s << "{ \"arguments\": { ";
for (auto st = initial_stats.begin(); st != initial_stats.end();) {
s << "\"" << *st << "\": [ [ 0, \"";
s << isc::util::ptimeToText(StatsMgr::instance().getObservation(*st)->getInteger().second);
s << "\" ] ]";
if (++st != initial_stats.end()) {
s << ", ";
}
}
s << " }, \"result\": 0 }";
auto stats_get_all = s.str();
EXPECT_EQ(stats_get_all, response);
......
......@@ -2589,10 +2589,7 @@ TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
// And pretend it's packet is only 3 bytes long.
pkt->data_.resize(3);
// Check that those statistics are set before the test.
// All should be present because we initialize
// all of them in server constructor. This piece of code is mainly reffered
// to previous situation when Kea used lazy initialization of statistics.
// Check that the tested statistics is initially set to 0
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
ObservationPtr parse_fail = mgr.getObservation("pkt6-parse-failed");
ObservationPtr recv_drop = mgr.getObservation("pkt6-receive-drop");
......
......@@ -770,10 +770,7 @@ Dhcpv6SrvTest::testReceiveStats(uint8_t pkt_type, const std::string& stat_name)
// And pretend it's packet of a different type
pkt->data_[0] = pkt_type;
// Check that those statistics are set before the test.
// All should be present because we initialize
// all of them in server constructor. This piece of code is mainly reffered
// to previous situation when Kea used lazy initialization of statistics.
// Check that the tested statistics is initially set to 0
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
ObservationPtr tested_stat = mgr.getObservation(stat_name);
EXPECT_TRUE(pkt6_rcvd);
......
......@@ -316,9 +316,7 @@ TEST_F(InfRequestTest, infRequestStats) {
getCfgSubnets6()->getAll();
ASSERT_EQ(1, subnets->size());
// Ok, let's check the statistics. All should be present because we initialize
// all of them in server constructor. This piece of code is mainly reffered
// to previous situation when Kea used lazy initialization of statistics.
// Check that the tested statistics is initially set to 0
using namespace isc::stats;
StatsMgr& mgr = StatsMgr::instance();
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
......
......@@ -492,9 +492,7 @@ TEST_F(SARRTest, sarrStats) {
getCfgSubnets6()->getAll();
ASSERT_EQ(2, subnets->size());
// Ok, let's check the statistics. All should be present because we initialize
// all of them in server constructor. This piece of code is mainly reffered
// to previous situation when Kea used lazy initialization of statistics.
// Check that the tested statistics is initially set to 0
using namespace isc::stats;
StatsMgr& mgr = StatsMgr::instance();
ObservationPtr pkt6_rcvd = mgr.getObservation("pkt6-received");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment