blob: 88fd5276549c4fbd5e1085f927c1039a69542fc6 [file] [log] [blame]
Keir Mierleaf5e3582019-12-30 13:11:05 -08001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15// This is a very basic direct output log implementation with no buffering.
16
17#include "pw_log_basic/log_basic.h"
18
19#include <cstring>
20
Keir Mierleaf5e3582019-12-30 13:11:05 -080021#include "pw_log/levels.h"
Armando Montanezf1f41102020-11-02 15:58:39 -080022#include "pw_log_basic_private/config.h"
Keir Mierleaf5e3582019-12-30 13:11:05 -080023#include "pw_string/string_builder.h"
Armando Montanezf7a5a742020-03-02 14:58:59 -080024#include "pw_sys_io/sys_io.h"
Keir Mierleaf5e3582019-12-30 13:11:05 -080025
26// ANSI color constants to control the terminal. Not Windows compatible.
27// clang-format off
28#define MAGENTA "\033[35m"
29#define YELLOW "\033[33m"
30#define RED "\033[31m"
31#define GREEN "\033[32m"
32#define BLUE "\033[96m"
33#define BLACK "\033[30m"
34#define YELLOW_BG "\033[43m"
35#define WHITE_BG "\033[47m"
36#define RED_BG "\033[41m"
37#define BOLD "\033[1m"
38#define RESET "\033[0m"
39// clang-format on
40
Wyatt Hepler2ccde062020-09-16 21:58:53 -070041namespace pw::log_basic {
Keir Mierleaf5e3582019-12-30 13:11:05 -080042namespace {
43
44const char* LogLevelToLogLevelName(int level) {
45 switch (level) {
46 // clang-format off
Armando Montaneza1065b92020-03-19 12:36:31 -070047#if PW_EMOJI
Keir Mierleaf5e3582019-12-30 13:11:05 -080048 case PW_LOG_LEVEL_DEBUG : return "👾" RESET;
49 case PW_LOG_LEVEL_INFO : return "ℹī¸ " RESET;
50 case PW_LOG_LEVEL_WARN : return "⚠ī¸ " RESET;
51 case PW_LOG_LEVEL_ERROR : return "❌" RESET;
52 case PW_LOG_LEVEL_CRITICAL : return "☠ī¸ " RESET;
53 default: return "❔" RESET;
54#else
55 case PW_LOG_LEVEL_DEBUG : return BLUE BOLD "DBG" RESET;
56 case PW_LOG_LEVEL_INFO : return MAGENTA BOLD "INF" RESET;
57 case PW_LOG_LEVEL_WARN : return YELLOW BOLD "WRN" RESET;
58 case PW_LOG_LEVEL_ERROR : return RED BOLD "ERR" RESET;
59 case PW_LOG_LEVEL_CRITICAL : return BLACK BOLD RED_BG "FTL" RESET;
60 default : return GREEN BOLD "UNK" RESET;
61#endif
62 // clang-format on
63 }
64}
65
66#if PW_LOG_SHOW_FILENAME
67const char* GetFileBasename(const char* filename) {
68 int length = std::strlen(filename);
69 if (length == 0) {
70 return filename;
71 }
72
73 // Start on the last character.
74 // TODO(pwbug/38): This part of the function doesn't work for Windows paths.
75 const char* basename = filename + std::strlen(filename) - 1;
76 while (basename != filename && *basename != '/') {
77 basename--;
78 }
79 if (*basename == '/') {
80 basename++;
81 }
82 return basename;
83}
84#endif // PW_LOG_SHOW_FILENAME
85
Wyatt Hepler2ccde062020-09-16 21:58:53 -070086void (*write_log)(std::string_view) = [](std::string_view log) {
87 sys_io::WriteLine(log);
88};
89
Keir Mierleaf5e3582019-12-30 13:11:05 -080090} // namespace
91
92// This is a fully loaded, inefficient-at-the-callsite, log implementation.
93extern "C" void pw_Log(int level,
94 unsigned int flags,
95 const char* module_name,
96 const char* file_name,
97 int line_number,
98 const char* function_name,
99 const char* message,
100 ...) {
Keir Mierleaf5e3582019-12-30 13:11:05 -0800101 // Accumulate the log message in this buffer, then output it.
102 pw::StringBuffer<150> buffer;
103
Ewout van Bekkumf6db1f52021-02-10 19:55:13 -0800104 // Column: Timestamp
105 // Note that this macro method defaults to a no-op.
106 PW_LOG_APPEND_TIMESTAMP(buffer);
107
Keir Mierleaf5e3582019-12-30 13:11:05 -0800108 // Column: Filename
Keir Mierleda0bccb2020-01-17 13:51:35 -0800109#if PW_LOG_SHOW_FILENAME
Keir Mierle8c352dc2020-02-02 13:58:19 -0800110 buffer.Format(" %-30s:%4d |", GetFileBasename(file_name), line_number);
Keir Mierleaf5e3582019-12-30 13:11:05 -0800111#else
Wyatt Hepler63afc002021-02-08 13:20:26 -0800112 static_cast<void>(file_name);
113 static_cast<void>(line_number);
Keir Mierle8c352dc2020-02-02 13:58:19 -0800114#endif
115
116 // Column: Function
117#if PW_LOG_SHOW_FUNCTION
118 buffer.Format(" %20s |", function_name);
119#else
Wyatt Hepler63afc002021-02-08 13:20:26 -0800120 static_cast<void>(function_name);
Keir Mierleaf5e3582019-12-30 13:11:05 -0800121#endif
122
123 // Column: Module
Keir Mierleda0bccb2020-01-17 13:51:35 -0800124#if PW_LOG_SHOW_MODULE
Keir Mierleaf5e3582019-12-30 13:11:05 -0800125 buffer << " " BOLD;
126 buffer.Format("%3s", module_name);
127 buffer << RESET " ";
Keir Mierleda0bccb2020-01-17 13:51:35 -0800128#else
Wyatt Hepler63afc002021-02-08 13:20:26 -0800129 static_cast<void>(module_name);
Keir Mierleda0bccb2020-01-17 13:51:35 -0800130#endif // PW_LOG_SHOW_MODULE
Keir Mierleaf5e3582019-12-30 13:11:05 -0800131
132 // Column: Flag
133#if PW_LOG_SHOW_FLAG
Armando Montaneza1065b92020-03-19 12:36:31 -0700134#if PW_EMOJI
Keir Mierleaf5e3582019-12-30 13:11:05 -0800135 buffer << (flags ? "🚩" : " ");
136#else
137 buffer << (flags ? "*" : "|");
Armando Montaneza1065b92020-03-19 12:36:31 -0700138#endif // PW_EMOJI
Keir Mierleaf5e3582019-12-30 13:11:05 -0800139 buffer << " ";
140#else
Wyatt Hepler63afc002021-02-08 13:20:26 -0800141 static_cast<void>(flags);
Keir Mierleaf5e3582019-12-30 13:11:05 -0800142#endif // PW_LOG_SHOW_FLAG
143
144 // Column: Level
Keir Mierleda0bccb2020-01-17 13:51:35 -0800145 buffer << LogLevelToLogLevelName(level) << " ";
Keir Mierleaf5e3582019-12-30 13:11:05 -0800146
147 // Column: Message
148 va_list args;
149 va_start(args, message);
Wyatt Hepler2596fe52020-01-23 17:40:10 -0800150 buffer.FormatVaList(message, args);
Keir Mierleaf5e3582019-12-30 13:11:05 -0800151 va_end(args);
152
153 // All done; flush the log.
Wyatt Hepler2ccde062020-09-16 21:58:53 -0700154 write_log(buffer);
Keir Mierleaf5e3582019-12-30 13:11:05 -0800155}
Wyatt Hepler2ccde062020-09-16 21:58:53 -0700156
157void SetOutput(void (*log_output)(std::string_view log)) {
158 write_log = log_output;
159}
160
161} // namespace pw::log_basic