load() now creates PerfMonMgr singleton and invokes it's configure() function.
src/hooks/dhcp/perfmon/monitored_duration.*
DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type) - new function
Translates DHCP_NOTYPE/DHCPV6_NOTYPE to "*"
src/hooks/dhcp/perfmon/perfmon_callouts.cc
Added PerfMonMgr singleton
int load(LibraryHandle& handle) - creates singleton and parses configuration
src/hooks/dhcp/perfmon/perfmon_config.cc
DurationKeyParser::getMessageNameType4(const std::string& name)
DurationKeyParser::getMessageNameType6(const std::string& name) - map "*" to NOTYPE
static std::map<std::string, uint16_t> name_type_map = {
src/hooks/dhcp/perfmon/tests/duration_key_parser_unittests.cc
TEST_F(DurationKeyParserTest, validScenarios4) - verify "*" message type parses
src/hooks/dhcp/perfmon/libloadtests/load_unload_unittests.cc
Updated to pass in a valid configuration on load test.
virtual ~PerfMonLibLoadTest() {
unloadLibraries();
}
+
+ /// @brief Creates a valid set configuration parameters valid for the library.
+ virtual isc::data::ElementPtr validConfigParams() {
+ std::string valid_config =
+ R"({
+ "enable-monitoring" : true,
+ "interval-width-secs" : 5,
+ "stats-mgr-reporting" : true,
+ "alarm-report-secs" : 600,
+ "alarms": [{
+ "duration-key": {
+ "query-type" : "*",
+ "response-type" : "*",
+ "start-event" : "socket-received",
+ "stop-event" : "buffer-read",
+ "subnet-id" : 70
+ },
+ "enable-alarm" : true,
+ "high-water-ms" : 500,
+ "low-water-ms" : 25
+ }]
+ })";
+
+ // Convert JSON texts to Element map.
+ return (Element::fromJSON(valid_config));
+ }
};
// Simple V4 test that checks the library can be loaded and unloaded several times.
TEST_F(PerfMonLibLoadTest, validLoad4) {
- validDaemonTest("kea-dhcp4");
+ validDaemonTest("kea-dhcp4", AF_INET, valid_params_);
}
// Simple V6 test that checks the library can be loaded and unloaded several times.
TEST_F(PerfMonLibLoadTest, validLoad6) {
- validDaemonTest("kea-dhcp6", AF_INET6);
+ validDaemonTest("kea-dhcp6", AF_INET6, valid_params_);
}
// Simple test that checks the library cannot by loaded by invalid daemons.
}
std::string
-DurationKey::getLabel() const {
- std::ostringstream oss;
- if (family_ == AF_INET) {
- oss << (query_type_ == DHCP_NOTYPE ? "NONE" : Pkt4::getName(query_type_)) << "-"
- << (response_type_ == DHCP_NOTYPE ? "NONE" : Pkt4::getName(response_type_));
- } else {
- oss << (query_type_ == DHCPV6_NOTYPE ? "NONE" : Pkt6::getName(query_type_)) << "-"
- << (response_type_ == DHCPV6_NOTYPE ? "NONE" : Pkt6::getName(response_type_));
+DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type) {
+ if (family == AF_INET) {
+ return (msg_type == DHCP_NOTYPE ? "*" : Pkt4::getName(msg_type));
}
- oss << "." << start_event_label_ << "-" << stop_event_label_
+ return (msg_type == DHCPV6_NOTYPE ? "*" : Pkt6::getName(msg_type));
+}
+
+std::string
+DurationKey::getLabel() const {
+ std::ostringstream oss;
+ oss << getMessageTypeLabel(family_, query_type_)
+ << "-"
+ << getMessageTypeLabel(family_, response_type_)
+ << "." << start_event_label_ << "-" << stop_event_label_
<< "." << subnet_id_;
return (oss.str());
return (subnet_id_);
}
+ /// @brief Get a label for a family-specific message type (e.g.
+ /// "DHCPDISCOVER", "SOLICIT")
+ ///
+ /// @param family Protocol family of the key (AF_INET or AF_INET6)
+ /// @param msg_type numeric message type to translate
+ ///
+ /// @return Text label, for values of DHCP_NOTYPE or DHCPV6_NOTYPE: "*"
+ static std::string getMessageTypeLabel(uint16_t family, uint16_t msg_type);
+
/// @brief Get a composite label of the member values with text message types.
///
/// The format of the string:
///
/// or
///
- /// "DHCPV6_SOLICIT-DHCPV6_ADVERTISE.socket_received.buffer_read.12"
+ /// "SOLICIT-ADVERTISE.socket_received.buffer_read.12"
///
/// @endcode
///
#include <config.h>
#include <perfmon_log.h>
+#include <perfmon_mgr.h>
#include <cc/command_interpreter.h>
#include <dhcpsrv/cfgmgr.h>
#include <hooks/hooks.h>
#include <process/daemon.h>
+namespace isc {
+namespace perfmon {
+
+/// @brief PerfMonMgr singleton
+PerfMonMgrPtr mgr;
+
+} // end of namespace perfmon
+}
+
+using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::hooks;
using namespace isc::log;
///
/// @param handle library handle
/// @return 0 when initialization is successful, 1 otherwise
-int load(LibraryHandle& /* handle */) {
- // Make the hook library not loadable by d2 or ca.
- uint16_t family = CfgMgr::instance().getFamily();
- const std::string& proc_name = Daemon::getProcName();
- if (family == AF_INET) {
- if (proc_name != "kea-dhcp4") {
- isc_throw(isc::Unexpected, "Bad process name: " << proc_name
- << ", expected kea-dhcp4");
- }
- } else {
- if (proc_name != "kea-dhcp6") {
+int load(LibraryHandle& handle) {
+ try {
+ // Make the hook library only loadable for kea-dhcpX.
+ uint16_t family = CfgMgr::instance().getFamily();
+ const std::string& proc_name = Daemon::getProcName();
+ if (family == AF_INET) {
+ if (proc_name != "kea-dhcp4") {
+ isc_throw(isc::Unexpected, "Bad process name: " << proc_name
+ << ", expected kea-dhcp4");
+ }
+ } else if (proc_name != "kea-dhcp6") {
isc_throw(isc::Unexpected, "Bad process name: " << proc_name
<< ", expected kea-dhcp6");
}
- }
- /// @todo register commands
- /// handle.registerCommandCallout("command-here", handler_here);
+ // Instantiate the manager singleton.
+ mgr.reset(new PerfMonMgr(family));
+
+ // Configure the manager using the hook library's parameters.
+ ConstElementPtr json = handle.getParameters();
+ mgr->configure(json);
+
+ /// @todo register commands
+ /// handle.registerCommandCallout("command-here", handler_here);
+ } catch (const std::exception& ex) {
+ LOG_ERROR(perfmon_logger, PERFMON_INIT_FAILED).arg(ex.what());
+ return (1);
+ }
LOG_INFO(perfmon_logger, PERFMON_INIT_OK);
return (0);
DurationKeyParser::getMessageNameType4(const std::string& name) {
static std::map<std::string, uint16_t> name_type_map = {
{"", DHCP_NOTYPE},
+ {"*", DHCP_NOTYPE},
{"DHCPDISCOVER", DHCPDISCOVER},
{"DHCPOFFER", DHCPOFFER},
{"DHCPREQUEST", DHCPREQUEST},
DurationKeyParser::getMessageNameType6(const std::string& name) {
static std::map<std::string, uint16_t> name_type_map = {
{"", DHCPV6_NOTYPE},
+ {"*", DHCPV6_NOTYPE},
{"SOLICIT", DHCPV6_SOLICIT},
{"ADVERTISE", DHCPV6_ADVERTISE},
{"REQUEST", DHCPV6_REQUEST},
/// },
/// "enable-alarm" : true,
/// "high-water-ms" : 500,
-/// "low-water-ms" : 25,
+/// "low-water-ms" : 25
/// },
/// ..
/// }]
})",
DHCPDISCOVER, DHCPOFFER, "start_here", "stop_there", SUBNET_ID_GLOBAL
},
+ {
+ // Empty message types should map to DHCP_NOTYPE
+ __LINE__,
+ R"(
+ {
+ "query-type": "",
+ "response-type": "",
+ "start-event": "start_here",
+ "stop-event": "stop_there",
+ "subnet-id": 701
+ })",
+ DHCP_NOTYPE, DHCP_NOTYPE, "start_here", "stop_there", 701
+ },
+ {
+ // "*" message types should map to DHCP_NOTYPE
+ __LINE__,
+ R"(
+ {
+ "query-type": "*",
+ "response-type": "*",
+ "start-event": "start_here",
+ "stop-event": "stop_there",
+ "subnet-id": 701
+ })",
+ DHCP_NOTYPE, DHCP_NOTYPE, "start_here", "stop_there", 701
+ },
};
testValidScenarios(scenarios, AF_INET);
})",
DHCPV6_SOLICIT, DHCPV6_ADVERTISE, "start_here", "stop_there", SUBNET_ID_GLOBAL
},
+ {
+ // Empty message types should map to DHCPV6_NOTYPE
+ __LINE__,
+ R"(
+ {
+ "query-type": "",
+ "response-type": "",
+ "start-event": "start_here",
+ "stop-event": "stop_there",
+ "subnet-id": 701
+ })",
+ DHCPV6_NOTYPE, DHCPV6_NOTYPE, "start_here", "stop_there", 701
+ },
+ {
+ // "*" message types should map to DHCPV6_NOTYPE
+ __LINE__,
+ R"(
+ {
+ "query-type": "*",
+ "response-type": "*",
+ "start-event": "start_here",
+ "stop-event": "stop_there",
+ "subnet-id": 701
+ })",
+ DHCPV6_NOTYPE, DHCPV6_NOTYPE, "start_here", "stop_there", 701
+ },
};
testValidScenarios(scenarios, AF_INET6);
EXPECT_EQ(mgr->getAlarmStore()->getFamily(), family_);
AlarmCollectionPtr alarms = mgr->getAlarmStore()->getAll();
ASSERT_EQ(alarms->size(), 1);
- DurationKeyPtr key(new DurationKey(family_, 0, 0, "process-started", "process-completed", 70));
+ DurationKeyPtr key(new DurationKey(family_, 0, 0, "process-started",
+ "process-completed", 70));
AlarmPtr alarm = (*alarms)[0];
ASSERT_TRUE(alarm);
EXPECT_EQ(*alarm, *key) << "alarm:" << alarm->getLabel();