* "Foo() completed in 4.3 seconds"
*
* You can customize what you use as the logger and clock. The logger needs
- * to have an operator()(StringPiece, double) that gets a message and a duration
- * (in seconds). The clock needs to model Clock from std::chrono.
+ * to have an operator()(StringPiece, std::chrono::duration<double>) that
+ * gets a message and a duration. The clock needs to model Clock from
+ * std::chrono.
*
* The default logger logs usings glog. It only logs if the message is
* non-empty, so you can also just use this class for timing, e.g.:
class Clock = std::chrono::high_resolution_clock>
class AutoTimer final {
public:
+ using DoubleSeconds = std::chrono::duration<double>;
+
explicit AutoTimer(
std::string&& msg = "",
- double minTimetoLog = 0.0,
+ const DoubleSeconds& minTimetoLog = DoubleSeconds::zero(),
Logger&& logger = Logger())
: destructionMessage_(std::move(msg)),
minTimeToLog_(minTimetoLog),
log(destructionMessage_);
}
- double log(StringPiece msg = "") {
+ DoubleSeconds log(StringPiece msg = "") {
return logImpl(Clock::now(), msg);
}
template <typename... Args>
- double log(Args&&... args) {
+ DoubleSeconds log(Args&&... args) {
auto now = Clock::now();
return logImpl(now, to<std::string>(std::forward<Args>(args)...));
}
template <typename... Args>
- double logFormat(Args&&... args) {
+ DoubleSeconds logFormat(Args&&... args) {
auto now = Clock::now();
return logImpl(now, format(std::forward<Args>(args)...).str());
}
private:
// We take in the current time so that we don't measure time to call
// to<std::string> or format() in the duration.
- double logImpl(std::chrono::time_point<Clock> now, StringPiece msg) {
- double duration =
- std::chrono::duration_cast<std::chrono::duration<double>>(now - start_)
- .count();
+ DoubleSeconds logImpl(std::chrono::time_point<Clock> now, StringPiece msg) {
+ auto duration = now - start_;
if (duration >= minTimeToLog_) {
logger_(msg, duration);
}
const std::string destructionMessage_;
std::chrono::time_point<Clock> start_ = Clock::now();
- double minTimeToLog_;
+ DoubleSeconds minTimeToLog_;
Logger logger_;
};
class Clock = std::chrono::high_resolution_clock>
auto makeAutoTimer(
std::string&& msg = "",
- double minTimeToLog = 0.0,
+ const std::chrono::duration<double>& minTimeToLog =
+ std::chrono::duration<double>::zero(),
Logger&& logger = Logger()) {
return AutoTimer<Logger, Clock>(
std::move(msg), minTimeToLog, std::move(logger));
template <GoogleLoggerStyle Style>
struct GoogleLogger final {
- void operator()(StringPiece msg, double sec) const {
+ void operator()(StringPiece msg, const std::chrono::duration<double>& sec)
+ const {
if (msg.empty()) {
return;
}
if (Style == GoogleLoggerStyle::PRETTY) {
- LOG(INFO) << msg << " in " << prettyPrint(sec, PrettyType::PRETTY_TIME);
+ LOG(INFO) << msg << " in "
+ << prettyPrint(sec.count(), PrettyType::PRETTY_TIME);
} else {
- LOG(INFO) << msg << " in " << sec << " seconds";
+ LOG(INFO) << msg << " in " << sec.count() << " seconds";
}
}
};
using namespace std;
struct StubLogger {
- void operator()(StringPiece msg, double sec) {
+ void operator()(StringPiece msg, std::chrono::duration<double> sec) {
m = msg.str();
- t = sec;
+ t = sec.count();
}
static std::string m;
static double t;
int StubClock::t = 0;
TEST(TestAutoTimer, HandleBasicClosure) {
- auto logger = [](StringPiece msg, double sec) {
+ auto logger = [](StringPiece msg, auto sec) {
return StubLogger()(msg, sec);
};
StubClock::t = 1;
// Here decltype is needed. But since most users are expected to use this
// method with the default clock, template specification won't be needed even
// when they use a closure. See test case HandleRealTimerClosure
- auto timer =
- makeAutoTimer<decltype(logger), StubClock>("", 0.0, std::move(logger));
+ auto timer = makeAutoTimer<decltype(logger), StubClock>(
+ "", std::chrono::duration<double>::zero(), std::move(logger));
StubClock::t = 3;
timer.log("foo");
ASSERT_EQ("foo", StubLogger::m);
TEST(TestAutoTimer, HandleRealTimerClosure) {
auto t = makeAutoTimer(
- "Third message on destruction", 0.0, [](StringPiece msg, double sec) {
+ "Third message on destruction",
+ std::chrono::duration<double>::zero(),
+ [](StringPiece msg, auto sec) {
GoogleLogger<GoogleLoggerStyle::PRETTY>()(msg, sec);
});
t.log("First message");
TEST(TestAutoTimer, HandleMinLogTime) {
StubClock::t = 1;
- AutoTimer<StubLogger, StubClock> timer("", 3);
+ AutoTimer<StubLogger, StubClock> timer("", std::chrono::duration<double>(3));
StubClock::t = 3;
// only 2 "seconds" have passed, so this shouldn't log
StubLogger::t = 0;
- ASSERT_EQ(2.0, timer.log("foo"));
- ASSERT_EQ(0, StubLogger::t);
+ ASSERT_EQ(std::chrono::duration<double>(2), timer.log("foo"));
+ ASSERT_EQ(std::chrono::duration<double>::zero().count(), StubLogger::t);
}