blob: b73595b1a4238d998a85558fd550a6f35502f120 [file] [log] [blame]
Brian Silverman14fd0fb2014-01-14 21:42:01 -08001#include "aos/linux_code/logging/linux_logging.h"
Brian Silvermanf665d692013-02-17 22:11:39 -08002
3#include <stdarg.h>
4#include <stdio.h>
5#include <string.h>
6#include <time.h>
7#include <sys/types.h>
8#include <errno.h>
9#include <unistd.h>
10#include <limits.h>
Brian Silvermana33af742014-03-08 12:44:12 -080011#include <inttypes.h>
Brian Silvermanf665d692013-02-17 22:11:39 -080012
13#include <algorithm>
14
15#include "aos/common/die.h"
Austin Schuh044e18b2015-10-21 20:17:09 -070016#include "aos/common/logging/logging_interface.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -080017#include "aos/linux_code/ipc_lib/queue.h"
Brian Silverman78968542014-03-05 17:03:43 -080018#include "aos/common/time.h"
Brian Silvermanf665d692013-02-17 22:11:39 -080019
20namespace aos {
21namespace logging {
Brian Silverman14fd0fb2014-01-14 21:42:01 -080022namespace linux_code {
Brian Silvermanf665d692013-02-17 22:11:39 -080023namespace {
24
Brian Silverman78968542014-03-05 17:03:43 -080025RawQueue *queue = NULL;
Brian Silvermanf665d692013-02-17 22:11:39 -080026
Brian Silverman78968542014-03-05 17:03:43 -080027int dropped_messages = 0;
Brian Silverman75e95302015-02-22 00:43:59 -050028::aos::time::Time dropped_start, backoff_start;
29// Wait this long after dropping a message before even trying to write any more.
30constexpr ::aos::time::Time kDropBackoff = ::aos::time::Time::InSeconds(0.1);
Brian Silverman78968542014-03-05 17:03:43 -080031
32LogMessage *GetMessageOrDie() {
33 LogMessage *message = static_cast<LogMessage *>(queue->GetMessage());
34 if (message == NULL) {
35 LOG(FATAL, "%p->GetMessage() failed\n", queue);
36 } else {
37 return message;
38 }
39}
40
41class LinuxQueueLogImplementation : public LogImplementation {
Brian Silvermanf7986142014-04-21 17:42:35 -070042 __attribute__((format(GOOD_PRINTF_FORMAT_TYPE, 3, 0)))
Brian Silverman88471dc2014-02-15 22:35:42 -080043 virtual void DoLog(log_level level, const char *format, va_list ap) override {
44 LogMessage *message = GetMessageOrDie();
Brian Silvermanf665d692013-02-17 22:11:39 -080045 internal::FillInMessage(level, format, ap, message);
Brian Silverman88471dc2014-02-15 22:35:42 -080046 Write(message);
47 }
Brian Silvermanf665d692013-02-17 22:11:39 -080048
Brian Silverman88471dc2014-02-15 22:35:42 -080049 virtual void LogStruct(log_level level, const ::std::string &message_string,
50 size_t size, const MessageType *type,
51 const ::std::function<size_t(char *)> &serialize)
52 override {
53 LogMessage *message = GetMessageOrDie();
54 internal::FillInMessageStructure(level, message_string, size, type,
55 serialize, message);
Brian Silvermanf665d692013-02-17 22:11:39 -080056 Write(message);
57 }
Brian Silverman664db1a2014-03-20 17:06:29 -070058
59 virtual void LogMatrix(log_level level, const ::std::string &message_string,
60 uint32_t type_id, int rows, int cols, const void *data)
61 override {
62 LogMessage *message = GetMessageOrDie();
63 internal::FillInMessageMatrix(level, message_string, type_id, rows, cols,
64 data, message);
65 Write(message);
66 }
Brian Silvermanf665d692013-02-17 22:11:39 -080067};
68
69} // namespace
70
71void Register() {
72 Init();
73
Austin Schuh0480bc82014-10-25 18:01:51 -070074 queue = RawQueue::Fetch("LoggingQueue", sizeof(LogMessage), 1323, 40000);
Brian Silvermanf665d692013-02-17 22:11:39 -080075 if (queue == NULL) {
76 Die("logging: couldn't fetch queue\n");
77 }
78
Brian Silverman88471dc2014-02-15 22:35:42 -080079 AddImplementation(new LinuxQueueLogImplementation());
Brian Silvermanf665d692013-02-17 22:11:39 -080080}
81
Brian Silverman7faaec72014-05-26 16:25:38 -070082const LogMessage *ReadNext(Options<RawQueue> flags, int *index) {
Brian Silvermana6d1b562013-09-01 14:39:39 -070083 return static_cast<const LogMessage *>(queue->ReadMessageIndex(flags, index));
Brian Silvermanf665d692013-02-17 22:11:39 -080084}
85
86const LogMessage *ReadNext() {
Brian Silverman08661c72013-09-01 17:24:38 -070087 return ReadNext(RawQueue::kBlock);
Brian Silvermanf665d692013-02-17 22:11:39 -080088}
89
Brian Silverman7faaec72014-05-26 16:25:38 -070090const LogMessage *ReadNext(Options<RawQueue> flags) {
Brian Silvermanf665d692013-02-17 22:11:39 -080091 const LogMessage *r = NULL;
92 do {
Brian Silvermana6d1b562013-09-01 14:39:39 -070093 r = static_cast<const LogMessage *>(queue->ReadMessage(flags));
Brian Silvermanf665d692013-02-17 22:11:39 -080094 // not blocking means return a NULL if that's what it gets
Brian Silverman08661c72013-09-01 17:24:38 -070095 } while ((flags & RawQueue::kBlock) && r == NULL);
Brian Silvermanf665d692013-02-17 22:11:39 -080096 return r;
97}
98
99LogMessage *Get() {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700100 return static_cast<LogMessage *>(queue->GetMessage());
Brian Silvermanf665d692013-02-17 22:11:39 -0800101}
102
103void Free(const LogMessage *msg) {
Brian Silvermana6d1b562013-09-01 14:39:39 -0700104 queue->FreeMessage(msg);
Brian Silvermanf665d692013-02-17 22:11:39 -0800105}
106
107void Write(LogMessage *msg) {
Brian Silverman75e95302015-02-22 00:43:59 -0500108 if (__builtin_expect(dropped_messages > 0, false)) {
109 ::aos::time::Time message_time =
110 ::aos::time::Time(msg->seconds, msg->nseconds);
Brian Silverman36ee13b2015-03-30 01:18:14 -0400111 if (message_time - backoff_start < kDropBackoff) {
Brian Silverman75e95302015-02-22 00:43:59 -0500112 ++dropped_messages;
113 queue->FreeMessage(msg);
114 return;
115 }
116
Brian Silverman78968542014-03-05 17:03:43 -0800117 LogMessage *dropped_message = GetMessageOrDie();
Brian Silvermana33af742014-03-08 12:44:12 -0800118 internal::FillInMessageVarargs(
119 ERROR, dropped_message,
120 "%d logs starting at %" PRId32 ".%" PRId32 " dropped\n",
Brian Silverman75e95302015-02-22 00:43:59 -0500121 dropped_messages, dropped_start.sec(), dropped_start.nsec());
Brian Silverman78968542014-03-05 17:03:43 -0800122 if (queue->WriteMessage(dropped_message, RawQueue::kNonBlock)) {
123 dropped_messages = 0;
124 } else {
125 // Don't even bother trying to write this message because it's not likely
126 // to work and it would be confusing to have one log in the middle of a
127 // string of failures get through.
128 ++dropped_messages;
Brian Silverman75e95302015-02-22 00:43:59 -0500129 backoff_start = message_time;
Brian Silvermana33af742014-03-08 12:44:12 -0800130 queue->FreeMessage(msg);
Brian Silverman78968542014-03-05 17:03:43 -0800131 return;
132 }
133 }
134 if (!queue->WriteMessage(msg, RawQueue::kNonBlock)) {
135 if (dropped_messages == 0) {
Brian Silverman75e95302015-02-22 00:43:59 -0500136 dropped_start = backoff_start =
137 ::aos::time::Time(msg->seconds, msg->nseconds);
Brian Silverman78968542014-03-05 17:03:43 -0800138 }
139 ++dropped_messages;
Brian Silvermanf665d692013-02-17 22:11:39 -0800140 }
141}
142
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800143} // namespace linux_code
Brian Silvermanf665d692013-02-17 22:11:39 -0800144} // namespace logging
145} // namespace aos