Commit a3856901 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3880] Implemented handlers for statistic-* commands.

parent 43a7ef68
# The following build order must be maintained.
SUBDIRS = exceptions util log hooks cryptolink dns cc stats dhcp config \
SUBDIRS = exceptions util log hooks cryptolink dns cc dhcp config stats \
asiolink asiodns testutils dhcp_ddns dhcpsrv
......@@ -11,6 +11,7 @@ libkea_stats_la_SOURCES += stats_mgr.h stats_mgr.cc
libkea_stats_la_CPPFLAGS = $(AM_CPPFLAGS)
libkea_stats_la_LIBADD = $(top_builddir)/src/lib/cc/libkea-cc.la
libkea_stats_la_LIBADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
libkea_stats_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la
libkea_stats_includedir = $(includedir)/$(PACKAGE_NAME)/stats
......
......@@ -14,8 +14,12 @@
#include <exceptions/exceptions.h>
#include <stats/stats_mgr.h>
#include <cc/data.h>
#include <config/command_interpreter.h>
using namespace std;
using namespace isc::data;
using namespace isc::config;
namespace isc {
namespace stats {
......@@ -142,6 +146,95 @@ size_t StatsMgr::count() const {
return (global_->stats_.size());
}
isc::data::ConstElementPtr
StatsMgr::statisticGetHandler(const std::string& /*name*/,
const isc::data::ConstElementPtr& params) {
if (!params) {
return (createAnswer(CONTROL_RESULT_ERROR,
"Missing mandatory 'name' parameter."));
}
ConstElementPtr stat_name = params->get("name");
if (!stat_name) {
return (createAnswer(CONTROL_RESULT_ERROR,
"Missing mandatory 'name' parameter."));
}
if (stat_name->getType() != Element::string) {
return (createAnswer(CONTROL_RESULT_ERROR,
"'name' parameter expected to be a string."));
}
return (createAnswer(CONTROL_RESULT_SUCCESS, get(stat_name->stringValue())));
}
isc::data::ConstElementPtr
StatsMgr::statisticResetHandler(const std::string& /*name*/,
const isc::data::ConstElementPtr& params) {
if (!params) {
return (createAnswer(CONTROL_RESULT_ERROR,
"Missing mandatory 'name' parameter."));
}
ConstElementPtr stat_name = params->get("name");
if (!stat_name) {
return (createAnswer(CONTROL_RESULT_ERROR,
"Missing mandatory 'name' parameter."));
}
if (stat_name->getType() != Element::string) {
return (createAnswer(CONTROL_RESULT_ERROR,
"'name' parameter expected to be a string."));
}
if (reset(stat_name->stringValue())) {
return (createAnswer(CONTROL_RESULT_SUCCESS,
"Statistic '" + stat_name->stringValue() + "' reset."));
} else {
return (createAnswer(CONTROL_RESULT_ERROR,
"No '" + stat_name->stringValue() + "' statistic found"));
}
}
isc::data::ConstElementPtr
StatsMgr::statisticRemoveHandler(const std::string& /*name*/,
const isc::data::ConstElementPtr& params) {
if (!params) {
return (createAnswer(CONTROL_RESULT_ERROR,
"Missing mandatory 'name' parameter."));
}
ConstElementPtr stat_name = params->get("name");
if (!stat_name) {
return (createAnswer(CONTROL_RESULT_ERROR,
"Missing mandatory 'name' parameter."));
}
if (del(stat_name->stringValue())) {
return (createAnswer(CONTROL_RESULT_SUCCESS,
"Statistic '" + stat_name->stringValue() + "' removed."));
} else {
return (createAnswer(CONTROL_RESULT_ERROR,
"No '" + stat_name->stringValue() + "' statistic found"));
}
}
isc::data::ConstElementPtr
StatsMgr::statisticRemoveAllHandler(const std::string& /*name*/,
const isc::data::ConstElementPtr& /*params*/) {
removeAll();
return (createAnswer(CONTROL_RESULT_SUCCESS,
"All statistics removed."));
}
isc::data::ConstElementPtr
StatsMgr::statisticGetAllHandler(const std::string& /*name*/,
const isc::data::ConstElementPtr& /*params*/) {
ConstElementPtr all_stats = getAll();
return (createAnswer(CONTROL_RESULT_SUCCESS, all_stats));
}
isc::data::ConstElementPtr
StatsMgr::statisticResetAllHandler(const std::string& /*name*/,
const isc::data::ConstElementPtr& /*params*/) {
resetAll();
return (createAnswer(CONTROL_RESULT_SUCCESS,
"All statistics reset to neutral values."));
}
};
......
......@@ -197,6 +197,104 @@ class StatsMgr : public boost::noncopyable {
/// @return Pointer to the Observation object
ObservationPtr getObservation(const std::string& name) const;
/// @defgroup command_methods Methods are used to handle commands.
///
/// @brief The following methods are used to handle commands:
///
/// @{
/// @brief Handles statistic-get command
///
/// This method handles statistic-get command, which returns value
/// of a given statistic). It expects one parameter stored in params map:
/// name: name-of-the-statistic
///
/// Example params structure:
/// {
/// "name": "packets-received"
/// }
///
/// @param name name of the command (ignored, should be "statistic-get")
/// @param params structure containing a map that contains "name"
/// @param return answer containing details of specified statistic
isc::data::ConstElementPtr
statisticGetHandler(const std::string& name,
const isc::data::ConstElementPtr& params);
/// @param Handles statistic-reset command
///
/// This method handles statistic-reset command, which resets value
/// of a given statistic. It expects one parameter stored in params map:
/// name: name-of-the-statistic
///
/// Example params structure:
/// {
/// "name": "packets-received"
/// }
///
/// @param name name of the command (ignored, should be "statistic-reset")
/// @param params structure containing a map that contains "name"
/// @param return answer containing confirmation
isc::data::ConstElementPtr
statisticResetHandler(const std::string& name,
const isc::data::ConstElementPtr& params);
/// @param Handles statistic-remove command
///
/// This method handles statistic-reset command, which removes a given
/// statistic completely. It expects one parameter stored in params map:
/// name: name-of-the-statistic
///
/// Example params structure:
/// {
/// "name": "packets-received"
/// }
///
/// @param name name of the command (ignored, should be "statistic-remove")
/// @param params structure containing a map that contains "name" element
/// @param return answer containing confirmation
isc::data::ConstElementPtr
statisticRemoveHandler(const std::string& name,
const isc::data::ConstElementPtr& params);
/// @brief Handles statistic-get-all command
///
/// This method handles statistic-get-all command, which returns values
/// of all statistics. Params parameter is ignored.
///
/// @param name name of the command (ignored, should be "statistic-get-all")
/// @param params ignored
/// @param return answer containing values of all statistic
isc::data::ConstElementPtr
statisticGetAllHandler(const std::string& name,
const isc::data::ConstElementPtr& params);
/// @brief Handles statistic-reset-all command
///
/// This method handles statistic-reset-all command, which sets values of
/// all statistics back to zero. Params parameter is ignored.
///
/// @param name name of the command (ignored, should be "statistic-reset-all")
/// @param params ignored
/// @param return answer confirming success of this operation
isc::data::ConstElementPtr
statisticResetAllHandler(const std::string& name,
const isc::data::ConstElementPtr& params);
/// @brief Handles statistic-remove-all command
///
/// This method handles statistic-remove-all command, which removes all
/// statistics. Params parameter is ignored.
///
/// @param name name of the command (ignored, should be "statistic-remove-all")
/// @param params ignored
/// @param return answer confirming success of this operation
isc::data::ConstElementPtr
statisticRemoveAllHandler(const std::string& name,
const isc::data::ConstElementPtr& params);
/// @}
private:
/// @brief Sets a given statistic to specified value (internal version).
......
......@@ -24,6 +24,7 @@ libstats_unittests_CXXFLAGS = $(AM_CXXFLAGS)
libstats_unittests_LDADD = $(top_builddir)/src/lib/stats/libkea-stats.la
libstats_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
libstats_unittests_LDADD += $(top_builddir)/src/lib/config/libkea-cfgclient.la
libstats_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
libstats_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
libstats_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
......
......@@ -17,6 +17,7 @@
#include <stats/stats_mgr.h>
#include <exceptions/exceptions.h>
#include <cc/data.h>
#include <config/command_interpreter.h>
#include <util/boost_time_utils.h>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/shared_ptr.hpp>
......@@ -28,6 +29,7 @@
using namespace isc;
using namespace isc::data;
using namespace isc::stats;
using namespace isc::config;
using namespace boost::posix_time;
namespace {
......@@ -42,6 +44,7 @@ public:
/// Makes sure that the Statistics Manager is instantiated.
StatsMgrTest() {
StatsMgr::instance();
StatsMgr::instance().removeAll();
}
/// @brief Destructor
......@@ -397,4 +400,274 @@ TEST_F(StatsMgrTest, DISABLED_performanceMultipleSet) {
<< " times took: " << isc::util::durationToText(dur) << std::endl;
}
// Test checks if statistic-get handler is able to return specified statistic.
TEST_F(StatsMgrTest, commandStatisticGet) {
StatsMgr::instance().setValue("alpha", static_cast<uint64_t>(1234));
ElementPtr params = Element::createMap();
params->set("name", Element::create("alpha"));
ConstElementPtr rsp = StatsMgr::instance().statisticGetHandler("statistic-get",
params);
ObservationPtr alpha;
EXPECT_NO_THROW(alpha = StatsMgr::instance().getObservation("alpha"));
ASSERT_TRUE(alpha);
std::string exp = "{ \"alpha\": [ [ 1234, \""
+ isc::util::ptimeToText(alpha->getInteger().second) + "\" ] ] }";
EXPECT_EQ("{ \"arguments\": " + exp + ", \"result\": 0 }", rsp->str());
}
// Test checks if statistic-get is able to handle:
// - a request without parameters
// - a request with missing statistic name
// - a request for non-existing statistic.
TEST_F(StatsMgrTest, commandStatisticGetNegative) {
// Case 1: a request without parameters
ConstElementPtr rsp = StatsMgr::instance().statisticGetHandler("statistic-get",
ElementPtr());
int status_code;
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(status_code, CONTROL_RESULT_ERROR);
// Case 2: a request with missing statistic name
ElementPtr params = Element::createMap();
rsp = StatsMgr::instance().statisticGetHandler("statistic-get", params);
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(status_code, CONTROL_RESULT_ERROR);
// Case 3: a request for non-existing statistic
params->set("name", Element::create("alpha"));
rsp = StatsMgr::instance().statisticGetHandler("statistic-get", params);
EXPECT_EQ("{ \"arguments\": { }, \"result\": 0 }", rsp->str());
}
// This test checks whether statistc-get-all command returns all statistics
// correctly.
TEST_F(StatsMgrTest, commandGetAll) {
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<uint64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
StatsMgr::instance().setValue("gamma", time_duration(1,2,3,4));
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// Now get them. They're used to generate expected output
ConstElementPtr rep_alpha = StatsMgr::instance().get("alpha");
ConstElementPtr rep_beta = StatsMgr::instance().get("beta");
ConstElementPtr rep_gamma = StatsMgr::instance().get("gamma");
ConstElementPtr rep_delta = StatsMgr::instance().get("delta");
ASSERT_TRUE(rep_alpha);
ASSERT_TRUE(rep_beta);
ASSERT_TRUE(rep_gamma);
ASSERT_TRUE(rep_delta);
std::string exp_str_alpha = "[ [ 1234, \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha")
->getInteger().second) + "\" ] ]";
std::string exp_str_beta = "[ [ 12.34, \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("beta")
->getFloat().second) + "\" ] ]";
std::string exp_str_gamma = "[ [ \"01:02:03.000004\", \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma")
->getDuration().second) + "\" ] ]";
std::string exp_str_delta = "[ [ \"Lorem ipsum\", \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("delta")
->getString().second) + "\" ] ]";
// Check that all of them can be reported at once
ConstElementPtr rsp = StatsMgr::instance().statisticGetAllHandler(
"statistic-get-all", ElementPtr());
ASSERT_TRUE(rsp);
int status_code;
ConstElementPtr rep_all = parseAnswer(status_code, rsp);
ASSERT_EQ(0, status_code);
ASSERT_TRUE(rep_all);
// Verifying this is a bit more involved, as we don't know whether the
// order would be preserved or not.
EXPECT_EQ(4, rep_all->size());
ASSERT_TRUE(rep_all->get("alpha"));
ASSERT_TRUE(rep_all->get("beta"));
ASSERT_TRUE(rep_all->get("delta"));
ASSERT_TRUE(rep_all->get("gamma"));
EXPECT_FALSE(rep_all->get("epsilon"));
EXPECT_EQ(exp_str_alpha, rep_all->get("alpha")->str());
EXPECT_EQ(exp_str_beta, rep_all->get("beta")->str());
EXPECT_EQ(exp_str_gamma, rep_all->get("gamma")->str());
EXPECT_EQ(exp_str_delta, rep_all->get("delta")->str());
}
// Test checks if statistic-reset handler is able to reset specified statistic.
TEST_F(StatsMgrTest, commandStatisticReset) {
StatsMgr::instance().setValue("alpha", static_cast<uint64_t>(1234));
ElementPtr params = Element::createMap();
params->set("name", Element::create("alpha"));
ConstElementPtr rsp =
StatsMgr::instance().statisticResetHandler("statistic-reset", params);
int status_code;
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status_code);
ObservationPtr alpha;
EXPECT_NO_THROW(alpha = StatsMgr::instance().getObservation("alpha"));
ASSERT_TRUE(alpha);
// Check that it was indeed reset
EXPECT_EQ(0, alpha->getInteger().first);
}
// Test checks if statistic-reset is able to handle:
// - a request without parameters
// - a request with missing statistic name
// - a request for non-existing statistic.
TEST_F(StatsMgrTest, commandStatisticResetNegative) {
// Case 1: a request without parameters
ConstElementPtr rsp =
StatsMgr::instance().statisticResetHandler("statistic-reset", ElementPtr());
int status_code;
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(status_code, CONTROL_RESULT_ERROR);
// Case 2: a request with missing statistic name
ElementPtr params = Element::createMap();
rsp = StatsMgr::instance().statisticResetHandler("statistic-reset", params);
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(status_code, CONTROL_RESULT_ERROR);
// Case 3: a request for non-existing statistic
params->set("name", Element::create("alpha"));
rsp = StatsMgr::instance().statisticResetHandler("statistic-reset", params);
EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'alpha' statistic found\" }",
rsp->str());
}
// This test checks whether statistic-reset-all command really resets all
// statistics correctly.
TEST_F(StatsMgrTest, commandResetAll) {
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<uint64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
StatsMgr::instance().setValue("gamma", time_duration(1,2,3,4));
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// Now get them. They're used to generate expected output
ConstElementPtr rep_alpha = StatsMgr::instance().get("alpha");
ConstElementPtr rep_beta = StatsMgr::instance().get("beta");
ConstElementPtr rep_gamma = StatsMgr::instance().get("gamma");
ConstElementPtr rep_delta = StatsMgr::instance().get("delta");
ASSERT_TRUE(rep_alpha);
ASSERT_TRUE(rep_beta);
ASSERT_TRUE(rep_gamma);
ASSERT_TRUE(rep_delta);
std::string exp_str_alpha = "[ [ 1234, \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha")
->getInteger().second) + "\" ] ]";
std::string exp_str_beta = "[ [ 12.34, \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("beta")
->getFloat().second) + "\" ] ]";
std::string exp_str_gamma = "[ [ \"01:02:03.000004\", \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma")
->getDuration().second) + "\" ] ]";
std::string exp_str_delta = "[ [ \"Lorem ipsum\", \""
+ isc::util::ptimeToText(StatsMgr::instance().getObservation("delta")
->getString().second) + "\" ] ]";
// Check that all of them can be reset at once
ConstElementPtr rsp = StatsMgr::instance().statisticResetAllHandler(
"statistic-reset-all", ElementPtr());
ASSERT_TRUE(rsp);
int status_code;
ConstElementPtr rep_all = parseAnswer(status_code, rsp);
ASSERT_EQ(0, status_code);
ASSERT_TRUE(rep_all);
// Check that they're indeed reset
EXPECT_EQ(0, StatsMgr::instance().getObservation("alpha")->getInteger().first);
EXPECT_EQ(0.0f,
StatsMgr::instance().getObservation("beta")->getFloat().first);
EXPECT_EQ(time_duration(0,0,0,0),
StatsMgr::instance().getObservation("gamma")->getDuration().first);
EXPECT_EQ("",
StatsMgr::instance().getObservation("delta")->getString().first);
}
// Test checks if statistic-remove handler is able to remove a statistic.
TEST_F(StatsMgrTest, commandStatisticRemove) {
StatsMgr::instance().setValue("alpha", static_cast<uint64_t>(1234));
ElementPtr params = Element::createMap();
params->set("name", Element::create("alpha"));
ConstElementPtr rsp =
StatsMgr::instance().statisticRemoveHandler("statistic-remove", params);
int status_code;
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(CONTROL_RESULT_SUCCESS, status_code);
// It should be gone.
EXPECT_FALSE(StatsMgr::instance().getObservation("alpha"));
}
// Test checks if statistic-remove is able to handle:
// - a request without parameters
// - a request with missing statistic name
// - a request for non-existing statistic.
TEST_F(StatsMgrTest, commandStatisticRemoveNegative) {
// Case 1: a request without parameters
ConstElementPtr rsp =
StatsMgr::instance().statisticRemoveHandler("statistic-remove", ElementPtr());
int status_code;
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(status_code, CONTROL_RESULT_ERROR);
// Case 2: a request with missing statistic name
ElementPtr params = Element::createMap();
rsp = StatsMgr::instance().statisticRemoveHandler("statistic-remove", params);
ASSERT_NO_THROW(parseAnswer(status_code, rsp));
EXPECT_EQ(status_code, CONTROL_RESULT_ERROR);
// Case 3: a request for non-existing statistic
params->set("name", Element::create("alpha"));
rsp = StatsMgr::instance().statisticRemoveHandler("statistic-remove", params);
EXPECT_EQ("{ \"result\": 1, \"text\": \"No 'alpha' statistic found\" }",
rsp->str());
}
// This test checks whether statistic-remove-all command really resets all
// statistics correctly.
TEST_F(StatsMgrTest, commandRemoveAll) {
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<uint64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
StatsMgr::instance().setValue("gamma", time_duration(1,2,3,4));
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// Check that all of them can be reset at once
ConstElementPtr rsp = StatsMgr::instance().statisticRemoveAllHandler(
"statistic-remove-all", ElementPtr());
ASSERT_TRUE(rsp);
int status_code;
ConstElementPtr rep_all = parseAnswer(status_code, rsp);
ASSERT_EQ(0, status_code);
EXPECT_FALSE(StatsMgr::instance().getObservation("alpha"));
EXPECT_FALSE(StatsMgr::instance().getObservation("beta"));
EXPECT_FALSE(StatsMgr::instance().getObservation("gamma"));
EXPECT_FALSE(StatsMgr::instance().getObservation("delta"));
}
};
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