Kea 2.5.9
monitored_duration.cc
Go to the documentation of this file.
1// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <dhcp/pkt4.h>
10#include <dhcp/pkt6.h>
11#include <dhcp/dhcp6.h>
13#include <monitored_duration.h>
14
15using namespace isc::dhcp;
16using namespace boost::posix_time;
17
18namespace isc {
19namespace perfmon {
20
21// DurationDataInterval methods
22
23DurationDataInterval::DurationDataInterval(const Timestamp& start_time /* = PktEvent::now()*/)
24 : start_time_(start_time), occurrences_(0),
25 min_duration_(pos_infin), max_duration_(neg_infin),
26 total_duration_(microseconds(0)) {
27}
28
29void
31 ++occurrences_;
32 if (duration < min_duration_) {
33 min_duration_ = duration;
34 }
35
36 if (duration > max_duration_) {
37 max_duration_ = duration;
38 }
39
40 total_duration_ += duration;
41}
42
45 if (!occurrences_) {
46 return (ZERO_DURATION());
47 }
48
49 return (total_duration_ / occurrences_);
50}
51
52bool
54 return ((start_time_ == other.start_time_) &&
55 (occurrences_ == other.occurrences_) &&
56 (min_duration_ == other.min_duration_) &&
57 (max_duration_ == other.max_duration_) &&
58 (total_duration_ == other.total_duration_));
59}
60
61// DurationKey methods
62
64 uint8_t query_type,
65 uint8_t response_type,
66 const std::string& start_event_label,
67 const std::string& stop_event_label,
68 dhcp::SubnetID subnet_id)
69 : family_(family),
70 query_type_(query_type),
71 response_type_(response_type),
72 start_event_label_(start_event_label),
73 stop_event_label_(stop_event_label),
74 subnet_id_(subnet_id) {
75 if (family != AF_INET && family != AF_INET6) {
76 isc_throw (BadValue, "DurationKey: family must be AF_INET or AF_INET6");
77 }
78
79 validateMessagePair(family, query_type, response_type);
80}
81
82void
83DurationKey::validateMessagePair(uint16_t family, uint8_t query_type, uint8_t response_type) {
84 if (family == AF_INET) {
85 switch(query_type) {
86 case DHCP_NOTYPE:
87 if (response_type == DHCP_NOTYPE ||
88 response_type == DHCPOFFER ||
89 response_type == DHCPACK ||
90 response_type == DHCPNAK) {
91 return;
92 }
93 break;
94
95 case DHCPDISCOVER:
96 if (response_type == DHCP_NOTYPE ||
97 response_type == DHCPOFFER ||
98 response_type == DHCPNAK) {
99 return;
100 }
101 break;
102
103 case DHCPREQUEST:
104 if (response_type == DHCP_NOTYPE ||
105 response_type == DHCPACK ||
106 response_type == DHCPNAK) {
107 return;
108 }
109 break;
110
111 case DHCPINFORM:
112 if (response_type == DHCP_NOTYPE ||
113 response_type == DHCPACK) {
114 return;
115 }
116 break;
117
118 default:
119 isc_throw(BadValue, "Query type not supported by monitoring: "
120 << Pkt4::getName(query_type));
121 break;
122 }
123
124 isc_throw(BadValue, "Response type: " << Pkt4::getName(response_type)
125 << " not valid for query type: " << Pkt4::getName(query_type));
126
127 } else {
128 switch(query_type) {
129 case DHCPV6_NOTYPE:
130 case DHCPV6_SOLICIT:
131 if (response_type == DHCPV6_NOTYPE ||
132 response_type == DHCPV6_ADVERTISE ||
133 response_type == DHCPV6_REPLY) {
134 return;
135 }
136 break;
137
138 case DHCPV6_REQUEST:
139 case DHCPV6_RENEW:
140 case DHCPV6_REBIND:
141 case DHCPV6_CONFIRM:
142 if (response_type == DHCPV6_NOTYPE ||
143 response_type == DHCPV6_REPLY) {
144 return;
145 }
146 break;
147
148 default:
149 isc_throw(BadValue, "Query type not supported by monitoring: "
150 << Pkt6::getName(query_type));
151 break;
152 }
153
154 isc_throw(BadValue, "Response type: " << Pkt6::getName(response_type)
155 << " not valid for query type: " << Pkt6::getName(query_type));
156 }
157}
158
159std::string
160DurationKey::getMessageTypeLabel(uint16_t family, uint16_t msg_type) {
161 if (family == AF_INET) {
162 return (msg_type == DHCP_NOTYPE ? "*" : Pkt4::getName(msg_type));
163 }
164
165 return (msg_type == DHCPV6_NOTYPE ? "*" : Pkt6::getName(msg_type));
166}
167
168std::string
170 std::ostringstream oss;
172 << "-"
174 << "." << start_event_label_ << "-" << stop_event_label_
175 << "." << subnet_id_;
176
177 return (oss.str());
178}
179
180std::string
181DurationKey::getStatName(const std::string& value_name) const {
182 std::ostringstream oss;
183 if (subnet_id_ != SUBNET_ID_GLOBAL) {
184 oss << "subnet-id[" << subnet_id_ << "].";
185 }
186
187 oss << "perfmon."
189 << "-"
191 << "." << start_event_label_ << "-" << stop_event_label_
192 << "." << value_name;
193
194 return (oss.str());
195}
196
197bool
199 return (
200 (query_type_ == other.query_type_) &&
201 (response_type_ == other.response_type_) &&
204 (subnet_id_ == other.subnet_id_)
205 );
206}
207
208bool
210 return (!(*this == other));
211}
212
213bool
214DurationKey::operator<(const DurationKey& other) const {
215 return ((query_type_ < other.query_type_) ||
216 (response_type_ < other.response_type_) ||
219 (subnet_id_ < other.subnet_id_));
220}
221
222std::ostream&
223operator<<(std::ostream& os, const DurationKey& key) {
224 os << key.getLabel();
225 return (os);
226}
227
228// MonitoredDuration methods
229
231 uint8_t query_type,
232 uint8_t response_type,
233 const std::string& start_event_label,
234 const std::string& stop_event_label,
235 dhcp::SubnetID subnet_id,
236 const Duration& interval_duration)
237 : DurationKey(family, query_type, response_type, start_event_label, stop_event_label, subnet_id),
238 interval_duration_(interval_duration),
239 current_interval_(0),
240 previous_interval_(0) {
241 if (interval_duration_ <= DurationDataInterval::ZERO_DURATION()) {
242 isc_throw(BadValue, "MonitoredDuration - interval_duration " << interval_duration_
243 << ", is invalid, it must be greater than 0");
244 }
245}
246
248 const Duration& interval_duration)
249 : DurationKey(key),
250 interval_duration_(interval_duration),
251 current_interval_(0),
252 previous_interval_(0) {
253 if (interval_duration_ <= DurationDataInterval::ZERO_DURATION()) {
254 isc_throw(BadValue, "MonitoredDuration - interval_duration " << interval_duration_
255 << ", is invalid, it must be greater than 0");
256 }
257}
258
260 : DurationKey(rhs),
261 interval_duration_(rhs.interval_duration_),
262 current_interval_(0),
263 previous_interval_(0) {
264 if (rhs.current_interval_) {
265 current_interval_.reset(new DurationDataInterval(*rhs.current_interval_));
266 }
267
268 if (rhs.previous_interval_) {
269 previous_interval_.reset(new DurationDataInterval(*rhs.previous_interval_));
270 }
271}
272
275 return (current_interval_ ? current_interval_->getStartTime()
277}
278
279bool
281 auto now = PktEvent::now();
282 bool do_report = false;
283 if (!current_interval_) {
284 current_interval_.reset(new DurationDataInterval(now));
285 } else if ((now - current_interval_->getStartTime()) > interval_duration_) {
286 previous_interval_ = current_interval_;
287 do_report = true;
288 current_interval_.reset(new DurationDataInterval(now));
289 }
290
291 current_interval_->addDuration(sample);
292 return (do_report);
293}
294
295void
297 if (!current_interval_) {
298 isc_throw(InvalidOperation, "MonitoredDuration::expireInterval"
299 " - no current interval for: " << getLabel());
300 }
301
302 previous_interval_ = current_interval_;
303 current_interval_.reset();
304}
305
306void
308 current_interval_.reset();
309 previous_interval_.reset();
310}
311
312} // end of namespace perfmon
313} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a function is called in a prohibited way.
const char * getName() const
Returns name of the DHCP message.
Definition: pkt4.cc:365
const char * getName() const
Returns name of the DHCPv6 message.
Definition: pkt6.cc:868
static boost::posix_time::ptime now()
Fetch the current UTC system time, microsecond precision.
Definition: pkt.h:117
static boost::posix_time::ptime & MIN_TIME()
Fetches the minimum timestamp.
Definition: pkt.h:132
Embodies a span of time (i.e.
DurationDataInterval(const Timestamp &start_time=dhcp::PktEvent::now())
Constructor.
static const Duration & ZERO_DURATION()
Get a duration of zero.
bool operator==(const DurationDataInterval &other) const
Equality operator.
Duration getAverageDuration() const
Get the average duration for the interval.
void addDuration(const Duration &duration)
Add a duration to the interval.
Houses the composite key that uniquely identifies a duration:
bool operator!=(const DurationKey &other) const
Inequality operator.
isc::dhcp::SubnetID subnet_id_
Subnet ID of the subnet selected during query fulfillment.
static std::string getMessageTypeLabel(uint16_t family, uint16_t msg_type)
Get a label for a family-specific message type (e.g.
uint8_t response_type_
Response message type (e.g. DHCPOFFER, DHCP6_ADVERTISE).
bool operator<(const DurationKey &other) const
Less than operator.
std::string start_event_label_
Label of the start event which begins the duration.
bool operator==(const DurationKey &other) const
Equality operator.
DurationKey(uint16_t family, uint8_t query_type, uint8_t response_type, const std::string &start_event_label, const std::string &stop_event_label, dhcp::SubnetID subnet_id)
Constructor.
uint16_t family_
Protocol family AF_INET or AF_INET6.
std::string getStatName(const std::string &value_name) const
Get the StatsMgr formatted compatible name.
static void validateMessagePair(uint16_t family, uint8_t query_type, uint8_t response_type)
Validates that a query and response message type pair is sane.
std::string stop_event_label_
Label of the end event which ends the duration.
std::string getLabel() const
Get a composite label of the member values with text message types.
uint8_t query_type_
Query message type (e.g. DHCPDISCOVER, DHCP6_SOLICIT).
Timestamp getCurrentIntervalStart() const
Get the current interval start time.
bool addSample(const Duration &sample)
Add a sample to the duration's current interval.
void expireCurrentInterval()
Concludes the current interval.
MonitoredDuration(uint16_t family, uint8_t query_type, uint8_t response_type, const std::string &start_event_label, const std::string &stop_event_label, dhcp::SubnetID subnet_id, const Duration &interval_duration)
Constructor.
void clear()
Deletes the current and previous intervals.
@ DHCPV6_ADVERTISE
Definition: dhcp6.h:199
@ DHCPV6_REQUEST
Definition: dhcp6.h:200
@ DHCPV6_RENEW
Definition: dhcp6.h:202
@ DHCPV6_REBIND
Definition: dhcp6.h:203
@ DHCPV6_REPLY
Definition: dhcp6.h:204
@ DHCPV6_SOLICIT
Definition: dhcp6.h:198
@ DHCPV6_CONFIRM
Definition: dhcp6.h:201
@ DHCPV6_NOTYPE
Definition: dhcp6.h:197
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition: subnet_id.h:25
@ DHCPREQUEST
Definition: dhcp4.h:238
@ DHCPOFFER
Definition: dhcp4.h:237
@ DHCPNAK
Definition: dhcp4.h:241
@ DHCPDISCOVER
Definition: dhcp4.h:236
@ DHCP_NOTYPE
Message Type option missing.
Definition: dhcp4.h:235
@ DHCPINFORM
Definition: dhcp4.h:243
@ DHCPACK
Definition: dhcp4.h:240
boost::posix_time::time_duration Duration
boost::posix_time::ptime Timestamp
std::ostream & operator<<(std::ostream &os, const DurationKey &key)
Defines the logger used by the top-level component of kea-lfc.