blob: 7c8a3296432362fc98df7af484b8b8f4ce054a04 [file] [log] [blame]
Brian Silverman01f0d222014-02-16 01:09:11 -08001#ifndef AOS_COMMON_UTIL_LOG_INTERVAL_H_
2#define AOS_COMMON_UTIL_LOG_INTERVAL_H_
3
4#include "aos/common/time.h"
5#include "aos/common/logging/logging.h"
6
7#include <string>
8
9namespace aos {
10namespace util {
11
12// A class to help with logging things that happen a lot only occasionally.
13//
14// Intended use {
15// static LogInterval interval(::aos::time::Time::InSeconds(0.2));
16//
17// if (WantToLog()) {
18// interval.WantToLog();
19// }
20// if (interval.ShouldLog()) {
21// LOG(DEBUG, "thingie happened! (%d times)\n", interval.Count());
22// }
23// }
24class LogInterval {
25 public:
26 constexpr LogInterval(const ::aos::time::Time &interval)
27 : count_(0), interval_(interval), last_done_(0, 0) {}
28
29 void WantToLog() {
30 if (count_ == 0) {
31 last_done_ = ::aos::time::Time::Now();
32 }
33 ++count_;
34 }
35 bool ShouldLog() {
36 const ::aos::time::Time now = ::aos::time::Time::Now();
Brian Silverman6a1cd212014-02-20 21:04:34 -080037 const bool r = (now - last_done_) >= interval_ && count_ > 0;
Brian Silverman01f0d222014-02-16 01:09:11 -080038 if (r) {
39 last_done_ = now;
40 }
41 return r;
42 }
43 int Count() {
44 const int r = count_;
45 count_ = 0;
46 return r;
47 }
48
Brian Silverman50a9d032014-02-16 17:20:57 -080049 const ::aos::time::Time &interval() const { return interval_; }
50
Brian Silverman01f0d222014-02-16 01:09:11 -080051 private:
52 int count_;
53 const ::aos::time::Time interval_;
54 ::aos::time::Time last_done_;
55};
56
57// This one is even easier to use. It always logs with a message "%s %d
Brian Silverman9c9ab422014-02-25 13:42:53 -080058// times\n". Call LOG_INTERVAL wherever it should log and make sure Print gets
59// called often (ie not after a conditional return)
Brian Silverman01f0d222014-02-16 01:09:11 -080060class SimpleLogInterval {
61 public:
62 SimpleLogInterval(const ::aos::time::Time &interval, log_level level,
63 const ::std::string &message)
64 : interval_(interval), level_(level), message_(message) {}
65
66#define LOG_INTERVAL(simple_log) \
Brian Silverman9c9ab422014-02-25 13:42:53 -080067 simple_log.WantToLog(LOG_SOURCENAME ": " STRINGIFY(__LINE__))
68 void WantToLog(const char *context) {
69 context_ = context;
70 interval_.WantToLog();
71 }
72
73 void Print() {
Brian Silverman01f0d222014-02-16 01:09:11 -080074 if (interval_.ShouldLog()) {
Brian Silverman9c9ab422014-02-25 13:42:53 -080075 CHECK_NOTNULL(context_);
76 log_do(level_, "%s: %.*s %d times over %f sec\n", context_,
Brian Silverman97478342014-02-16 20:26:31 -080077 static_cast<int>(message_.size()), message_.data(),
78 interval_.Count(), interval_.interval().ToSeconds());
Brian Silverman9c9ab422014-02-25 13:42:53 -080079 context_ = NULL;
Brian Silverman01f0d222014-02-16 01:09:11 -080080 }
81 }
82
83 private:
84 LogInterval interval_;
85 const log_level level_;
86 const ::std::string message_;
Brian Silverman9c9ab422014-02-25 13:42:53 -080087 const char *context_ = NULL;
Brian Silverman01f0d222014-02-16 01:09:11 -080088};
89
90} // namespace util
91} // namespace aos
92
93#endif // AOS_COMMON_UTIL_LOG_INTERVAL_H_