blob: 294750b7cb936a8451d84ce6bef8b03901ef6b5c [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>
Brian Silvermanf665d692013-02-17 22:11:39 -08005
Tyler Chatowbf0609c2021-07-31 16:13:27 -07006#include <cstdint>
Tyler Chatow5febd8f2020-01-05 18:25:31 -08007#include <functional>
Austin Schuha0c41ba2020-09-10 22:59:14 -07008#include <memory>
Tyler Chatow5febd8f2020-01-05 18:25:31 -08009#include <string>
Austin Schuhad9e5eb2021-11-19 20:33:55 -080010#include <string_view>
Stephan Pleines0960c262024-05-31 20:29:24 -070011#include <utility>
Brian Silvermanf665d692013-02-17 22:11:39 -080012
John Park33858a32018-09-28 23:05:48 -070013#include "aos/logging/context.h"
14#include "aos/logging/interface.h"
15#include "aos/logging/logging.h"
John Park33858a32018-09-28 23:05:48 -070016#include "aos/macros.h"
Austin Schuh82c0c822019-05-27 19:55:20 -070017#include "aos/time/time.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080018
Brian Silvermancb5da1f2015-12-05 22:19:58 -050019// This file has various concrete LogImplementations.
Brian Silvermanf665d692013-02-17 22:11:39 -080020
21namespace aos {
22namespace logging {
23
24// Unless explicitly stated otherwise, format must always be a string constant,
25// args are printf-style arguments for format, and ap is a va_list of args.
Brian Silverman1a572cc2013-03-05 19:58:01 -080026// The validity of format and args together will be checked at compile time
Brian Silvermancb5da1f2015-12-05 22:19:58 -050027// using a function attribute.
Brian Silvermanf665d692013-02-17 22:11:39 -080028
Brian Silvermancb5da1f2015-12-05 22:19:58 -050029// Contains all of the information about a given logging call.
Brian Silverman88471dc2014-02-15 22:35:42 -080030struct LogMessage {
Brian Silverman88471dc2014-02-15 22:35:42 -080031 int32_t seconds, nseconds;
Brian Silvermanff12c9f2014-03-19 17:53:29 -070032 // message_length is just the length of the actual data (which member depends
33 // on the type).
Brian Silverman88471dc2014-02-15 22:35:42 -080034 size_t message_length, name_length;
Brian Silvermanf665d692013-02-17 22:11:39 -080035 pid_t source;
36 static_assert(sizeof(source) == 4, "that's how they get printed");
37 // Per task/thread.
38 uint16_t sequence;
39 log_level level;
Austin Schuh044e18b2015-10-21 20:17:09 -070040 char name[LOG_MESSAGE_NAME_LEN];
Austin Schuh56196432020-10-24 20:15:21 -070041 char message[LOG_MESSAGE_LEN];
Brian Silvermanf665d692013-02-17 22:11:39 -080042};
Brian Silvermanf665d692013-02-17 22:11:39 -080043
44// Returns left > right. LOG_UNKNOWN is most important.
45static inline bool log_gt_important(log_level left, log_level right) {
46 if (left == ERROR) left = 3;
47 if (right == ERROR) right = 3;
48 return left > right;
49}
50
51// Returns a string representing level or "unknown".
52static inline const char *log_str(log_level level) {
Tyler Chatow5febd8f2020-01-05 18:25:31 -080053#define DECL_LEVEL(name, value) \
54 if (level == name) return #name;
Brian Silvermanf665d692013-02-17 22:11:39 -080055 DECL_LEVELS;
56#undef DECL_LEVEL
57 return "unknown";
58}
59// Returns the log level represented by str or LOG_UNKNOWN.
60static inline log_level str_log(const char *str) {
Tyler Chatow5febd8f2020-01-05 18:25:31 -080061#define DECL_LEVEL(name, value) \
62 if (!strcmp(str, #name)) return name;
Brian Silvermanf665d692013-02-17 22:11:39 -080063 DECL_LEVELS;
64#undef DECL_LEVEL
65 return LOG_UNKNOWN;
66}
67
Brian Silvermanbe858a12014-04-30 17:37:28 -070068// Implements all of the DoLog* methods in terms of a (pure virtual in this
69// class) HandleMessage method that takes a pointer to the message.
70class HandleMessageLogImplementation : public LogImplementation {
Austin Schuh82c0c822019-05-27 19:55:20 -070071 protected:
72 virtual ::aos::monotonic_clock::time_point monotonic_now() const {
73 return ::aos::monotonic_clock::now();
74 }
75
Brian Silvermancb5da1f2015-12-05 22:19:58 -050076 private:
Tyler Chatow5febd8f2020-01-05 18:25:31 -080077 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0))) void DoLog(
78 log_level level, const char *format, va_list ap) override;
Brian Silvermanbe858a12014-04-30 17:37:28 -070079
80 virtual void HandleMessage(const LogMessage &message) = 0;
81};
82
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080083// A log implementation that dumps all messages to a C stdio stream.
Brian Silvermanbe858a12014-04-30 17:37:28 -070084class StreamLogImplementation : public HandleMessageLogImplementation {
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080085 public:
86 StreamLogImplementation(FILE *stream);
87
Austin Schuhad9e5eb2021-11-19 20:33:55 -080088 // Returns the name of this actual thread as the name.
89 std::string_view MyName() override {
90 internal::Context *context = internal::Context::Get();
91 return context->MyName();
92 }
93
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080094 private:
Brian Silvermancb5da1f2015-12-05 22:19:58 -050095 void HandleMessage(const LogMessage &message) override;
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080096
97 FILE *const stream_;
98};
99
Austin Schuh56196432020-10-24 20:15:21 -0700100// Returns the current implementation.
Austin Schuha0c41ba2020-09-10 22:59:14 -0700101std::shared_ptr<LogImplementation> GetImplementation();
Tyler Chatow4b471e12020-01-05 20:19:36 -0800102
Austin Schuha0c41ba2020-09-10 22:59:14 -0700103// Sets the current implementation.
104void SetImplementation(std::shared_ptr<LogImplementation> implementation);
Brian Silvermanf665d692013-02-17 22:11:39 -0800105
Austin Schuh56196432020-10-24 20:15:21 -0700106// A logging implementation which just uses a callback.
Austin Schuha0c41ba2020-09-10 22:59:14 -0700107class CallbackLogImplementation : public HandleMessageLogImplementation {
108 public:
109 CallbackLogImplementation(
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800110 const ::std::function<void(const LogMessage &)> &callback,
111 const std::string *name)
112 : callback_(callback), name_(name) {}
113
114 // Returns the provided name. This is most likely the event loop name.
115 std::string_view MyName() override { return *name_; }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700116
117 private:
118 void HandleMessage(const LogMessage &message) override { callback_(message); }
119
120 ::std::function<void(const LogMessage &)> callback_;
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800121 const std::string *name_;
Austin Schuha0c41ba2020-09-10 22:59:14 -0700122};
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500123
Tyler Chatow67ddb032020-01-12 14:30:04 -0800124class ScopedLogRestorer {
125 public:
Austin Schuh56196432020-10-24 20:15:21 -0700126 ScopedLogRestorer() : prev_impl_(GetImplementation()) {}
127 ~ScopedLogRestorer() { SetImplementation(std::move(prev_impl_)); }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700128
129 void Swap(std::shared_ptr<LogImplementation> new_impl) {
Austin Schuh56196432020-10-24 20:15:21 -0700130 SetImplementation(std::move(new_impl));
Austin Schuha0c41ba2020-09-10 22:59:14 -0700131 }
Tyler Chatow67ddb032020-01-12 14:30:04 -0800132
133 private:
Austin Schuha0c41ba2020-09-10 22:59:14 -0700134 std::shared_ptr<LogImplementation> prev_impl_;
Tyler Chatow67ddb032020-01-12 14:30:04 -0800135};
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800136
Brian Silvermanf665d692013-02-17 22:11:39 -0800137// This is where all of the code that is only used by actual LogImplementations
138// goes.
139namespace internal {
140
Brian Silverman88471dc2014-02-15 22:35:42 -0800141// Fills in *message according to the given inputs (with type kString).
142// Used for implementing LogImplementation::DoLog.
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800143void FillInMessage(log_level level, std::string_view name,
Austin Schuh82c0c822019-05-27 19:55:20 -0700144 ::aos::monotonic_clock::time_point monotonic_now,
145 const char *format, va_list ap, LogMessage *message)
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800146 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 4, 0)));
Brian Silvermanf665d692013-02-17 22:11:39 -0800147
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800148__attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 5, 6))) static inline void
149FillInMessageVarargs(log_level level, std::string_view name,
Austin Schuh82c0c822019-05-27 19:55:20 -0700150 ::aos::monotonic_clock::time_point monotonic_now,
151 LogMessage *message, const char *format, ...) {
Brian Silverman78968542014-03-05 17:03:43 -0800152 va_list ap;
153 va_start(ap, format);
Austin Schuhad9e5eb2021-11-19 20:33:55 -0800154 FillInMessage(level, name, monotonic_now, format, ap, message);
Brian Silverman78968542014-03-05 17:03:43 -0800155 va_end(ap);
156}
157
Brian Silvermanf665d692013-02-17 22:11:39 -0800158// Prints message to output.
159void PrintMessage(FILE *output, const LogMessage &message);
160
Brian Silvermanf665d692013-02-17 22:11:39 -0800161} // namespace internal
162} // namespace logging
163} // namespace aos
164
John Park33858a32018-09-28 23:05:48 -0700165#endif // AOS_LOGGING_IMPLEMENTATIONS_H_