Kea 3.1.3
lib/stats/stats_mgr.cc
Go to the documentation of this file.
1// Copyright (C) 2015-2025 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
10#include <stats/stats_mgr.h>
11#include <cc/data.h>
14#include <util/bigints.h>
15
16#include <boost/make_shared.hpp>
17
18#include <chrono>
19
20using namespace std;
21using namespace std::chrono;
22using namespace isc::data;
23using namespace isc::config;
24using namespace isc::util;
25
26namespace isc {
27namespace stats {
28
31 static StatsMgr stats_mgr;
32 return (stats_mgr);
33}
34
35StatsMgr::StatsMgr() :
36 global_(boost::make_shared<StatContext>()), mutex_(new mutex()) {
37}
38
39void
40StatsMgr::setValue(const string& name, const int64_t value) {
41 MultiThreadingLock lock(*mutex_);
42 setValueInternal(name, value);
43}
44
45void
46StatsMgr::setValue(const string& name, const int128_t& value) {
47 MultiThreadingLock lock(*mutex_);
48 setValueInternal(name, value);
49}
50
51void
52StatsMgr::setValue(const string& name, const double value) {
53 MultiThreadingLock lock(*mutex_);
54 setValueInternal(name, value);
55}
56
57void
58StatsMgr::setValue(const string& name, const StatsDuration& value) {
59 MultiThreadingLock lock(*mutex_);
60 setValueInternal(name, value);
61}
62
63void
64StatsMgr::setValue(const string& name, const string& value) {
65 MultiThreadingLock lock(*mutex_);
66 setValueInternal(name, value);
67}
68
69void
70StatsMgr::addValue(const string& name, const int64_t value) {
71 MultiThreadingLock lock(*mutex_);
72 addValueInternal(name, value);
73}
74
75void
76StatsMgr::addValue(const string& name, const int128_t& value) {
77 MultiThreadingLock lock(*mutex_);
78 addValueInternal(name, value);
79}
80
81void
82StatsMgr::addValue(const string& name, const double value) {
83 MultiThreadingLock lock(*mutex_);
84 addValueInternal(name, value);
85}
86
87void
88StatsMgr::addValue(const string& name, const StatsDuration& value) {
89 MultiThreadingLock lock(*mutex_);
90 addValueInternal(name, value);
91}
92
93void
94StatsMgr::addValue(const string& name, const string& value) {
95 MultiThreadingLock lock(*mutex_);
96 addValueInternal(name, value);
97}
98
100StatsMgr::getObservation(const string& name) const {
101 MultiThreadingLock lock(*mutex_);
102 return (getObservationInternal(name));
103}
104
106StatsMgr::getObservationInternal(const string& name) const {
108 // Currently we keep everything in a global context.
109 return (global_->get(name));
110}
111
112void
117
118void
121 // Currently we keep everything in a global context.
122 global_->add(stat);
123}
124
125bool
126StatsMgr::deleteObservation(const string& name) {
127 MultiThreadingLock lock(*mutex_);
128 return (deleteObservationInternal(name));
129}
130
131bool
132StatsMgr::deleteObservationInternal(const string& name) {
134 // Currently we keep everything in a global context.
135 return (global_->del(name));
136}
137
138bool
139StatsMgr::setMaxSampleAge(const string& name, const StatsDuration& duration) {
140 MultiThreadingLock lock(*mutex_);
141 return (setMaxSampleAgeInternal(name, duration));
142}
143
144bool
145StatsMgr::setMaxSampleAgeInternal(const string& name,
146 const StatsDuration& duration) {
148 if (obs) {
149 obs->setMaxSampleAge(duration);
150 return (true);
151 }
152 return (false);
153}
154
155bool
156StatsMgr::setMaxSampleCount(const string& name, uint32_t max_samples) {
157 MultiThreadingLock lock(*mutex_);
158 return (setMaxSampleCountInternal(name, max_samples));
159}
160
161bool
162StatsMgr::setMaxSampleCountInternal(const string& name,
163 uint32_t max_samples) {
165 if (obs) {
166 obs->setMaxSampleCount(max_samples);
167 return (true);
168 }
169 return (false);
170}
171
172void
174 MultiThreadingLock lock(*mutex_);
175 setMaxSampleAgeAllInternal(duration);
176}
177
178void
179StatsMgr::setMaxSampleAgeAllInternal(const StatsDuration& duration) {
180 global_->setMaxSampleAgeAll(duration);
181}
182
183void
184StatsMgr::setMaxSampleCountAll(uint32_t max_samples) {
185 MultiThreadingLock lock(*mutex_);
186 setMaxSampleCountAllInternal(max_samples);
187}
188
189void
190StatsMgr::setMaxSampleCountAllInternal(uint32_t max_samples) {
191 global_->setMaxSampleCountAll(max_samples);
192}
193
194void
196 MultiThreadingLock lock(*mutex_);
197 setMaxSampleAgeDefaultInternal(duration);
198}
199
200void
201StatsMgr::setMaxSampleAgeDefaultInternal(const StatsDuration& duration) {
203}
204
205void
207 MultiThreadingLock lock(*mutex_);
208 setMaxSampleCountDefaultInternal(max_samples);
209}
210
211void
212StatsMgr::setMaxSampleCountDefaultInternal(uint32_t max_samples) {
214}
215
216const StatsDuration&
218 MultiThreadingLock lock(*mutex_);
219 return (getMaxSampleAgeDefaultInternal());
220}
221
222const StatsDuration&
223StatsMgr::getMaxSampleAgeDefaultInternal() const {
225}
226
227uint32_t
229 MultiThreadingLock lock(*mutex_);
230 return (getMaxSampleCountDefaultInternal());
231}
232
233uint32_t
234StatsMgr::getMaxSampleCountDefaultInternal() const {
236}
237
238bool
239StatsMgr::reset(const string& name) {
240 MultiThreadingLock lock(*mutex_);
241 return (resetInternal(name));
242}
243
244bool
245StatsMgr::resetInternal(const string& name) {
247 if (obs) {
248 obs->reset();
249 return (true);
250 }
251 return (false);
252}
253
254bool
255StatsMgr::del(const string& name) {
256 MultiThreadingLock lock(*mutex_);
257 return (delInternal(name));
258}
259
260bool
261StatsMgr::delInternal(const string& name) {
262 return (global_->del(name));
263}
264
265void
267 MultiThreadingLock lock(*mutex_);
268 removeAllInternal();
269}
270
271void
272StatsMgr::removeAllInternal() {
273 global_->clear();
274}
275
277StatsMgr::get(const string& name) const {
278 MultiThreadingLock lock(*mutex_);
279 return (getInternal(name));
280}
281
283StatsMgr::getInternal(const string& name) const {
284 ElementPtr map = Element::createMap(); // a map
286 if (obs) {
287 map->set(name, obs->getJSON()); // that contains observations
288 }
289 return (map);
290}
291
294 MultiThreadingLock lock(*mutex_);
295 return (getAllInternal());
296}
297
300 MultiThreadingLock lock(*mutex_);
301 return (getAllGlobalInternal());
302}
303
305StatsMgr::getAllInternal() const {
306 return (global_->getAll());
307}
308
310StatsMgr::getAllGlobalInternal() const {
311 return (global_->getAllGlobal());
312}
313
314void
316 MultiThreadingLock lock(*mutex_);
317 resetAllInternal();
318}
319
320void
321StatsMgr::resetAllInternal() {
322 global_->resetAll();
323}
324
325size_t
326StatsMgr::getSize(const string& name) const {
327 MultiThreadingLock lock(*mutex_);
328 return (getSizeInternal(name));
329}
330
331size_t
332StatsMgr::getSizeInternal(const string& name) const {
334 if (obs) {
335 return (obs->getSize());
336 }
337 return (0);
338}
339
340size_t
342 MultiThreadingLock lock(*mutex_);
343 return (countInternal());
344}
345
346size_t
347StatsMgr::countInternal() const {
348 return (global_->size());
349}
350
353 const ConstElementPtr& params) {
354 string name, error;
355 StatsDuration duration;
356 if (!StatsMgr::getStatName(params, name, error)) {
357 return (createAnswer(CONTROL_RESULT_ERROR, error));
358 }
359 if (!StatsMgr::getStatDuration(params, duration, error)) {
360 return (createAnswer(CONTROL_RESULT_ERROR, error));
361 }
362 if (StatsMgr::instance().setMaxSampleAge(name, duration)) {
364 "Statistic '" + name + "' duration limit is set."));
365 } else {
367 "No '" + name + "' statistic found"));
368 }
369}
370
373 const ConstElementPtr& params) {
374 string name, error;
375 uint32_t max_samples;
376 if (!StatsMgr::getStatName(params, name, error)) {
377 return (createAnswer(CONTROL_RESULT_ERROR, error));
378 }
379 if (!StatsMgr::getStatMaxSamples(params, max_samples, error)) {
380 return (createAnswer(CONTROL_RESULT_ERROR, error));
381 }
382 if (StatsMgr::instance().setMaxSampleCount(name, max_samples)) {
384 "Statistic '" + name + "' count limit is set."));
385 } else {
387 "No '" + name + "' statistic found"));
388 }
389}
390
392StatsMgr::statisticGetHandler(const string& /*name*/,
393 const ConstElementPtr& params) {
394 string name, error;
395 if (!StatsMgr::getStatName(params, name, error)) {
396 return (createAnswer(CONTROL_RESULT_ERROR, error));
397 }
399 StatsMgr::instance().get(name)));
400}
401
403StatsMgr::statisticResetHandler(const string& /*name*/,
404 const ConstElementPtr& params) {
405 string name, error;
406 if (!StatsMgr::getStatName(params, name, error)) {
407 return (createAnswer(CONTROL_RESULT_ERROR, error));
408 }
409 if (StatsMgr::instance().reset(name)) {
411 "Statistic '" + name + "' reset."));
412 } else {
414 "No '" + name + "' statistic found"));
415 }
416}
417
419StatsMgr::statisticRemoveHandler(const string& /*name*/,
420 const ConstElementPtr& params) {
421 string name, error;
422 if (!StatsMgr::getStatName(params, name, error)) {
423 return (createAnswer(CONTROL_RESULT_ERROR, error));
424 }
425 if (StatsMgr::instance().del(name)) {
427 "Statistic '" + name + "' removed."));
428 } else {
430 "No '" + name + "' statistic found"));
431 }
432
433}
434
437 const ConstElementPtr& /*params*/) {
440 "Warning: statistic-remove-all command is deprecated."
441 " All statistics removed."));
442}
443
445StatsMgr::statisticGetAllHandler(const string& /*name*/,
446 const ConstElementPtr& /*params*/) {
448 return (createAnswer(CONTROL_RESULT_SUCCESS, all_stats));
449}
450
453 const ConstElementPtr& /*params*/) {
455 return (createAnswer(CONTROL_RESULT_SUCCESS, all_stats));
456}
457
460 const ConstElementPtr& /*params*/) {
463 "All statistics reset to neutral values."));
464}
465
468 string error;
469 StatsDuration duration;
470 if (!StatsMgr::getStatDuration(params, duration, error)) {
471 return (createAnswer(CONTROL_RESULT_ERROR, error));
472 }
473 MultiThreadingLock lock(*mutex_);
474 StatsMgr::instance().setMaxSampleCountDefaultInternal(0);
475 StatsMgr::instance().setMaxSampleAgeDefaultInternal(duration);
476 StatsMgr::instance().setMaxSampleAgeAllInternal(duration);
478 "All statistics duration limit are set."));
479}
480
483 string error;
484 uint32_t max_samples;
485 if (!StatsMgr::getStatMaxSamples(params, max_samples, error)) {
486 return (createAnswer(CONTROL_RESULT_ERROR, error));
487 }
488 if (max_samples == 0) {
489 error = "'max-samples' parameter must not be zero";
490 return (createAnswer(CONTROL_RESULT_ERROR, error));
491 }
492 MultiThreadingLock lock(*mutex_);
493 StatsMgr::instance().setMaxSampleCountDefaultInternal(max_samples);
494 StatsMgr::instance().setMaxSampleCountAllInternal(max_samples);
496 "All statistics count limit are set."));
497}
498
499bool
500StatsMgr::getStatName(const ConstElementPtr& params,
501 string& name,
502 string& reason) {
503 if (!params) {
504 reason = "Missing mandatory 'name' parameter.";
505 return (false);
506 }
507 ConstElementPtr stat_name = params->get("name");
508 if (!stat_name) {
509 reason = "Missing mandatory 'name' parameter.";
510 return (false);
511 }
512 if (stat_name->getType() != Element::string) {
513 reason = "'name' parameter expected to be a string.";
514 return (false);
515 }
516 name = stat_name->stringValue();
517 return (true);
518}
519
520bool
521StatsMgr::getStatDuration(const ConstElementPtr& params,
522 StatsDuration& duration,
523 string& reason) {
524 if (!params) {
525 reason = "Missing mandatory 'duration' parameter.";
526 return (false);
527 }
528 ConstElementPtr stat_duration = params->get("duration");
529 if (!stat_duration) {
530 reason = "Missing mandatory 'duration' parameter.";
531 return (false);
532 }
533 duration = std::chrono::seconds(stat_duration->intValue());
534 return (true);
535}
536
537bool
538StatsMgr::getStatMaxSamples(const ConstElementPtr& params,
539 uint32_t& max_samples,
540 string& reason) {
541 if (!params) {
542 reason = "Missing mandatory 'max-samples' parameter.";
543 return (false);
544 }
545 ConstElementPtr stat_max_samples = params->get("max-samples");
546 if (!stat_max_samples) {
547 reason = "Missing mandatory 'max-samples' parameter.";
548 return (false);
549 }
550 if (stat_max_samples->getType() != Element::integer) {
551 reason = "'max-samples' parameter expected to be an integer.";
552 return (false);
553 }
554 max_samples = stat_max_samples->intValue();
555 return (true);
556}
557
558} // end of namespace stats
559} // end of namespace isc
@ integer
Definition data.h:140
@ string
Definition data.h:144
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static const StatsDuration & getMaxSampleAgeDefault()
Get default maximum age of samples.
static uint32_t getMaxSampleCountDefault()
Get default maximum count of samples.
static void setMaxSampleCountDefault(uint32_t max_samples)
Determines default maximum count of samples.
static void setMaxSampleAgeDefault(const StatsDuration &duration)
Determines default maximum age of samples.
Statistics Manager class.
ObservationPtr getObservation(const std::string &name) const
Returns an observation.
ObservationPtr getObservationInternal(const std::string &name) const
Returns an observation in a thread safe context.
static StatsMgr & instance()
Statistics Manager accessor method.
void addObservationInternal(const ObservationPtr &stat)
Adds a new observation in a thread safe context.
void addValueInternal(const std::string &name, DataType value)
Adds specified value to a given statistic (internal version).
void addObservation(const ObservationPtr &stat)
Adds a new observation.
void setValueInternal(const std::string &name, DataType value)
Sets a given statistic to specified value (internal version).
This file contains several functions and constants that are used for handling commands and responses ...
isc::data::ConstElementPtr statisticSetMaxSampleCountAllHandler(const isc::data::ConstElementPtr &params)
Handles statistic-sample-count-set-all command.
static isc::data::ConstElementPtr statisticResetHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-reset command.
static isc::data::ConstElementPtr statisticGetAllHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-get-all command.
static isc::data::ConstElementPtr statisticRemoveHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-remove command.
static isc::data::ConstElementPtr statisticGetHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-get command.
static isc::data::ConstElementPtr statisticGlobalGetAllHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-global-get-all command.
isc::data::ConstElementPtr statisticSetMaxSampleAgeAllHandler(const isc::data::ConstElementPtr &params)
Handles statistic-sample-age-set-all command.
static isc::data::ConstElementPtr statisticResetAllHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-reset-all command.
static isc::data::ConstElementPtr statisticSetMaxSampleAgeHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-sample-age-set command.
static isc::data::ConstElementPtr statisticRemoveAllHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-remove-all command.
static isc::data::ConstElementPtr statisticSetMaxSampleCountHandler(const std::string &name, const isc::data::ConstElementPtr &params)
Handles statistic-sample-count-set command.
bool reset(const std::string &name)
Resets specified statistic.
void removeAll()
Removes all collected statistics.
isc::data::ConstElementPtr getAllGlobal() const
Returns all global statistics (omitting subnet statistics) as a JSON structure.
void resetAll()
Resets all collected statistics back to zero.
bool del(const std::string &name)
Removes specified statistic.
size_t count() const
Returns number of available statistics.
isc::data::ConstElementPtr getAll() const
Returns all statistics as a JSON structure.
size_t getSize(const std::string &name) const
Returns size of specified statistic.
isc::data::ConstElementPtr get(const std::string &name) const
Returns a single statistic as a JSON structure.
void setMaxSampleCountDefault(uint32_t max_samples)
Set default count limit.
bool setMaxSampleCount(const std::string &name, uint32_t max_samples)
Determines how many samples of a given statistic should be kept.
uint32_t getMaxSampleCountDefault() const
Get default count limit.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
bool setMaxSampleAge(const std::string &name, const StatsDuration &duration)
Determines maximum age of samples.
const StatsDuration & getMaxSampleAgeDefault() const
Get default duration limit.
void setMaxSampleAgeAll(const StatsDuration &duration)
Set duration limit for all collected statistics.
void setMaxSampleCountAll(uint32_t max_samples)
Set count limit for all collected statistics.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
void setMaxSampleAgeDefault(const StatsDuration &duration)
Set default duration limit.
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
ConstElementPtr createAnswer()
Creates a standard config/command level success answer message (i.e.
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< Observation > ObservationPtr
Observation pointer.
std::chrono::system_clock::duration StatsDuration
Defines duration type.
Definition observation.h:43
boost::multiprecision::checked_int128_t int128_t
Definition bigints.h:19
Defines the logger used by the top-level component of kea-lfc.
Statistics context.
Definition context.h:31
RAII lock object to protect the code in the same scope with a mutex.