blob: 0cb0cd8acaf03721b8f1526f0a7aa8a016b793f0 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/logging/interface.h"
Brian Silvermanb0893882014-02-10 14:48:30 -08002
Brian Silvermanb0893882014-02-10 14:48:30 -08003#include <stdarg.h>
Austin Schuh044e18b2015-10-21 20:17:09 -07004#include <stdio.h>
Brian Silvermanb0893882014-02-10 14:48:30 -08005#include <string.h>
6
Austin Schuh044e18b2015-10-21 20:17:09 -07007#include <functional>
Tyler Chatow4b471e12020-01-05 20:19:36 -08008#include <type_traits>
Brian Silverman88471dc2014-02-15 22:35:42 -08009
John Park33858a32018-09-28 23:05:48 -070010#include "aos/die.h"
11#include "aos/logging/context.h"
Austin Schuh56196432020-10-24 20:15:21 -070012#include "aos/logging/implementations.h"
13#include "glog/logging.h"
Brian Silvermanb0893882014-02-10 14:48:30 -080014
Brian Silvermanb0893882014-02-10 14:48:30 -080015namespace aos {
16namespace logging {
17namespace internal {
18
Brian Silverman88471dc2014-02-15 22:35:42 -080019size_t ExecuteFormat(char *output, size_t output_size, const char *format,
20 va_list ap) {
21 static const char *const continued = "...\n";
Brian Silvermanb0893882014-02-10 14:48:30 -080022 const size_t size = output_size - strlen(continued);
23 const int ret = vsnprintf(output, size, format, ap);
Alex Perrycb7da4b2019-08-28 19:35:56 -070024 typedef ::std::common_type<int, size_t>::type RetType;
Brian Silvermanb0893882014-02-10 14:48:30 -080025 if (ret < 0) {
Austin Schuh56196432020-10-24 20:15:21 -070026 PLOG(FATAL) << "vsnprintf(" << output << ", " << size << ", " << format
27 << ", args) failed";
Brian Silverman88471dc2014-02-15 22:35:42 -080028 } else if (static_cast<RetType>(ret) >= static_cast<RetType>(size)) {
Brian Silvermanb0893882014-02-10 14:48:30 -080029 // Overwrite the '\0' at the end of the existing data and
30 // copy in the one on the end of continued.
31 memcpy(&output[size - 1], continued, strlen(continued) + 1);
32 }
Brian Silverman88471dc2014-02-15 22:35:42 -080033 return ::std::min<RetType>(ret, size);
Brian Silvermanb0893882014-02-10 14:48:30 -080034}
35
Brian Silvermand6974f42014-02-14 13:39:21 -080036} // namespace internal
37
38using internal::Context;
39
Brian Silvermanb0893882014-02-10 14:48:30 -080040void VLog(log_level level, const char *format, va_list ap) {
Austin Schuh56196432020-10-24 20:15:21 -070041 va_list ap1;
42 va_copy(ap1, ap);
43
44 Context *context = Context::Get();
45
46 const std::shared_ptr<LogImplementation> implementation =
47 context->implementation;
48 // Log to the implementation if we have it, and stderr as a backup.
49 if (implementation) {
50 implementation->DoLog(level, format, ap1);
51 } else {
52 aos::logging::LogMessage message;
53 aos::logging::internal::FillInMessage(level, aos::monotonic_clock::now(),
54 format, ap, &message);
55 aos::logging::internal::PrintMessage(stderr, message);
56 }
57 va_end(ap1);
58
59 if (level == FATAL) {
60 VDie(format, ap);
61 }
Brian Silvermanb0893882014-02-10 14:48:30 -080062}
63
Brian Silvermanb0893882014-02-10 14:48:30 -080064} // namespace logging
65} // namespace aos
66
67void log_do(log_level level, const char *format, ...) {
68 va_list ap;
69 va_start(ap, format);
70 aos::logging::VLog(level, format, ap);
71 va_end(ap);
72}