blob: af591eef984a06d49ec68b4a448668a5166e6463 [file] [log] [blame]
Austin Schuh044e18b2015-10-21 20:17:09 -07001#ifndef AOS_COMMON_LOGGING_LOGGING_INTERFACE_H_
2#define AOS_COMMON_LOGGING_LOGGING_INTERFACE_H_
3
4#include <stdarg.h>
5
6#include <string>
7#include <functional>
8
9#include "aos/common/logging/logging.h"
10
11namespace aos {
12
13struct MessageType;
14
15} // namespace aos
16
17namespace aos {
18namespace logging {
19
20// Represents a system that can actually take log messages and do something
21// useful with them.
22// All of the code (transitively too!) in the DoLog here can make
23// normal LOG and LOG_DYNAMIC calls but can NOT call LOG_CORK/LOG_UNCORK. These
24// calls will not result in DoLog recursing. However, implementations must be
25// safe to call from multiple threads/tasks at the same time. Also, any other
26// overriden methods may end up logging through a given implementation's DoLog.
27class LogImplementation {
28 public:
29 LogImplementation() : next_(NULL) {}
30
31 // The one that this one's implementation logs to.
32 // NULL means that there is no next one.
33 LogImplementation *next() { return next_; }
34 // Virtual in case a subclass wants to perform checks. There will be a valid
35 // logger other than this one available while this is called.
36 virtual void set_next(LogImplementation *next) { next_ = next; }
37
38 private:
39 // Actually logs the given message. Implementations should somehow create a
40 // LogMessage and then call internal::FillInMessage.
41 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
42 virtual void DoLog(log_level level, const char *format, va_list ap) = 0;
43 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 4)))
44 void DoLogVariadic(log_level level, const char *format, ...) {
45 va_list ap;
46 va_start(ap, format);
47 DoLog(level, format, ap);
48 va_end(ap);
49 }
50
51 // Logs the contents of an auto-generated structure. The implementation here
52 // just converts it to a string with PrintMessage and then calls DoLog with
53 // that, however some implementations can be a lot more efficient than that.
54 // size and type are the result of calling Size() and Type() on the type of
55 // the message.
56 // serialize will call Serialize on the message.
57 virtual void LogStruct(log_level level, const ::std::string &message,
58 size_t size, const MessageType *type,
59 const ::std::function<size_t(char *)> &serialize);
60 // Similiar to LogStruct, except for matrixes.
61 // type_id is the type of the elements of the matrix.
62 // data points to rows*cols*type_id.Size() bytes of data in row-major order.
63 virtual void LogMatrix(log_level level, const ::std::string &message,
64 uint32_t type_id, int rows, int cols,
65 const void *data);
66
67 // These functions call similar methods on the "current" LogImplementation or
68 // Die if they can't find one.
69 // levels is how many LogImplementations to not use off the stack.
70 static void DoVLog(log_level, const char *format, va_list ap, int levels)
71 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 2, 0)));
72 // This one is implemented in queue_logging.cc.
73 static void DoLogStruct(log_level level, const ::std::string &message,
74 size_t size, const MessageType *type,
75 const ::std::function<size_t(char *)> &serialize,
76 int levels);
77 // This one is implemented in matrix_logging.cc.
78 static void DoLogMatrix(log_level level, const ::std::string &message,
79 uint32_t type_id, int rows, int cols,
80 const void *data, int levels);
81
82 // Friends so that they can access the static Do* functions.
83 friend void VLog(log_level, const char *, va_list);
84 friend void LogNext(log_level, const char *, ...);
85 template <class T>
86 friend void DoLogStruct(log_level, const ::std::string &, const T &);
87 template <class T>
88 friend void DoLogMatrix(log_level, const ::std::string &, const T &);
89
90 LogImplementation *next_;
91};
92
93} // namespace logging
94} // namespace aos
95
96#endif // AOS_COMMON_LOGGING_LOGGING_INTERFACE_H_