blob: a6302859cea4141d4506eeb30e32ea2fc8114cbd [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/logging/interface.h"
Brian Silvermanb0893882014-02-10 14:48:30 -08002
Stephan Pleines0960c262024-05-31 20:29:24 -07003#include <algorithm>
Tyler Chatowbf0609c2021-07-31 16:13:27 -07004#include <cstdarg>
5#include <cstdio>
6#include <cstring>
Stephan Pleines0960c262024-05-31 20:29:24 -07007#include <memory>
8#include <ostream>
9#include <string>
Tyler Chatow4b471e12020-01-05 20:19:36 -080010#include <type_traits>
Brian Silverman88471dc2014-02-15 22:35:42 -080011
Austin Schuh99f7c6a2024-06-25 22:07:44 -070012#include "absl/log/check.h"
13#include "absl/log/log.h"
Philipp Schrader790cb542023-07-05 21:06:52 -070014
John Park33858a32018-09-28 23:05:48 -070015#include "aos/die.h"
16#include "aos/logging/context.h"
Austin Schuh56196432020-10-24 20:15:21 -070017#include "aos/logging/implementations.h"
Stephan Pleines0960c262024-05-31 20:29:24 -070018#include "aos/time/time.h"
Brian Silvermanb0893882014-02-10 14:48:30 -080019
Stephan Pleinesf63bde82024-01-13 15:59:33 -080020namespace aos::logging {
Brian Silvermanb0893882014-02-10 14:48:30 -080021namespace internal {
22
Brian Silverman88471dc2014-02-15 22:35:42 -080023size_t ExecuteFormat(char *output, size_t output_size, const char *format,
24 va_list ap) {
25 static const char *const continued = "...\n";
Brian Silvermanb0893882014-02-10 14:48:30 -080026 const size_t size = output_size - strlen(continued);
27 const int ret = vsnprintf(output, size, format, ap);
Alex Perrycb7da4b2019-08-28 19:35:56 -070028 typedef ::std::common_type<int, size_t>::type RetType;
Brian Silvermanb0893882014-02-10 14:48:30 -080029 if (ret < 0) {
Austin Schuh56196432020-10-24 20:15:21 -070030 PLOG(FATAL) << "vsnprintf(" << output << ", " << size << ", " << format
31 << ", args) failed";
Brian Silverman88471dc2014-02-15 22:35:42 -080032 } else if (static_cast<RetType>(ret) >= static_cast<RetType>(size)) {
Brian Silvermanb0893882014-02-10 14:48:30 -080033 // Overwrite the '\0' at the end of the existing data and
34 // copy in the one on the end of continued.
35 memcpy(&output[size - 1], continued, strlen(continued) + 1);
36 }
Brian Silverman88471dc2014-02-15 22:35:42 -080037 return ::std::min<RetType>(ret, size);
Brian Silvermanb0893882014-02-10 14:48:30 -080038}
39
Brian Silvermand6974f42014-02-14 13:39:21 -080040} // namespace internal
41
42using internal::Context;
43
Brian Silvermanb0893882014-02-10 14:48:30 -080044void VLog(log_level level, const char *format, va_list ap) {
Austin Schuh56196432020-10-24 20:15:21 -070045 va_list ap1;
46 va_copy(ap1, ap);
47
48 Context *context = Context::Get();
49
50 const std::shared_ptr<LogImplementation> implementation =
51 context->implementation;
52 // Log to the implementation if we have it, and stderr as a backup.
53 if (implementation) {
54 implementation->DoLog(level, format, ap1);
55 } else {
56 aos::logging::LogMessage message;
Austin Schuhad9e5eb2021-11-19 20:33:55 -080057 aos::logging::internal::FillInMessage(level, context->MyName(),
58 aos::monotonic_clock::now(), format,
59 ap, &message);
Austin Schuh56196432020-10-24 20:15:21 -070060 aos::logging::internal::PrintMessage(stderr, message);
61 }
62 va_end(ap1);
63
64 if (level == FATAL) {
65 VDie(format, ap);
66 }
Brian Silvermanb0893882014-02-10 14:48:30 -080067}
68
Stephan Pleinesf63bde82024-01-13 15:59:33 -080069} // namespace aos::logging
Brian Silvermanb0893882014-02-10 14:48:30 -080070
71void log_do(log_level level, const char *format, ...) {
72 va_list ap;
73 va_start(ap, format);
74 aos::logging::VLog(level, format, ap);
75 va_end(ap);
76}