blob: de1a8ddc459b4424cb86c4eecdf942cac90b6189 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_LOGGING_IMPLEMENTATIONS_H_
2#define AOS_LOGGING_IMPLEMENTATIONS_H_
Brian Silvermanf665d692013-02-17 22:11:39 -08003
4#include <sys/types.h>
5#include <unistd.h>
Brian Silvermanf665d692013-02-17 22:11:39 -08006
Brian Silverman6da04272014-05-18 18:47:48 -07007#include <atomic>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07008#include <climits>
9#include <cstdarg>
10#include <cstdint>
11#include <cstdio>
12#include <cstring>
Tyler Chatow5febd8f2020-01-05 18:25:31 -080013#include <functional>
Austin Schuha0c41ba2020-09-10 22:59:14 -070014#include <memory>
Tyler Chatow5febd8f2020-01-05 18:25:31 -080015#include <string>
Brian Silvermanf665d692013-02-17 22:11:39 -080016
John Park33858a32018-09-28 23:05:48 -070017#include "aos/logging/context.h"
18#include "aos/logging/interface.h"
19#include "aos/logging/logging.h"
20#include "aos/logging/sizes.h"
21#include "aos/macros.h"
Austin Schuh82c0c822019-05-27 19:55:20 -070022#include "aos/time/time.h"
23#include "aos/type_traits/type_traits.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080024
Brian Silvermancb5da1f2015-12-05 22:19:58 -050025// This file has various concrete LogImplementations.
Brian Silvermanf665d692013-02-17 22:11:39 -080026
27namespace aos {
28namespace logging {
29
30// Unless explicitly stated otherwise, format must always be a string constant,
31// args are printf-style arguments for format, and ap is a va_list of args.
Brian Silverman1a572cc2013-03-05 19:58:01 -080032// The validity of format and args together will be checked at compile time
Brian Silvermancb5da1f2015-12-05 22:19:58 -050033// using a function attribute.
Brian Silvermanf665d692013-02-17 22:11:39 -080034
Brian Silvermancb5da1f2015-12-05 22:19:58 -050035// Contains all of the information about a given logging call.
Brian Silverman88471dc2014-02-15 22:35:42 -080036struct LogMessage {
Brian Silverman88471dc2014-02-15 22:35:42 -080037 int32_t seconds, nseconds;
Brian Silvermanff12c9f2014-03-19 17:53:29 -070038 // message_length is just the length of the actual data (which member depends
39 // on the type).
Brian Silverman88471dc2014-02-15 22:35:42 -080040 size_t message_length, name_length;
Brian Silvermanf665d692013-02-17 22:11:39 -080041 pid_t source;
42 static_assert(sizeof(source) == 4, "that's how they get printed");
43 // Per task/thread.
44 uint16_t sequence;
45 log_level level;
Austin Schuh044e18b2015-10-21 20:17:09 -070046 char name[LOG_MESSAGE_NAME_LEN];
Austin Schuh56196432020-10-24 20:15:21 -070047 char message[LOG_MESSAGE_LEN];
Brian Silvermanf665d692013-02-17 22:11:39 -080048};
49static_assert(shm_ok<LogMessage>::value, "it's going in a queue");
50
51// Returns left > right. LOG_UNKNOWN is most important.
52static inline bool log_gt_important(log_level left, log_level right) {
53 if (left == ERROR) left = 3;
54 if (right == ERROR) right = 3;
55 return left > right;
56}
57
58// Returns a string representing level or "unknown".
59static inline const char *log_str(log_level level) {
Tyler Chatow5febd8f2020-01-05 18:25:31 -080060#define DECL_LEVEL(name, value) \
61 if (level == name) return #name;
Brian Silvermanf665d692013-02-17 22:11:39 -080062 DECL_LEVELS;
63#undef DECL_LEVEL
64 return "unknown";
65}
66// Returns the log level represented by str or LOG_UNKNOWN.
67static inline log_level str_log(const char *str) {
Tyler Chatow5febd8f2020-01-05 18:25:31 -080068#define DECL_LEVEL(name, value) \
69 if (!strcmp(str, #name)) return name;
Brian Silvermanf665d692013-02-17 22:11:39 -080070 DECL_LEVELS;
71#undef DECL_LEVEL
72 return LOG_UNKNOWN;
73}
74
Brian Silvermanbe858a12014-04-30 17:37:28 -070075// Implements all of the DoLog* methods in terms of a (pure virtual in this
76// class) HandleMessage method that takes a pointer to the message.
77class HandleMessageLogImplementation : public LogImplementation {
Austin Schuh82c0c822019-05-27 19:55:20 -070078 protected:
79 virtual ::aos::monotonic_clock::time_point monotonic_now() const {
80 return ::aos::monotonic_clock::now();
81 }
82
Brian Silvermancb5da1f2015-12-05 22:19:58 -050083 private:
Tyler Chatow5febd8f2020-01-05 18:25:31 -080084 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) void DoLog(
85 log_level level, const char *format, va_list ap) override;
Brian Silvermanbe858a12014-04-30 17:37:28 -070086
87 virtual void HandleMessage(const LogMessage &message) = 0;
88};
89
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080090// A log implementation that dumps all messages to a C stdio stream.
Brian Silvermanbe858a12014-04-30 17:37:28 -070091class StreamLogImplementation : public HandleMessageLogImplementation {
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080092 public:
93 StreamLogImplementation(FILE *stream);
94
95 private:
Brian Silvermancb5da1f2015-12-05 22:19:58 -050096 void HandleMessage(const LogMessage &message) override;
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080097
98 FILE *const stream_;
99};
100
Austin Schuh56196432020-10-24 20:15:21 -0700101// Returns the current implementation.
Austin Schuha0c41ba2020-09-10 22:59:14 -0700102std::shared_ptr<LogImplementation> GetImplementation();
Tyler Chatow4b471e12020-01-05 20:19:36 -0800103
Austin Schuha0c41ba2020-09-10 22:59:14 -0700104// Sets the current implementation.
105void SetImplementation(std::shared_ptr<LogImplementation> implementation);
Brian Silvermanf665d692013-02-17 22:11:39 -0800106
Austin Schuh56196432020-10-24 20:15:21 -0700107// A logging implementation which just uses a callback.
Austin Schuha0c41ba2020-09-10 22:59:14 -0700108class CallbackLogImplementation : public HandleMessageLogImplementation {
109 public:
110 CallbackLogImplementation(
111 const ::std::function<void(const LogMessage &)> &callback)
112 : callback_(callback) {}
113
114 private:
115 void HandleMessage(const LogMessage &message) override { callback_(message); }
116
117 ::std::function<void(const LogMessage &)> callback_;
118};
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500119
Tyler Chatow67ddb032020-01-12 14:30:04 -0800120class ScopedLogRestorer {
121 public:
Austin Schuh56196432020-10-24 20:15:21 -0700122 ScopedLogRestorer() : prev_impl_(GetImplementation()) {}
123 ~ScopedLogRestorer() { SetImplementation(std::move(prev_impl_)); }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700124
125 void Swap(std::shared_ptr<LogImplementation> new_impl) {
Austin Schuh56196432020-10-24 20:15:21 -0700126 SetImplementation(std::move(new_impl));
Austin Schuha0c41ba2020-09-10 22:59:14 -0700127 }
Tyler Chatow67ddb032020-01-12 14:30:04 -0800128
129 private:
Austin Schuha0c41ba2020-09-10 22:59:14 -0700130 std::shared_ptr<LogImplementation> prev_impl_;
Tyler Chatow67ddb032020-01-12 14:30:04 -0800131};
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800132
Brian Silvermanf665d692013-02-17 22:11:39 -0800133// This is where all of the code that is only used by actual LogImplementations
134// goes.
135namespace internal {
136
Brian Silverman88471dc2014-02-15 22:35:42 -0800137// Fills in *message according to the given inputs (with type kString).
138// Used for implementing LogImplementation::DoLog.
Austin Schuh82c0c822019-05-27 19:55:20 -0700139void FillInMessage(log_level level,
140 ::aos::monotonic_clock::time_point monotonic_now,
141 const char *format, va_list ap, LogMessage *message)
142 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)));
Brian Silvermanf665d692013-02-17 22:11:39 -0800143
Austin Schuh82c0c822019-05-27 19:55:20 -0700144__attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 4, 5))) static inline void
145FillInMessageVarargs(log_level level,
146 ::aos::monotonic_clock::time_point monotonic_now,
147 LogMessage *message, const char *format, ...) {
Brian Silverman78968542014-03-05 17:03:43 -0800148 va_list ap;
149 va_start(ap, format);
Austin Schuh82c0c822019-05-27 19:55:20 -0700150 FillInMessage(level, monotonic_now, format, ap, message);
Brian Silverman78968542014-03-05 17:03:43 -0800151 va_end(ap);
152}
153
Brian Silvermanf665d692013-02-17 22:11:39 -0800154// Prints message to output.
155void PrintMessage(FILE *output, const LogMessage &message);
156
Brian Silvermanf665d692013-02-17 22:11:39 -0800157} // namespace internal
158} // namespace logging
159} // namespace aos
160
John Park33858a32018-09-28 23:05:48 -0700161#endif // AOS_LOGGING_IMPLEMENTATIONS_H_