blob: 096127aa9094ec2fc6a2ba3e68499adc6395b6d4 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/logging/implementations.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08002
Brian4a424a22014-04-02 11:52:45 -07003#include <inttypes.h>
Tyler Chatow5febd8f2020-01-05 18:25:31 -08004#include <stdarg.h>
Austin Schuh044e18b2015-10-21 20:17:09 -07005
Brian Silvermancb5da1f2015-12-05 22:19:58 -05006#include <algorithm>
Austin Schuhf2a50ba2016-12-24 16:16:26 -08007#include <chrono>
Austin Schuha0c41ba2020-09-10 22:59:14 -07008#include <mutex>
Brian Silvermancb5da1f2015-12-05 22:19:58 -05009
Tyler Chatow5febd8f2020-01-05 18:25:31 -080010#include "absl/base/call_once.h"
John Park33858a32018-09-28 23:05:48 -070011#include "aos/die.h"
12#include "aos/logging/printf_formats.h"
Austin Schuha0c41ba2020-09-10 22:59:14 -070013#include "aos/stl_mutex/stl_mutex.h"
John Park33858a32018-09-28 23:05:48 -070014#include "aos/time/time.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080015
16namespace aos {
17namespace logging {
18namespace {
19
Austin Schuhf2a50ba2016-12-24 16:16:26 -080020namespace chrono = ::std::chrono;
21
Austin Schuha0c41ba2020-09-10 22:59:14 -070022struct GlobalState {
23 std::shared_ptr<LogImplementation> implementation;
24 aos::stl_mutex lock;
25 static GlobalState *Get() {
26 static GlobalState r;
27 return &r;
Brian Silvermanf665d692013-02-17 22:11:39 -080028 }
29};
30
Brian Silvermanf665d692013-02-17 22:11:39 -080031} // namespace
32namespace internal {
Brian Silverman88471dc2014-02-15 22:35:42 -080033namespace {
Brian Silvermanf665d692013-02-17 22:11:39 -080034
Austin Schuh82c0c822019-05-27 19:55:20 -070035void FillInMessageBase(log_level level,
36 monotonic_clock::time_point monotonic_now,
37 LogMessage *message) {
Brian Silvermanf665d692013-02-17 22:11:39 -080038 Context *context = Context::Get();
39
Brian Silvermanf665d692013-02-17 22:11:39 -080040 message->level = level;
41 message->source = context->source;
Austin Schuhaebbc342015-01-25 02:25:13 -080042 memcpy(message->name, context->name, context->name_size);
43 message->name_length = context->name_size;
Brian Silvermanf665d692013-02-17 22:11:39 -080044
Austin Schuhf2a50ba2016-12-24 16:16:26 -080045 message->seconds =
46 chrono::duration_cast<chrono::seconds>(monotonic_now.time_since_epoch())
47 .count();
48 message->nseconds =
49 chrono::duration_cast<chrono::nanoseconds>(
50 monotonic_now.time_since_epoch() - chrono::seconds(message->seconds))
51 .count();
Brian Silvermanf665d692013-02-17 22:11:39 -080052
53 message->sequence = context->sequence++;
54}
55
Brian Silverman88471dc2014-02-15 22:35:42 -080056} // namespace
57
Austin Schuh82c0c822019-05-27 19:55:20 -070058void FillInMessage(log_level level, monotonic_clock::time_point monotonic_now,
59 const char *format, va_list ap, LogMessage *message) {
60 FillInMessageBase(level, monotonic_now, message);
Brian Silverman88471dc2014-02-15 22:35:42 -080061
62 message->message_length =
63 ExecuteFormat(message->message, sizeof(message->message), format, ap);
64 message->type = LogMessage::Type::kString;
65}
66
Brian Silvermanf665d692013-02-17 22:11:39 -080067void PrintMessage(FILE *output, const LogMessage &message) {
Brian Silvermana7234c62014-03-24 20:23:25 -070068#define BASE_ARGS \
69 AOS_LOGGING_BASE_ARGS( \
70 message.name_length, message.name, static_cast<int32_t>(message.source), \
71 message.sequence, message.level, message.seconds, message.nseconds)
72 switch (message.type) {
Brian Silverman88471dc2014-02-15 22:35:42 -080073 case LogMessage::Type::kString:
Brian Silvermana7234c62014-03-24 20:23:25 -070074 fprintf(output, AOS_LOGGING_BASE_FORMAT "%.*s", BASE_ARGS,
Brian Silverman88471dc2014-02-15 22:35:42 -080075 static_cast<int>(message.message_length), message.message);
76 break;
Brian Silverman88471dc2014-02-15 22:35:42 -080077 }
Brian Silvermanc1a244e2014-02-20 14:12:39 -080078#undef BASE_ARGS
Brian Silvermanf665d692013-02-17 22:11:39 -080079}
80
81} // namespace internal
82
Brian Silvermanbe858a12014-04-30 17:37:28 -070083void HandleMessageLogImplementation::DoLog(log_level level, const char *format,
84 va_list ap) {
85 LogMessage message;
Austin Schuh82c0c822019-05-27 19:55:20 -070086 internal::FillInMessage(level, monotonic_now(), format, ap, &message);
Brian Silvermanbe858a12014-04-30 17:37:28 -070087 HandleMessage(message);
88}
89
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080090StreamLogImplementation::StreamLogImplementation(FILE *stream)
91 : stream_(stream) {}
92
Brian Silvermanbe858a12014-04-30 17:37:28 -070093void StreamLogImplementation::HandleMessage(const LogMessage &message) {
Brian Silverman1e8ddfe2013-12-19 16:20:53 -080094 internal::PrintMessage(stream_, message);
95}
96
Austin Schuha0c41ba2020-09-10 22:59:14 -070097void SetImplementation(std::shared_ptr<LogImplementation> implementation) {
98 Init();
99 GlobalState *const global = GlobalState::Get();
100 std::unique_lock<aos::stl_mutex> locker(global->lock);
101 global->implementation = std::move(implementation);
102}
Brian Silvermanf665d692013-02-17 22:11:39 -0800103
Austin Schuha0c41ba2020-09-10 22:59:14 -0700104std::shared_ptr<LogImplementation> SwapImplementation(
105 std::shared_ptr<LogImplementation> implementation) {
106 std::shared_ptr<LogImplementation> result;
107 {
108 GlobalState *const global = GlobalState::Get();
109 std::unique_lock<aos::stl_mutex> locker(global->lock);
110 result = std::move(global->implementation);
111 global->implementation = std::move(implementation);
Brian Silvermanf665d692013-02-17 22:11:39 -0800112 }
Austin Schuha0c41ba2020-09-10 22:59:14 -0700113 Cleanup();
114 return result;
Tyler Chatow4b471e12020-01-05 20:19:36 -0800115}
116
Austin Schuha0c41ba2020-09-10 22:59:14 -0700117std::shared_ptr<LogImplementation> GetImplementation() {
118 GlobalState *const global = GlobalState::Get();
119 std::unique_lock<aos::stl_mutex> locker(global->lock);
120 CHECK(global->implementation);
121 return global->implementation;
Brian Silvermanf665d692013-02-17 22:11:39 -0800122}
123
Austin Schuha0c41ba2020-09-10 22:59:14 -0700124namespace {
Tyler Chatow67ddb032020-01-12 14:30:04 -0800125
Austin Schuha0c41ba2020-09-10 22:59:14 -0700126struct DoInit {
127 DoInit() {
128 GlobalState *const global = GlobalState::Get();
129 std::unique_lock<aos::stl_mutex> locker(global->lock);
130 CHECK(!global->implementation);
131 global->implementation = std::make_shared<StreamLogImplementation>(stdout);
132 }
133};
134
135} // namespace
136
137void Init() { static DoInit do_init; }
Brian Silvermanf665d692013-02-17 22:11:39 -0800138
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800139void Load() { internal::Context::Get(); }
Brian Silvermanf665d692013-02-17 22:11:39 -0800140
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800141void Cleanup() { internal::Context::Delete(); }
Brian Silvermancb5da1f2015-12-05 22:19:58 -0500142
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800143void RegisterCallbackImplementation(
Austin Schuha0c41ba2020-09-10 22:59:14 -0700144 const ::std::function<void(const LogMessage &)> &callback) {
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800145 Init();
Austin Schuha0c41ba2020-09-10 22:59:14 -0700146 SetImplementation(std::make_shared<CallbackLogImplementation>(callback));
Tyler Chatow5febd8f2020-01-05 18:25:31 -0800147}
148
Brian Silvermanf665d692013-02-17 22:11:39 -0800149} // namespace logging
150} // namespace aos