continue])
AC_MSG_CHECKING(range-for support)
- feature="constexpr"
+ feature="range-for support"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[#include <vector>
[#include <atomic>
std::atomic_flag flag;],
[])],
- [AC_MSG_RESULT([yes])
- break],
+ [AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
continue])
+ AC_MSG_CHECKING(chrono support)
+ feature="chrono"
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <chrono>
+ using namespace std::chrono;],
+ [auto now = high_resolution_clock::now();])],
+ [AC_MSG_RESULT([yes])
+ break],
+ [AC_MSG_RESULT([no])
+ continue])
+
done
-])dnl AX_ISC_RPATH
+])dnl AX_ISC_CPP11
#include <hooks/hooks_manager.h>
#include <log/logger_support.h>
#include <stats/stats_mgr.h>
-#include <util/boost_time_utils.h>
#include <util/multi_threading_mgr.h>
+#include <util/chrono_time_utils.h>
#include <testutils/io_utils.h>
#include <testutils/unix_control_client.h>
#include <testutils/sandbox.h>
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 << isc::util::clockToText(StatsMgr::instance().getObservation(*st)->getInteger().second);
s << "\" ] ]";
if (++st != initial_stats.end()) {
s << ", ";
#include <hooks/hooks_manager.h>
#include <log/logger_support.h>
#include <stats/stats_mgr.h>
-#include <util/boost_time_utils.h>
#include <util/multi_threading_mgr.h>
#include <testutils/io_utils.h>
#include <testutils/unix_control_client.h>
#include <testutils/sandbox.h>
+#include <util/chrono_time_utils.h>
#include "marker_file.h"
#include "test_libraries.h"
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 << isc::util::clockToText(StatsMgr::instance().getObservation(*st)->getInteger().second);
s << "\" ] ]";
if (++st != initial_stats.end()) {
s << ", ";
#include <config.h>
#include <stats/observation.h>
-#include <util/boost_time_utils.h>
+#include <util/chrono_time_utils.h>
#include <cc/data.h>
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/date_time/gregorian/gregorian.hpp>
+#include <chrono>
#include <utility>
using namespace std;
+using namespace std::chrono;
using namespace isc::data;
-using namespace boost::posix_time;
namespace isc {
namespace stats {
}
if (storage.empty()) {
- storage.push_back(make_pair(value, microsec_clock::local_time()));
+ storage.push_back(make_pair(value, SampleClock::now()));
} else {
// Storing of more than one sample
- storage.push_front(make_pair(value, microsec_clock::local_time()));
+ storage.push_front(make_pair(value, SampleClock::now()));
if (max_sample_count_.first) {
// if max_sample_count_ is set to true
for (std::list<IntegerSample>::iterator it = s.begin(); it != s.end(); ++it) {
entry = isc::data::Element::createList();
value = isc::data::Element::create(static_cast<int64_t>((*it).first));
- timestamp = isc::data::Element::create(isc::util::ptimeToText((*it).second));
+ timestamp = isc::data::Element::create(isc::util::clockToText((*it).second));
entry->add(value);
entry->add(timestamp);
for (std::list<FloatSample>::iterator it = s.begin(); it != s.end(); ++it) {
entry = isc::data::Element::createList();
value = isc::data::Element::create((*it).first);
- timestamp = isc::data::Element::create(isc::util::ptimeToText((*it).second));
+ timestamp = isc::data::Element::create(isc::util::clockToText((*it).second));
entry->add(value);
entry->add(timestamp);
for (std::list<DurationSample>::iterator it = s.begin(); it != s.end(); ++it) {
entry = isc::data::Element::createList();
value = isc::data::Element::create(isc::util::durationToText((*it).first));
- timestamp = isc::data::Element::create(isc::util::ptimeToText((*it).second));
+ timestamp = isc::data::Element::create(isc::util::clockToText((*it).second));
entry->add(value);
entry->add(timestamp);
for (std::list<StringSample>::iterator it = s.begin(); it != s.end(); ++it) {
entry = isc::data::Element::createList();
value = isc::data::Element::create((*it).first);
- timestamp = isc::data::Element::create(isc::util::ptimeToText((*it).second));
+ timestamp = isc::data::Element::create(isc::util::clockToText((*it).second));
entry->add(value);
entry->add(timestamp);
}
case STAT_DURATION: {
duration_samples_.clear();
- setValue(time_duration(0, 0, 0, 0));
+ setValue(StatsDuration::zero());
return;
}
case STAT_STRING: {
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <boost/shared_ptr.hpp>
-#include <boost/date_time/time_duration.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <chrono>
#include <list>
#include <stdint.h>
isc::Exception(file, line, what) {}
};
+/// @brief Define clock
+///
+typedef std::chrono::system_clock SampleClock;
+
/// @brief Defines duration resolution
///
-typedef boost::posix_time::time_duration StatsDuration;
+typedef std::chrono::system_clock::duration StatsDuration;
/// @defgroup stat_samples Specifies supported observation types.
///
/// @{
/// @brief Integer (implemented as signed 64-bit integer)
-typedef std::pair<int64_t, boost::posix_time::ptime> IntegerSample;
+typedef std::pair<int64_t, SampleClock::time_point> IntegerSample;
/// @brief Float (implemented as double precision)
-typedef std::pair<double, boost::posix_time::ptime> FloatSample;
+typedef std::pair<double, SampleClock::time_point> FloatSample;
/// @brief Time Duration
-typedef std::pair<StatsDuration, boost::posix_time::ptime> DurationSample;
+typedef std::pair<StatsDuration, SampleClock::time_point> DurationSample;
/// @brief String
-typedef std::pair<std::string, boost::posix_time::ptime> StringSample;
+typedef std::pair<std::string, SampleClock::time_point> StringSample;
/// @}
/// @param duration determines maximum age of samples
/// Example:
/// To set a statistic to keep observations for the last 5 minutes, call:
- /// setMaxSampleAge(time_duration(0, 5, 0, 0));
+ /// setMaxSampleAge(std::chrono::minutes(5));
/// To revert statistic to a single value, call:
- /// setMaxSampleAge(time_duration(0, 0, 0, 0));
+ /// setMaxSampleAge(StatsDuration::zero());
void setMaxSampleAge(const StatsDuration& duration);
/// @brief Determines how many samples of a given statistic should be kept.
/// @brief Maximum timespan of samples
/// The limit is represented as a pair
- /// of bool value and StatsDuration(boost::posix_time::time_duration)
+ /// of bool value and StatsDuration
/// Only one kind of limit can be active
/// The bool value informs which limit
/// is available
///
/// By default the MaxSampleCount is set to 20
/// and MaxSampleAge is disabled
- static std::pair<bool, StatsDuration> default_max_sample_age_;
+ std::pair<bool, StatsDuration> max_sample_age_ = std::make_pair(false,
+ StatsDuration::zero());
/// @defgroup samples_storage Storage for supported observations
///
#include <stats/stats_mgr.h>
#include <cc/data.h>
#include <cc/command_interpreter.h>
-#include <util/boost_time_utils.h>
#include <util/multi_threading_mgr.h>
-#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/make_shared.hpp>
+#include <chrono>
using namespace std;
+using namespace std::chrono;
using namespace isc::data;
using namespace isc::config;
using namespace isc::util;
reason = "Missing mandatory 'duration' parameter.";
return (false);
}
- int64_t time_duration = stat_duration->intValue();
- int64_t hours = time_duration / 3600;
- time_duration -= hours * 3600;
- int64_t minutes = time_duration / 60;
- time_duration -= minutes * 60;
- int64_t seconds = time_duration;
- duration = boost::posix_time::time_duration(hours, minutes, seconds, 0);
+ duration = std::chrono::seconds(stat_duration->intValue());
return (true);
}
/// setMaxSampleCount() below.
/// Example:
/// To set a statistic to keep observations for the last 5 minutes, call:
- /// setMaxSampleAge("incoming-packets", time_duration(0, 5, 0, 0));
+ /// setMaxSampleAge("incoming-packets", StatsDuration::minutes(5));
/// to revert statistic to a single value, call:
- /// setMaxSampleAge("incoming-packets", time_duration(0, 0, 0, 0));
+ /// setMaxSampleAge("incoming-packets", StatsDuration:zero());
///
/// @param name name of the observation
/// @param duration determines maximum age of samples
#include <stats/context.h>
#include <gtest/gtest.h>
-#include <util/boost_time_utils.h>
+#include <util/chrono_time_utils.h>
#include <string>
using namespace isc::data;
using namespace isc::stats;
-using namespace boost::posix_time;
using namespace std;
+using namespace std::chrono;
// Basic test that checks get, add, del methods
TEST(ContextTest, basic) {
EXPECT_EQ(from_ctx->getMaxSampleCount().second, 50);
// Set sample age for all statistics
- EXPECT_NO_THROW(ctx.setMaxSampleAgeAll(millisec::time_duration(0, 4, 5, 3)));
+ const StatsDuration& dur(minutes(4) + seconds(5) + milliseconds(3));
+ EXPECT_NO_THROW(ctx.setMaxSampleAgeAll(dur));
EXPECT_NO_THROW(from_ctx = ctx.get("alpha"));
ASSERT_TRUE(from_ctx);
- EXPECT_EQ(from_ctx->getMaxSampleAge().second, millisec::time_duration(0, 4, 5, 3));
+ EXPECT_EQ(from_ctx->getMaxSampleAge().second, dur);
EXPECT_NO_THROW(from_ctx = ctx.get("gamma"));
ASSERT_TRUE(from_ctx);
- EXPECT_EQ(from_ctx->getMaxSampleAge().second, millisec::time_duration(0, 4, 5, 3));
+ EXPECT_EQ(from_ctx->getMaxSampleAge().second, dur);
// Clear all statistics.
EXPECT_NO_THROW(ctx.clear());
#include <stats/observation.h>
#include <exceptions/exceptions.h>
-#include <util/boost_time_utils.h>
+#include <util/chrono_time_utils.h>
#include <boost/shared_ptr.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <gtest/gtest.h>
#include <iostream>
using namespace isc;
using namespace isc::stats;
-using namespace boost::posix_time;
+using namespace std::chrono;
namespace {
+const StatsDuration& dur1234(hours(1) + minutes(2) + seconds(3) +
+ milliseconds(4));
+const StatsDuration& dur5678(hours(5) + minutes(6) + seconds(7) +
+ milliseconds(8));
+const StatsDuration& dur681012(hours(6) + minutes(8) + seconds(10) +
+ milliseconds(12));
+const StatsDuration& dur453(minutes(4) + seconds(5) + milliseconds(3));
+
/// @brief Test class for Observation
///
/// This simple fixture class initializes four observations:
ObservationTest() :
a("alpha", static_cast<int64_t>(1234)), // integer
b("beta", 12.34), // float
- c("gamma", millisec::time_duration(1, 2, 3, 4)), // duration
+ c("gamma", dur1234), // duration
d("delta", "1234") { // string
}
EXPECT_EQ(1234, a.getInteger().first);
EXPECT_EQ(12.34, b.getFloat().first);
- EXPECT_EQ(millisec::time_duration(1, 2, 3, 4),
- c.getDuration().first);
+ EXPECT_EQ(dur1234, c.getDuration().first);
EXPECT_EQ("1234", d.getString().first);
// Let's check that attempting to get a different type
TEST_F(ObservationTest, setValue) {
EXPECT_NO_THROW(a.setValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.setValue(56e+78));
- EXPECT_NO_THROW(c.setValue(millisec::time_duration(5, 6, 7, 8)));
+ EXPECT_NO_THROW(c.setValue(dur5678));
EXPECT_NO_THROW(d.setValue("fiveSixSevenEight"));
EXPECT_EQ(5678, a.getInteger().first);
EXPECT_EQ(56e+78, b.getFloat().first);
- EXPECT_EQ(millisec::time_duration(5, 6, 7, 8), c.getDuration().first);
+ EXPECT_EQ(dur5678, c.getDuration().first);
EXPECT_EQ("fiveSixSevenEight", d.getString().first);
// Now check whether setting value to a different type does
// throw an exception
EXPECT_THROW(a.setValue(56e+78), InvalidStatType);
- EXPECT_THROW(a.setValue(millisec::time_duration(5, 6, 7, 8)), InvalidStatType);
+ EXPECT_THROW(a.setValue(dur5678), InvalidStatType);
EXPECT_THROW(a.setValue("fiveSixSevenEight"), InvalidStatType);
EXPECT_THROW(b.setValue(static_cast<int64_t>(5678)), InvalidStatType);
- EXPECT_THROW(b.setValue(millisec::time_duration(5, 6, 7, 8)), InvalidStatType);
+ EXPECT_THROW(b.setValue(dur5678), InvalidStatType);
EXPECT_THROW(b.setValue("fiveSixSevenEight"), InvalidStatType);
EXPECT_THROW(c.setValue(static_cast<int64_t>(5678)), InvalidStatType);
EXPECT_THROW(d.setValue(static_cast<int64_t>(5678)), InvalidStatType);
EXPECT_THROW(d.setValue(56e+78), InvalidStatType);
- EXPECT_THROW(d.setValue(millisec::time_duration(5, 6, 7, 8)), InvalidStatType);
+ EXPECT_THROW(d.setValue(dur5678), InvalidStatType);
}
// This test checks whether it is possible to add value to existing
EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.addValue(56.78));
- EXPECT_NO_THROW(c.addValue(millisec::time_duration(5, 6, 7, 8)));
+ EXPECT_NO_THROW(c.addValue(dur5678));
EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
EXPECT_EQ(6912, a.getInteger().first);
EXPECT_EQ(69.12, b.getFloat().first);
- EXPECT_EQ(millisec::time_duration(6, 8, 10, 12), c.getDuration().first);
+ EXPECT_EQ(dur681012, c.getDuration().first);
EXPECT_EQ("1234fiveSixSevenEight", d.getString().first);
ASSERT_EQ(a.getSize(), 2);
// Arrays of 4 types of samples
int64_t int_samples[3] = {1234, 6912, 5678};
double float_samples[3] = {12.34, 69.12, 56e+78};
- millisec::time_duration duration_samples[3] = {millisec::time_duration(1, 2, 3, 4),
- millisec::time_duration(6, 8, 10, 12), millisec::time_duration(5, 6, 7, 8)};
+ StatsDuration duration_samples[3] = {dur1234,
+ dur681012, dur5678};
std::string string_samples[3] = {"1234", "1234fiveSixSevenEight", "fiveSixSevenEight"};
EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.addValue(56.78));
- EXPECT_NO_THROW(c.addValue(millisec::time_duration(5, 6, 7, 8)));
+ EXPECT_NO_THROW(c.addValue(dur5678));
EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
EXPECT_NO_THROW(a.setValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.setValue(56e+78));
- EXPECT_NO_THROW(c.setValue(millisec::time_duration(5, 6, 7, 8)));
+ EXPECT_NO_THROW(c.setValue(dur5678));
EXPECT_NO_THROW(d.setValue("fiveSixSevenEight"));
ASSERT_EQ(a.getSize(), 3);
a.addValue(static_cast<int64_t>(5678));
b.addValue(56.78);
- c.addValue(millisec::time_duration(5, 6, 7, 8));
+ c.addValue(dur5678);
d.addValue("fiveSixSevenEight");
EXPECT_NO_THROW(a.getSize());
a.setValue(static_cast<int64_t>(5678));
b.setValue(56e+78);
- c.setValue(millisec::time_duration(5, 6, 7, 8));
+ c.setValue(dur5678);
d.setValue("fiveSixSevenEight");
EXPECT_NO_THROW(a.getSize());
std::string string_samples[22] = {"a", "b", "c", "d", "e", "f", "g", "h",
"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
"v"};
- millisec::time_duration duration_samples[22];
+ StatsDuration duration_samples[22];
for (uint32_t i = 0; i < 22; ++i) {
- duration_samples[i] = millisec::time_duration(0, 0, 0, i);
+ duration_samples[i] = milliseconds(i);
}
// By default the max_sample_count is set to 20 and max_sample_age
// Add new values to each type of Observation
a.setValue(static_cast<int64_t>(21));
b.setValue(21.0);
- c.setValue(millisec::time_duration(0, 0, 0, 21));
+ c.setValue(milliseconds(21));
d.setValue("v");
samples_int = a.getIntegers();
// Checks whether setting age limits works properly
TEST_F(ObservationTest, setAgeLimit) {
// Set max_sample_age to 1 second
- ASSERT_NO_THROW(c.setMaxSampleAge(millisec::time_duration(0, 0, 1, 0)));
+ ASSERT_NO_THROW(c.setMaxSampleAge(seconds(1)));
// Add some value
- c.setValue(millisec::time_duration(0, 0, 0, 5));
+ c.setValue(milliseconds(5));
// Wait 1 second
sleep(1);
// and add new value
- c.setValue(millisec::time_duration(0, 0, 0, 3));
+ c.setValue(milliseconds(3));
// get the list of all samples
std::list<DurationSample> samples_duration = c.getDurations();
// check whether the size of samples is equal to 1
ASSERT_EQ(c.getSize(), 1);
// and whether it contains an expected value
- EXPECT_EQ((*samples_duration.begin()).first, millisec::time_duration(0, 0, 0, 3));
+ EXPECT_EQ((*samples_duration.begin()).first, milliseconds(3));
// Wait 1 second to ensure removing previously set value
sleep(1);
// add 10 new values
for (uint32_t i = 0; i < 10; ++i) {
- c.setValue(millisec::time_duration(0, 0, 0, i));
+ c.setValue(milliseconds(i));
}
// change the max_sample_age to smaller
- ASSERT_NO_THROW(c.setMaxSampleAge(millisec::time_duration(0, 0, 0, 300)));
+ ASSERT_NO_THROW(c.setMaxSampleAge(milliseconds(300)));
samples_duration = c.getDurations();
// check whether the size of samples is equal to 10
// and whether it contains expected values
uint32_t i = 9;
for (std::list<DurationSample>::iterator it = samples_duration.begin(); it != samples_duration.end(); ++it) {
- EXPECT_EQ((*it).first, millisec::time_duration(0, 0, 0, i));
+ EXPECT_EQ((*it).first, milliseconds(i));
--i;
}
}
EXPECT_EQ(d.getMaxSampleCount().second, 20);
// change limit to time duration
- ASSERT_NO_THROW(a.setMaxSampleAge(millisec::time_duration(0, 4, 5, 3)));
- ASSERT_NO_THROW(b.setMaxSampleAge(millisec::time_duration(0, 4, 5, 3)));
- ASSERT_NO_THROW(c.setMaxSampleAge(millisec::time_duration(0, 4, 5, 3)));
- ASSERT_NO_THROW(d.setMaxSampleAge(millisec::time_duration(0, 4, 5, 3)));
+ ASSERT_NO_THROW(a.setMaxSampleAge(dur453));
+ ASSERT_NO_THROW(b.setMaxSampleAge(dur453));
+ ASSERT_NO_THROW(c.setMaxSampleAge(dur453));
+ ASSERT_NO_THROW(d.setMaxSampleAge(dur453));
EXPECT_EQ(a.getMaxSampleAge().first, true);
EXPECT_EQ(b.getMaxSampleAge().first, true);
EXPECT_EQ(c.getMaxSampleAge().first, true);
EXPECT_EQ(d.getMaxSampleAge().first, true);
- EXPECT_EQ(a.getMaxSampleAge().second, millisec::time_duration(0, 4, 5, 3));
- EXPECT_EQ(b.getMaxSampleAge().second, millisec::time_duration(0, 4, 5, 3));
- EXPECT_EQ(c.getMaxSampleAge().second, millisec::time_duration(0, 4, 5, 3));
- EXPECT_EQ(d.getMaxSampleAge().second, millisec::time_duration(0, 4, 5, 3));
+ EXPECT_EQ(a.getMaxSampleAge().second, dur453);
+ EXPECT_EQ(b.getMaxSampleAge().second, dur453);
+ EXPECT_EQ(c.getMaxSampleAge().second, dur453);
+ EXPECT_EQ(d.getMaxSampleAge().second, dur453);
EXPECT_EQ(a.getMaxSampleCount().first, false);
EXPECT_EQ(b.getMaxSampleCount().first, false);
// Test checks whether timing is reported properly.
TEST_F(ObservationTest, timers) {
- ptime before = microsec_clock::local_time();
+ auto before = SampleClock::now();
b.setValue(123.0); // Set it to a random value and record the time.
// Allow a bit of imprecision. This test allows 500ms. That should be ok,
// when running on virtual machines.
- ptime after = before + milliseconds(500);
+ auto after = before + milliseconds(500);
// Now wait some time. We want to confirm that the timestamp recorded is the
// time the observation took place, not current time.
TEST_F(ObservationTest, integerToJSON) {
// String which contains first added sample
std::string first_sample = ", [ 1234, \"" +
- isc::util::ptimeToText(a.getInteger().second) + "\" ] ]";
+ isc::util::clockToText(a.getInteger().second) + "\" ] ]";
a.setValue(static_cast<int64_t>(1234));
std::string exp = "[ [ 1234, \"" +
- isc::util::ptimeToText(a.getInteger().second) + "\" ]" + first_sample;
+ isc::util::clockToText(a.getInteger().second) + "\" ]" + first_sample;
std::cout << a.getJSON()->str() << std::endl;
EXPECT_EQ(exp, a.getJSON()->str());
TEST_F(ObservationTest, floatToJSON) {
// String which contains first added sample
std::string first_sample = ", [ 12.34, \"" +
- isc::util::ptimeToText(b.getFloat().second) + "\" ] ]";
+ isc::util::clockToText(b.getFloat().second) + "\" ] ]";
// Let's use a value that converts easily to floating point.
// No need to deal with infinite fractions in binary systems.
b.setValue(1234.5);
std::string exp = "[ [ 1234.5, \"" +
- isc::util::ptimeToText(b.getFloat().second) + "\" ]" + first_sample;
+ isc::util::clockToText(b.getFloat().second) + "\" ]" + first_sample;
std::cout << b.getJSON()->str() << std::endl;
EXPECT_EQ(exp, b.getJSON()->str());
// details.
TEST_F(ObservationTest, durationToJSON) {
// String which contains first added sample
- std::string first_sample = ", [ \"01:02:03.000004\", \"" +
- isc::util::ptimeToText(c.getDuration().second) + "\" ] ]";
+ std::string first_sample = ", [ \"01:02:03.004000\", \"" +
+ isc::util::clockToText(c.getDuration().second) + "\" ] ]";
// 1 hour 2 minutes 3 seconds and 4 milliseconds
- c.setValue(time_duration(1, 2, 3, 4));
+ c.setValue(dur1234);
- std::string exp = "[ [ \"01:02:03.000004\", \"" +
- isc::util::ptimeToText(c.getDuration().second) + "\" ]" + first_sample;
+ std::string exp = "[ [ \"01:02:03.004000\", \"" +
+ isc::util::clockToText(c.getDuration().second) + "\" ]" + first_sample;
std::cout << c.getJSON()->str() << std::endl;
EXPECT_EQ(exp, c.getJSON()->str());
TEST_F(ObservationTest, stringToJSON) {
// String which contains first added sample
std::string first_sample = ", [ \"1234\", \"" +
- isc::util::ptimeToText(d.getString().second) + "\" ] ]";
+ isc::util::clockToText(d.getString().second) + "\" ] ]";
d.setValue("Lorem ipsum dolor sit amet");
std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \"" +
- isc::util::ptimeToText(d.getString().second) + "\" ]" + first_sample;
+ isc::util::clockToText(d.getString().second) + "\" ]" + first_sample;
std::cout << d.getJSON()->str() << std::endl;
EXPECT_EQ(exp, d.getJSON()->str());
TEST_F(ObservationTest, reset) {
EXPECT_NO_THROW(a.addValue(static_cast<int64_t>(5678)));
EXPECT_NO_THROW(b.addValue(56.78));
- EXPECT_NO_THROW(c.addValue(millisec::time_duration(5, 6, 7, 8)));
+ EXPECT_NO_THROW(c.addValue(dur5678));
EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
a.reset(); // integer
EXPECT_EQ(0, a.getInteger().first);
EXPECT_EQ(0.0, b.getFloat().first);
- EXPECT_EQ(time_duration(0, 0, 0, 0), c.getDuration().first);
+ EXPECT_EQ(StatsDuration::zero(), c.getDuration().first);
EXPECT_EQ("", d.getString().first);
ASSERT_EQ(a.getSize(), 1);
#include <exceptions/exceptions.h>
#include <cc/data.h>
#include <cc/command_interpreter.h>
-#include <util/boost_time_utils.h>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <util/chrono_time_utils.h>
#include <boost/shared_ptr.hpp>
#include <gtest/gtest.h>
using namespace isc::data;
using namespace isc::stats;
using namespace isc::config;
-using namespace boost::posix_time;
+using namespace std::chrono;
namespace {
+const StatsDuration& dur1234(hours(1) + minutes(2) + seconds(3) +
+ milliseconds(4));
+const StatsDuration& dur5678(hours(5) + minutes(6) + seconds(7) +
+ milliseconds(8));
+const StatsDuration& dur1245(hours(1) + minutes(2) + seconds(45));
+
/// @brief Fixture class for StatsMgr testing
///
/// Very simple class that makes sure that StatsMgr is indeed instantiated
ASSERT_TRUE(alpha);
std::string exp = "{ \"alpha\": [ [ 1234, \"" +
- isc::util::ptimeToText(alpha->getInteger().second) + "\" ] ] }";
+ isc::util::clockToText(alpha->getInteger().second) + "\" ] ] }";
EXPECT_EQ(exp, StatsMgr::instance().get("alpha")->str());
}
ASSERT_TRUE(beta);
std::string exp = "{ \"beta\": [ [ 12.34, \"" +
- isc::util::ptimeToText(beta->getFloat().second) + "\" ] ] }";
+ isc::util::clockToText(beta->getFloat().second) + "\" ] ] }";
EXPECT_EQ(exp, StatsMgr::instance().get("beta")->str());
}
// Test checks whether it's possible to record and later report
// a duration statistic.
TEST_F(StatsMgrTest, durationStat) {
- EXPECT_NO_THROW(StatsMgr::instance().setValue("gamma",
- microsec::time_duration(1, 2, 3, 4)));
+ EXPECT_NO_THROW(StatsMgr::instance().setValue("gamma", dur1234));
ObservationPtr gamma;
EXPECT_NO_THROW(gamma = StatsMgr::instance().getObservation("gamma"));
ASSERT_TRUE(gamma);
- std::string exp = "{ \"gamma\": [ [ \"01:02:03.000004\", \"" +
- isc::util::ptimeToText(gamma->getDuration().second) + "\" ] ] }";
+ std::string exp = "{ \"gamma\": [ [ \"01:02:03.004000\", \"" +
+ isc::util::clockToText(gamma->getDuration().second) + "\" ] ] }";
EXPECT_EQ(exp, StatsMgr::instance().get("gamma")->str());
}
ASSERT_TRUE(delta);
std::string exp = "{ \"delta\": [ [ \"Lorem ipsum\", \"" +
- isc::util::ptimeToText(delta->getString().second) + "\" ] ] }";
+ isc::util::clockToText(delta->getString().second) + "\" ] ] }";
EXPECT_EQ(exp, StatsMgr::instance().get("delta")->str());
}
TEST_F(StatsMgrTest, getSize) {
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", microsec::time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
EXPECT_NO_THROW(StatsMgr::instance().getSize("alpha"));
StatsMgr::instance().setValue("foo", static_cast<int64_t>(1));
EXPECT_NO_THROW(StatsMgr::instance().setMaxSampleAge("foo",
- time_duration(0, 0, 1, 0)));
+ seconds(1)));
for (uint32_t i = 0; i < 10; ++i) {
if (i == 5) {
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// check the setting of time limit to existing statistics
- EXPECT_NO_THROW(StatsMgr::instance().setMaxSampleAgeAll(time_duration(0, 0, 1, 0)));
+ EXPECT_NO_THROW(StatsMgr::instance().setMaxSampleAgeAll(seconds(1)));
// check if time limit was set properly and whether count limit is disabled
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleAge().second,
- time_duration(0, 0, 1, 0));
+ seconds(1));
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleCount().first, false);
EXPECT_EQ(StatsMgr::instance().getObservation("beta")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("beta")->getMaxSampleAge().second,
- time_duration(0, 0, 1, 0));
+ seconds(1));
EXPECT_EQ(StatsMgr::instance().getObservation("beta")->getMaxSampleCount().first, false);
EXPECT_EQ(StatsMgr::instance().getObservation("gamma")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("gamma")->getMaxSampleAge().second,
- time_duration(0, 0, 1, 0));
+ seconds(1));
EXPECT_EQ(StatsMgr::instance().getObservation("gamma")->getMaxSampleCount().first, false);
EXPECT_EQ(StatsMgr::instance().getObservation("delta")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("delta")->getMaxSampleAge().second,
- time_duration(0, 0, 1, 0));
+ seconds(1));
EXPECT_EQ(StatsMgr::instance().getObservation("delta")->getMaxSampleCount().first, false);
// check the setting of count limit to existing statistics
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem");
// The string's representation of firstly added statistics
std::string alpha_first = ", [ 1234, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha")
+ isc::util::clockToText(StatsMgr::instance().getObservation("alpha")
->getInteger().second) + "\" ] ]";
std::string beta_first = ", [ 12.34, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("beta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("beta")
->getFloat().second) + "\" ] ]";
- std::string gamma_first = ", [ \"01:02:03.000004\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma")
+ std::string gamma_first = ", [ \"01:02:03.004000\", \"" +
+ isc::util::clockToText(StatsMgr::instance().getObservation("gamma")
->getDuration().second) + "\" ] ]";
std::string delta_first = ", [ \"Lorem\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("delta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("delta")
->getString().second) + "\" ] ]";
// Now add some values to them
StatsMgr::instance().addValue("alpha", static_cast<int64_t>(5678));
StatsMgr::instance().addValue("beta", 56.78);
- StatsMgr::instance().addValue("gamma", time_duration(5, 6, 7, 8));
+ StatsMgr::instance().addValue("gamma", dur5678);
StatsMgr::instance().addValue("delta", " ipsum");
// There should be 4 statistics reported
ASSERT_TRUE(rep_delta);
std::string exp_str_alpha = "[ [ 6912, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha")
+ isc::util::clockToText(StatsMgr::instance().getObservation("alpha")
->getInteger().second) + "\" ]" + alpha_first;
std::string exp_str_beta = "[ [ 69.12, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("beta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("beta")
->getFloat().second) + "\" ]" + beta_first;
- std::string exp_str_gamma = "[ [ \"06:08:10.000012\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma")
+ std::string exp_str_gamma = "[ [ \"06:08:10.012000\", \"" +
+ isc::util::clockToText(StatsMgr::instance().getObservation("gamma")
->getDuration().second) + "\" ]" + gamma_first;
std::string exp_str_delta = "[ [ \"Lorem ipsum\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("delta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("delta")
->getString().second) + "\" ]" + delta_first;
// Check that individual stats are reported properly
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// This should reset alpha to 0
// The other stats should remain untouched
EXPECT_EQ(12.34,
StatsMgr::instance().getObservation("beta")->getFloat().first);
- EXPECT_EQ(time_duration(1, 2, 3, 4),
+ EXPECT_EQ(dur1234,
StatsMgr::instance().getObservation("gamma")->getDuration().first);
EXPECT_EQ("Lorem ipsum",
StatsMgr::instance().getObservation("delta")->getString().first);
EXPECT_NO_THROW(StatsMgr::instance().reset("delta"));
EXPECT_EQ(0.0,
StatsMgr::instance().getObservation("beta")->getFloat().first);
- EXPECT_EQ(time_duration(0, 0, 0, 0),
+ EXPECT_EQ(StatsDuration::zero(),
StatsMgr::instance().getObservation("gamma")->getDuration().first);
EXPECT_EQ("",
StatsMgr::instance().getObservation("delta")->getString().first);
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// This should reset alpha to 0
StatsMgr::instance().getObservation("alpha")->getInteger().first);
EXPECT_EQ(0.0,
StatsMgr::instance().getObservation("beta")->getFloat().first);
- EXPECT_EQ(time_duration(0, 0, 0, 0),
+ EXPECT_EQ(StatsDuration::zero(),
StatsMgr::instance().getObservation("gamma")->getDuration().first);
EXPECT_EQ("",
StatsMgr::instance().getObservation("delta")->getString().first);
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// This should reset alpha to 0
uint32_t cycles = 1000000;
- ptime before = microsec_clock::local_time();
+ auto before = SampleClock::now();
for (uint32_t i = 0; i < cycles; ++i) {
StatsMgr::instance().addValue("metric1", 0.1 * i);
}
- ptime after = microsec_clock::local_time();
+ auto after = SampleClock::now();
- time_duration dur = after - before;
+ auto dur = after - before;
std::cout << "Incrementing a single statistic " << cycles << " times took: "
<< isc::util::durationToText(dur) << std::endl;
uint32_t cycles = 1000000;
- ptime before = microsec_clock::local_time();
+ auto before = SampleClock::now();
for (uint32_t i = 0; i < cycles; ++i) {
StatsMgr::instance().setValue("metric1", 0.1 * i);
}
- ptime after = microsec_clock::local_time();
+ auto after = SampleClock::now();
- time_duration dur = after - before;
+ auto dur = after - before;
std::cout << "Setting a single statistic " << cycles << " times took: "
<< isc::util::durationToText(dur) << std::endl;
StatsMgr::instance().setValue(tmp.str(), static_cast<int64_t>(i));
}
- ptime before = microsec_clock::local_time();
+ auto before = SampleClock::now();
for (uint32_t i = 0; i < cycles; ++i) {
StatsMgr::instance().addValue("metric1", static_cast<int64_t>(i));
}
- ptime after = microsec_clock::local_time();
+ auto after = SampleClock::now();
- time_duration dur = after - before;
+ auto dur = after - before;
std::cout << "Incrementing one of " << stats << " statistics " << cycles
<< " times took: " << isc::util::durationToText(dur) << std::endl;
StatsMgr::instance().setValue(tmp.str(), static_cast<int64_t>(i));
}
- ptime before = microsec_clock::local_time();
+ auto before = SampleClock::now();
for (uint32_t i = 0; i < cycles; ++i) {
StatsMgr::instance().setValue("metric1", static_cast<int64_t>(i));
}
- ptime after = microsec_clock::local_time();
+ auto after = SampleClock::now();
- time_duration dur = after - before;
+ auto dur = after - before;
std::cout << "Setting one of " << stats << " statistics " << cycles
<< " times took: " << isc::util::durationToText(dur) << std::endl;
ASSERT_TRUE(alpha);
std::string exp = "{ \"alpha\": [ [ 1234, \"" +
- isc::util::ptimeToText(alpha->getInteger().second) + "\" ] ] }";
+ isc::util::clockToText(alpha->getInteger().second) + "\" ] ] }";
EXPECT_EQ("{ \"arguments\": " + exp + ", \"result\": 0 }", rsp->str());
}
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// Now get them. They're used to generate expected output
ASSERT_TRUE(rep_delta);
std::string exp_str_alpha = "[ [ 1234, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha")
+ isc::util::clockToText(StatsMgr::instance().getObservation("alpha")
->getInteger().second) + "\" ] ]";
std::string exp_str_beta = "[ [ 12.34, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("beta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("beta")
->getFloat().second) + "\" ] ]";
- std::string exp_str_gamma = "[ [ \"01:02:03.000004\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma")
+ std::string exp_str_gamma = "[ [ \"01:02:03.004000\", \"" +
+ isc::util::clockToText(StatsMgr::instance().getObservation("gamma")
->getDuration().second) + "\" ] ]";
std::string exp_str_delta = "[ [ \"Lorem ipsum\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("delta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("delta")
->getString().second) + "\" ] ]";
// Check that all of them can be reported at once
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// Now get them. They're used to generate expected output
ASSERT_TRUE(rep_delta);
std::string exp_str_alpha = "[ [ 1234, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha")
+ isc::util::clockToText(StatsMgr::instance().getObservation("alpha")
->getInteger().second) + "\" ] ]";
std::string exp_str_beta = "[ [ 12.34, \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("beta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("beta")
->getFloat().second) + "\" ] ]";
- std::string exp_str_gamma = "[ [ \"01:02:03.000004\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma")
+ std::string exp_str_gamma = "[ [ \"01:02:03.004000\", \"" +
+ isc::util::clockToText(StatsMgr::instance().getObservation("gamma")
->getDuration().second) + "\" ] ]";
std::string exp_str_delta = "[ [ \"Lorem ipsum\", \"" +
- isc::util::ptimeToText(StatsMgr::instance().getObservation("delta")
+ isc::util::clockToText(StatsMgr::instance().getObservation("delta")
->getString().second) + "\" ] ]";
// Check that all of them can be reset at once
StatsMgr::instance().getObservation("alpha")->getInteger().first);
EXPECT_EQ(0.0f,
StatsMgr::instance().getObservation("beta")->getFloat().first);
- EXPECT_EQ(time_duration(0, 0, 0, 0),
+ EXPECT_EQ(StatsDuration::zero(),
StatsMgr::instance().getObservation("gamma")->getDuration().first);
EXPECT_EQ("",
StatsMgr::instance().getObservation("delta")->getString().first);
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
// Check that all of them can be reset at once
ElementPtr params = Element::createMap();
params->set("name", Element::create("alpha"));
- params->set("duration", Element::create(1245)); // time_duration(0, 20, 45, 0)
+ params->set("duration", Element::create(1245)); // minutes(20) + seconds(45)
ConstElementPtr rsp =
StatsMgr::instance().statisticSetMaxSampleAgeHandler("statistic-sample-age-set", params);
// check if time limit was set properly and whether count limit is disabled
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleAge().second,
- time_duration(0, 20, 45, 0));
+ minutes(20) + seconds(45));
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleCount().first, false);
}
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
ElementPtr params = Element::createMap();
- params->set("duration", Element::create(3765)); // time_duration(1, 2, 45, 0)
+ params->set("duration", Element::create(3765)); // dur1245
ConstElementPtr rsp =
StatsMgr::instance().statisticSetMaxSampleAgeAllHandler(params);
// check if time limit was set properly and whether count limit is disabled
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleAge().second,
- time_duration(1, 2, 45, 0));
+ dur1245);
EXPECT_EQ(StatsMgr::instance().getObservation("alpha")->getMaxSampleCount().first, false);
EXPECT_EQ(StatsMgr::instance().getObservation("beta")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("beta")->getMaxSampleAge().second,
- time_duration(1, 2, 45, 0));
+ dur1245);
EXPECT_EQ(StatsMgr::instance().getObservation("beta")->getMaxSampleCount().first, false);
EXPECT_EQ(StatsMgr::instance().getObservation("gamma")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("gamma")->getMaxSampleAge().second,
- time_duration(1, 2, 45, 0));
+ dur1245);
EXPECT_EQ(StatsMgr::instance().getObservation("gamma")->getMaxSampleCount().first, false);
EXPECT_EQ(StatsMgr::instance().getObservation("delta")->getMaxSampleAge().first, true);
EXPECT_EQ(StatsMgr::instance().getObservation("delta")->getMaxSampleAge().second,
- time_duration(1, 2, 45, 0));
+ dur1245);
EXPECT_EQ(StatsMgr::instance().getObservation("delta")->getMaxSampleCount().first, false);
}
// Set a couple of statistics
StatsMgr::instance().setValue("alpha", static_cast<int64_t>(1234));
StatsMgr::instance().setValue("beta", 12.34);
- StatsMgr::instance().setValue("gamma", time_duration(1, 2, 3, 4));
+ StatsMgr::instance().setValue("gamma", dur1234);
StatsMgr::instance().setValue("delta", "Lorem ipsum");
ElementPtr params = Element::createMap();
lib_LTLIBRARIES = libkea-util.la
libkea_util_la_SOURCES = boost_time_utils.h boost_time_utils.cc
libkea_util_la_SOURCES += buffer.h io_utilities.h
+libkea_util_la_SOURCES += chrono_time_utils.h chrono_time_utils.cc
libkea_util_la_SOURCES += csv_file.h csv_file.cc
libkea_util_la_SOURCES += doubles.h
libkea_util_la_SOURCES += filename.h filename.cc
--- /dev/null
+// Copyright (C) 2015-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/chrono_time_utils.h>
+#include <sstream>
+#include <iomanip>
+
+using namespace std::chrono;
+
+std::string
+isc::util::clockToText(system_clock::time_point t, size_t fsecs_precision) {
+ time_t tt = system_clock::to_time_t(t);
+ struct tm tm;
+ localtime_r(&tt, &tm);
+ std::stringstream s;
+ s << (tm.tm_year + 1900)
+ << "-" << std::setw(2) << std::setfill('0') << (tm.tm_mon + 1)
+ << "-" << std::setw(2) << std::setfill('0') << tm.tm_mday
+ << " " << std::setw(2) << std::setfill('0') << tm.tm_hour
+ << ":" << std::setw(2) << std::setfill('0') << tm.tm_min
+ << ":" << std::setw(2) << std::setfill('0') << tm.tm_sec;
+
+ // If the requested precision is less than the maximum native precision
+ // we will divide the fractional seconds value by 10^(max - requested)
+ if (fsecs_precision) {
+ microseconds frac = t - system_clock::from_time_t(tt);
+ auto fsecs = frac.count();
+ size_t width = MAX_FSECS_PRECISION;
+ if (fsecs_precision < width) {
+ for (auto i = 0; i < width - fsecs_precision; ++i) {
+ fsecs /= 10;
+ }
+
+ width = fsecs_precision;
+ }
+
+ s << "." << std::setw(width)
+ << std::setfill('0')
+ << fsecs;
+ }
+
+ return (s.str());
+}
+
+std::string
+isc::util::durationToText(system_clock::duration dur, size_t fsecs_precision) {
+ seconds unfrac = duration_cast<seconds>(dur);
+ auto secs = unfrac.count();
+ std::stringstream s;
+ auto hours = secs / 3600;
+ secs -= hours * 3600;
+ s << std::setw(2) << std::setfill('0') << hours;
+ auto mins = secs / 60;
+ secs -= mins * 60;
+ s << ":" << std::setw(2) << std::setfill('0') << mins
+ << ":" << std::setw(2) << std::setfill('0') << secs;
+
+ // If the requested precision is less than the maximum native precision
+ // we will divide the fractional seconds value by 10^(max - requested)
+ if (fsecs_precision) {
+ microseconds frac = dur - unfrac;
+ auto fsecs = frac.count();
+ size_t width = MAX_FSECS_PRECISION;
+ if (fsecs_precision < width) {
+ for (auto i = 0; i < width - fsecs_precision; ++i) {
+ fsecs /= 10;
+ }
+
+ width = fsecs_precision;
+ }
+
+ s << "." << std::setw(width)
+ << std::setfill('0')
+ << fsecs;
+ }
+
+ return (s.str());
+}
--- /dev/null
+// Copyright (C) 2015-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef KEA_CHRONO_TIME_UTILS_H
+#define KEA_CHRONO_TIME_UTILS_H
+
+#include <chrono>
+#include <string>
+
+namespace isc {
+namespace util {
+
+/// @brief The number of digits of fractional seconds supplied by the
+/// underlying class, std::chrono::time_point. Typically 6 = microseconds.
+const size_t MAX_FSECS_PRECISION = 6;
+
+/// @brief Converts chrono time point structure to text
+///
+/// This is Kea implementation for converting time point to strings.
+/// @param t time point value to convert to text
+/// @param fsecs_precision number of digits of precision for fractional seconds.
+/// Zero omits the value.
+///
+/// @return a string representing time
+std::string clockToText(std::chrono::system_clock::time_point t,
+ size_t fsecs_precision = MAX_FSECS_PRECISION);
+
+/// @brief Converts StatsDuration to text
+///
+/// See @ref clockToText for explanation why we chose our own implementation.
+/// @param dur duration value to convert to text
+/// @param fsecs_precision number of digits of precision for fractional seconds.
+/// Zero omits the value.
+///
+/// @return a string representing time
+std::string durationToText(std::chrono::system_clock::duration,
+ size_t fsecs_precision = MAX_FSECS_PRECISION);
+
+}; // end of isc::util namespace
+}; // end of isc namespace
+
+#endif
run_unittests_SOURCES += base64_unittest.cc
run_unittests_SOURCES += boost_time_utils_unittest.cc
run_unittests_SOURCES += buffer_unittest.cc
+run_unittests_SOURCES += chrono_time_utils_unittest.cc
run_unittests_SOURCES += csv_file_unittest.cc
run_unittests_SOURCES += doubles_unittest.cc
run_unittests_SOURCES += fd_share_tests.cc
--- /dev/null
+// Copyright (C) 2015-2020 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <config.h>
+
+#include <util/chrono_time_utils.h>
+
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace std::chrono;
+using namespace isc::util;
+
+/// Check the clockToText() function returns a numeric month.
+TEST(ChronoTimeUtilsTest, epoch) {
+ // The system clock is a wall clock using the local time zone so
+ // the epoch is zero only at some places or of course if the
+ // system is in UTC...
+ struct tm epoch;
+ memset(&epoch, 0, sizeof(epoch));
+ epoch.tm_year = 70;
+ epoch.tm_mday = 1;
+ time_t tepoch = timelocal(&epoch);
+ system_clock::time_point pepoch = system_clock::from_time_t(tepoch);
+
+ // We're going to loop through precision values starting with 0 through
+ // the max supported precision. Each pass should after the first, should
+ // add an additional level of precision: secs, secs/10, secs/100,
+ // secs/1000 and so on. The initial string has no fraction seconds.
+ std::string expected("1970-01-01 00:00:00");
+ std::string sepoch;
+ for (int precision = 0; precision <= MAX_FSECS_PRECISION; ++precision) {
+ if (precision == 1) {
+ // Adding fractional seconds so we need append a decimal point.
+ expected.push_back('.');
+ }
+
+ if (precision >= 1) {
+ // Adding an additional level of precision, append a zero.
+ expected.push_back('0');
+ }
+
+ // Now let's see if we get the correct precision in the text.
+ sepoch = clockToText(pepoch, precision);
+ EXPECT_EQ(expected, sepoch) << " test precision:" << precision;
+ }
+
+ // Expected string should have same precision as default, so
+ // test the default.
+ sepoch = clockToText(pepoch);
+ EXPECT_EQ(expected, sepoch);
+
+ // Now test a requested precision beyond default. We should
+ // get the default precision.
+ sepoch = clockToText(pepoch, MAX_FSECS_PRECISION + 1);
+ EXPECT_EQ(expected, sepoch);
+
+}
+
+/// Check the durationToText() works as expected.
+/// Note durationToText() is not called by clockToText().
+TEST(ChronoTimeUtilsTest, duration) {
+ system_clock::duration p123 = hours(1) + minutes(2) + seconds(3);
+
+ // We're going to loop through precision values starting with 0 through
+ // the max supported precision. Each pass should after the first, should
+ // add an additional level of precision: secs, secs/10, secs/100,
+ // secs/1000 and so on. The initial string has no fraction seconds.
+ std::string expected("01:02:03");
+ std::string s123;
+ for (int precision = 0; precision <= MAX_FSECS_PRECISION; ++precision) {
+ if (precision == 1) {
+ // Adding fractional seconds so we need append a decimal point.
+ expected.push_back('.');
+ }
+
+ if (precision >= 1) {
+ // Adding an additional level of precision, append a zero.
+ expected.push_back('0');
+ }
+
+ // Now let's see if we get the correct precision in the text.
+ s123 = durationToText(p123, precision);
+ EXPECT_EQ(expected, s123) << " test precision:" << precision;
+ }
+
+ // Expected string should have same precision as default, so
+ // test the default.
+ s123 = durationToText(p123);
+ EXPECT_EQ(expected, s123);
+
+ // Now test a requested precision beyond default. We should
+ // get the default precision.
+ s123 = durationToText(p123, MAX_FSECS_PRECISION + 1);
+ EXPECT_EQ(expected, s123);
+}
+
+// The 2015 Bastille day
+TEST(ChronoTimeUtilsTest, bastilleDay) {
+ struct tm tm;
+ tm.tm_year = 2015 - 1900;
+ tm.tm_mon = 7 - 1;
+ tm.tm_mday = 14;
+ tm.tm_hour = 12;
+ tm.tm_min = 13;
+ tm.tm_sec = 14;
+ time_t tbast = timelocal(&tm);
+ system_clock::time_point tpbast = system_clock::from_time_t(tbast);
+ tpbast += milliseconds(500);
+
+ // We're going to loop through precision values starting with 0 through
+ // the max supported precision. Each pass should after the first, should
+ // add an additional level of precision: secs, secs/10, secs/100,
+ // secs/1000 and so on. The initial string has no fraction seconds.
+ std::string expected("2015-07-14 12:13:14");
+ std::string sbast;
+ for (int precision = 0; precision <= MAX_FSECS_PRECISION; ++precision) {
+ if (precision == 1) {
+ // Adding fractional seconds so we need append a decimal point
+ // and the digit 5 (i.e. 500 ms = .5 secs).
+ expected.push_back('.');
+ expected.push_back('5');
+ } else if (precision > 1) {
+ // Adding an additional level of precision, append a zero.
+ expected.push_back('0');
+ }
+
+ // Now let's see if we get the correct precision in the text.
+ sbast = clockToText(tpbast, precision);
+ EXPECT_EQ(expected, sbast) << " test precision:" << precision;
+ }
+
+ // Expected string should have same precision as default, so
+ // test the default.
+ sbast = clockToText(tpbast);
+ EXPECT_EQ(expected, sbast);
+
+ // Now test a requested precision beyond default. We should
+ // get the default precision.
+ sbast = clockToText(tpbast, MAX_FSECS_PRECISION + 1);
+ EXPECT_EQ(expected, sbast);
+}