blob: 50237fc4d5001774840e36b4afbffdc09f4a0400 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_LOGGING_INTERFACE_H_
2#define AOS_LOGGING_INTERFACE_H_
Austin Schuh044e18b2015-10-21 20:17:09 -07003
4#include <stdarg.h>
5
6#include <string>
7#include <functional>
8
John Park33858a32018-09-28 23:05:48 -07009#include "aos/logging/logging.h"
10#include "aos/macros.h"
Austin Schuh044e18b2015-10-21 20:17:09 -070011
Brian Silvermancb5da1f2015-12-05 22:19:58 -050012// This file has the non-C-compatible parts of the logging client interface.
13
Austin Schuh044e18b2015-10-21 20:17:09 -070014namespace aos {
15
16struct MessageType;
17
Austin Schuh044e18b2015-10-21 20:17:09 -070018namespace logging {
Brian Silvermancb5da1f2015-12-05 22:19:58 -050019namespace internal {
20
21// Defined in queue_logging.cc.
22void DoLogStruct(log_level level, const ::std::string &message, size_t size,
23 const MessageType *type,
24 const ::std::function<size_t(char *)> &serialize, int levels);
25
26// Defined in matrix_logging.cc.
27void DoLogMatrix(log_level level, const ::std::string &message,
28 uint32_t type_id, int rows, int cols, const void *data,
29 int levels);
30
31} // namespace internal
Austin Schuh044e18b2015-10-21 20:17:09 -070032
Brian Silverman17291d82015-10-24 22:30:57 -040033// Takes a message and logs it. It will set everything up and then call DoLog
34// for the current LogImplementation.
35void VLog(log_level level, const char *format, va_list ap)
36 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
37// Adds to the saved up message.
38void VCork(int line, const char *function, const char *format, va_list ap)
39 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
40// Actually logs the saved up message.
41void VUnCork(int line, const char *function, log_level level, const char *file,
42 const char *format, va_list ap)
43 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 0)));
44
Austin Schuh044e18b2015-10-21 20:17:09 -070045// Represents a system that can actually take log messages and do something
46// useful with them.
47// All of the code (transitively too!) in the DoLog here can make
48// normal LOG and LOG_DYNAMIC calls but can NOT call LOG_CORK/LOG_UNCORK. These
49// calls will not result in DoLog recursing. However, implementations must be
50// safe to call from multiple threads/tasks at the same time. Also, any other
51// overriden methods may end up logging through a given implementation's DoLog.
52class LogImplementation {
53 public:
54 LogImplementation() : next_(NULL) {}
55
56 // The one that this one's implementation logs to.
57 // NULL means that there is no next one.
58 LogImplementation *next() { return next_; }
59 // Virtual in case a subclass wants to perform checks. There will be a valid
60 // logger other than this one available while this is called.
61 virtual void set_next(LogImplementation *next) { next_ = next; }
62
Austin Schuh1bf8a212019-05-26 22:13:14 -070063 virtual bool fill_type_cache() { return true; }
64
Brian Silvermancb5da1f2015-12-05 22:19:58 -050065 protected:
Austin Schuh044e18b2015-10-21 20:17:09 -070066 // Actually logs the given message. Implementations should somehow create a
67 // LogMessage and then call internal::FillInMessage.
68 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
69 virtual void DoLog(log_level level, const char *format, va_list ap) = 0;
70 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)))
71 void DoLogVariadic(log_level level, const char *format, ...) {
72 va_list ap;
73 va_start(ap, format);
74 DoLog(level, format, ap);
75 va_end(ap);
76 }
77
Brian Silvermancb5da1f2015-12-05 22:19:58 -050078 // Logs the contents of an auto-generated structure.
Austin Schuh044e18b2015-10-21 20:17:09 -070079 // size and type are the result of calling Size() and Type() on the type of
80 // the message.
81 // serialize will call Serialize on the message.
82 virtual void LogStruct(log_level level, const ::std::string &message,
83 size_t size, const MessageType *type,
Brian Silvermancb5da1f2015-12-05 22:19:58 -050084 const ::std::function<size_t(char *)> &serialize) = 0;
Austin Schuh044e18b2015-10-21 20:17:09 -070085 // Similiar to LogStruct, except for matrixes.
86 // type_id is the type of the elements of the matrix.
87 // data points to rows*cols*type_id.Size() bytes of data in row-major order.
88 virtual void LogMatrix(log_level level, const ::std::string &message,
89 uint32_t type_id, int rows, int cols,
Brian Silvermancb5da1f2015-12-05 22:19:58 -050090 const void *data) = 0;
Austin Schuh044e18b2015-10-21 20:17:09 -070091
Brian Silvermancb5da1f2015-12-05 22:19:58 -050092 private:
Austin Schuh044e18b2015-10-21 20:17:09 -070093 // These functions call similar methods on the "current" LogImplementation or
94 // Die if they can't find one.
95 // levels is how many LogImplementations to not use off the stack.
96 static void DoVLog(log_level, const char *format, va_list ap, int levels)
97 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
Austin Schuh044e18b2015-10-21 20:17:09 -070098
Austin Schuh044e18b2015-10-21 20:17:09 -070099 friend void VLog(log_level, const char *, va_list);
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500100 friend void internal::DoLogStruct(
101 log_level level, const ::std::string &message, size_t size,
102 const MessageType *type, const ::std::function<size_t(char *)> &serialize,
103 int levels);
104 friend void internal::DoLogMatrix(log_level level,
105 const ::std::string &message,
106 uint32_t type_id, int rows, int cols,
107 const void *data, int levels);
Austin Schuh044e18b2015-10-21 20:17:09 -0700108
109 LogImplementation *next_;
110};
111
Brian Silverman17291d82015-10-24 22:30:57 -0400112namespace internal {
113
114// Prints format (with ap) into output and correctly deals with the result
115// being too long etc.
116size_t ExecuteFormat(char *output, size_t output_size, const char *format,
117 va_list ap)
118 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
119
120// Runs the given function with the current LogImplementation (handles switching
121// it out while running function etc).
122// levels is how many LogImplementations to not use off the stack.
123void RunWithCurrentImplementation(
124 int levels, ::std::function<void(LogImplementation *)> function);
125
126} // namespace internal
Austin Schuh044e18b2015-10-21 20:17:09 -0700127} // namespace logging
128} // namespace aos
129
John Park33858a32018-09-28 23:05:48 -0700130#endif // AOS_LOGGING_INTERFACE_H_