blob: 54ebd6d4f541e880c4b7537f5404f50e7b834068 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_UTIL_LOG_INTERVAL_H_
2#define AOS_UTIL_LOG_INTERVAL_H_
Brian Silverman01f0d222014-02-16 01:09:11 -08003
John Park33858a32018-09-28 23:05:48 -07004#include "aos/logging/logging.h"
James Kuszmaul651fc3f2019-05-15 21:14:25 -07005#include "aos/time/time.h"
Brian Silverman01f0d222014-02-16 01:09:11 -08006
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 {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080015// static LogInterval interval(::std::chrono::millseconds(200));
Brian Silverman01f0d222014-02-16 01:09:11 -080016//
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:
Austin Schuh61bdc602016-12-04 19:10:10 -080026 constexpr LogInterval(::std::chrono::nanoseconds interval)
27 : interval_(interval) {}
Brian Silverman01f0d222014-02-16 01:09:11 -080028
29 void WantToLog() {
30 if (count_ == 0) {
Austin Schuh9fe68f72019-08-10 19:32:03 -070031 // TODO(austin): event loops!
Austin Schuh61bdc602016-12-04 19:10:10 -080032 last_done_ = ::aos::monotonic_clock::now();
Brian Silverman01f0d222014-02-16 01:09:11 -080033 }
34 ++count_;
35 }
36 bool ShouldLog() {
Austin Schuh61bdc602016-12-04 19:10:10 -080037 const ::aos::monotonic_clock::time_point now =
38 ::aos::monotonic_clock::now();
39 const bool r = now >= interval_ + last_done_ && count_ > 0;
Brian Silverman01f0d222014-02-16 01:09:11 -080040 if (r) {
41 last_done_ = now;
42 }
43 return r;
44 }
45 int Count() {
46 const int r = count_;
47 count_ = 0;
48 return r;
49 }
50
Austin Schuh61bdc602016-12-04 19:10:10 -080051 ::std::chrono::nanoseconds interval() const { return interval_; }
Brian Silverman50a9d032014-02-16 17:20:57 -080052
Brian Silverman01f0d222014-02-16 01:09:11 -080053 private:
Austin Schuh61bdc602016-12-04 19:10:10 -080054 int count_ = 0;
55 const ::std::chrono::nanoseconds interval_;
56 ::aos::monotonic_clock::time_point last_done_ =
57 ::aos::monotonic_clock::min_time;
Brian Silverman01f0d222014-02-16 01:09:11 -080058};
59
60// This one is even easier to use. It always logs with a message "%s %d
Brian Silverman9c9ab422014-02-25 13:42:53 -080061// times\n". Call LOG_INTERVAL wherever it should log and make sure Print gets
62// called often (ie not after a conditional return)
Brian Silverman01f0d222014-02-16 01:09:11 -080063class SimpleLogInterval {
64 public:
Austin Schuh61bdc602016-12-04 19:10:10 -080065 SimpleLogInterval(::std::chrono::nanoseconds interval, log_level level,
Brian Silverman01f0d222014-02-16 01:09:11 -080066 const ::std::string &message)
67 : interval_(interval), level_(level), message_(message) {}
68
Austin Schuhf257f3c2019-10-27 21:00:43 -070069#define AOS_LOG_INTERVAL(simple_log) \
Brian Silverman9c9ab422014-02-25 13:42:53 -080070 simple_log.WantToLog(LOG_SOURCENAME ": " STRINGIFY(__LINE__))
71 void WantToLog(const char *context) {
72 context_ = context;
73 interval_.WantToLog();
74 }
75
76 void Print() {
Brian Silverman01f0d222014-02-16 01:09:11 -080077 if (interval_.ShouldLog()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070078 AOS_CHECK_NOTNULL(context_);
Brian Silverman9c9ab422014-02-25 13:42:53 -080079 log_do(level_, "%s: %.*s %d times over %f sec\n", context_,
Brian Silverman97478342014-02-16 20:26:31 -080080 static_cast<int>(message_.size()), message_.data(),
Austin Schuh61bdc602016-12-04 19:10:10 -080081 interval_.Count(),
James Kuszmaul651fc3f2019-05-15 21:14:25 -070082 ::aos::time::DurationInSeconds(interval_.interval()));
Brian Silverman9c9ab422014-02-25 13:42:53 -080083 context_ = NULL;
Brian Silverman01f0d222014-02-16 01:09:11 -080084 }
85 }
86
87 private:
88 LogInterval interval_;
89 const log_level level_;
90 const ::std::string message_;
Brian Silverman9c9ab422014-02-25 13:42:53 -080091 const char *context_ = NULL;
Brian Silverman01f0d222014-02-16 01:09:11 -080092};
93
94} // namespace util
95} // namespace aos
96
John Park33858a32018-09-28 23:05:48 -070097#endif // AOS_UTIL_LOG_INTERVAL_H_