blob: 08d06bb583852025399051cf5b5f9ee602b9c846 [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
Austin Schuh60e77942022-05-16 17:48:24 -07004#include <string>
5
John Park33858a32018-09-28 23:05:48 -07006#include "aos/logging/logging.h"
James Kuszmaul651fc3f2019-05-15 21:14:25 -07007#include "aos/time/time.h"
Brian Silverman01f0d222014-02-16 01:09:11 -08008
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -08009namespace aos::util {
Brian Silverman01f0d222014-02-16 01:09:11 -080010
11// A class to help with logging things that happen a lot only occasionally.
12//
13// Intended use {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080014// static LogInterval interval(::std::chrono::millseconds(200));
Brian Silverman01f0d222014-02-16 01:09:11 -080015//
16// if (WantToLog()) {
17// interval.WantToLog();
18// }
19// if (interval.ShouldLog()) {
20// LOG(DEBUG, "thingie happened! (%d times)\n", interval.Count());
21// }
22// }
23class LogInterval {
24 public:
Austin Schuh61bdc602016-12-04 19:10:10 -080025 constexpr LogInterval(::std::chrono::nanoseconds interval)
26 : interval_(interval) {}
Brian Silverman01f0d222014-02-16 01:09:11 -080027
28 void WantToLog() {
29 if (count_ == 0) {
Austin Schuh9fe68f72019-08-10 19:32:03 -070030 // TODO(austin): event loops!
Austin Schuh61bdc602016-12-04 19:10:10 -080031 last_done_ = ::aos::monotonic_clock::now();
Brian Silverman01f0d222014-02-16 01:09:11 -080032 }
33 ++count_;
34 }
35 bool ShouldLog() {
Austin Schuh61bdc602016-12-04 19:10:10 -080036 const ::aos::monotonic_clock::time_point now =
37 ::aos::monotonic_clock::now();
38 const bool r = now >= interval_ + last_done_ && count_ > 0;
Brian Silverman01f0d222014-02-16 01:09:11 -080039 if (r) {
40 last_done_ = now;
41 }
42 return r;
43 }
44 int Count() {
45 const int r = count_;
46 count_ = 0;
47 return r;
48 }
49
Austin Schuh61bdc602016-12-04 19:10:10 -080050 ::std::chrono::nanoseconds interval() const { return interval_; }
Brian Silverman50a9d032014-02-16 17:20:57 -080051
Brian Silverman01f0d222014-02-16 01:09:11 -080052 private:
Austin Schuh61bdc602016-12-04 19:10:10 -080053 int count_ = 0;
54 const ::std::chrono::nanoseconds interval_;
55 ::aos::monotonic_clock::time_point last_done_ =
56 ::aos::monotonic_clock::min_time;
Brian Silverman01f0d222014-02-16 01:09:11 -080057};
58
59// This one is even easier to use. It always logs with a message "%s %d
Brian Silverman9c9ab422014-02-25 13:42:53 -080060// times\n". Call LOG_INTERVAL wherever it should log and make sure Print gets
61// called often (ie not after a conditional return)
Brian Silverman01f0d222014-02-16 01:09:11 -080062class SimpleLogInterval {
63 public:
Austin Schuh61bdc602016-12-04 19:10:10 -080064 SimpleLogInterval(::std::chrono::nanoseconds interval, log_level level,
Brian Silverman01f0d222014-02-16 01:09:11 -080065 const ::std::string &message)
66 : interval_(interval), level_(level), message_(message) {}
67
Austin Schuhf257f3c2019-10-27 21:00:43 -070068#define AOS_LOG_INTERVAL(simple_log) \
Austin Schuhc69e6792021-02-05 11:20:05 -080069 simple_log.WantToLog(LOG_SOURCENAME ": " AOS_STRINGIFY(__LINE__))
Brian Silverman9c9ab422014-02-25 13:42:53 -080070 void WantToLog(const char *context) {
71 context_ = context;
72 interval_.WantToLog();
73 }
74
75 void Print() {
Brian Silverman01f0d222014-02-16 01:09:11 -080076 if (interval_.ShouldLog()) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070077 AOS_CHECK_NOTNULL(context_);
Brian Silverman9c9ab422014-02-25 13:42:53 -080078 log_do(level_, "%s: %.*s %d times over %f sec\n", context_,
Brian Silverman97478342014-02-16 20:26:31 -080079 static_cast<int>(message_.size()), message_.data(),
Austin Schuh61bdc602016-12-04 19:10:10 -080080 interval_.Count(),
James Kuszmaul651fc3f2019-05-15 21:14:25 -070081 ::aos::time::DurationInSeconds(interval_.interval()));
Brian Silverman9c9ab422014-02-25 13:42:53 -080082 context_ = NULL;
Brian Silverman01f0d222014-02-16 01:09:11 -080083 }
84 }
85
86 private:
87 LogInterval interval_;
88 const log_level level_;
89 const ::std::string message_;
Brian Silverman9c9ab422014-02-25 13:42:53 -080090 const char *context_ = NULL;
Brian Silverman01f0d222014-02-16 01:09:11 -080091};
92
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080093} // namespace aos::util
Brian Silverman01f0d222014-02-16 01:09:11 -080094
John Park33858a32018-09-28 23:05:48 -070095#endif // AOS_UTIL_LOG_INTERVAL_H_