Coverage Report

Created: 2025-06-13 06:31

/proc/self/cwd/pw_log_basic/log_basic.cc
Line
Count
Source (jump to first uncovered line)
1
// 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
21
#include "pw_log/levels.h"
22
#include "pw_log_basic_private/config.h"
23
#include "pw_string/string_builder.h"
24
#include "pw_sys_io/sys_io.h"
25
26
// ANSI color constants to control the terminal. Not Windows compatible.
27
// clang-format off
28
455k
#define MAGENTA   "\033[35m"
29
876k
#define YELLOW    "\033[33m"
30
389k
#define RED       "\033[31m"
31
0
#define GREEN     "\033[32m"
32
19.1M
#define BLUE      "\033[96m"
33
0
#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
20.8M
#define RESET     "\033[0m"
39
// clang-format on
40
41
namespace pw::log_basic {
42
namespace {
43
44
20.8M
const char* LogLevelToLogLevelName(int level) {
45
20.8M
  switch (level) {
46
    // clang-format off
47
#if PW_EMOJI
48
    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
19.1M
    case PW_LOG_LEVEL_DEBUG    : return BLUE     BOLD        "DBG" RESET;
56
455k
    case PW_LOG_LEVEL_INFO     : return MAGENTA  BOLD        "INF" RESET;
57
876k
    case PW_LOG_LEVEL_WARN     : return YELLOW   BOLD        "WRN" RESET;
58
389k
    case PW_LOG_LEVEL_ERROR    : return RED      BOLD        "ERR" RESET;
59
0
    case PW_LOG_LEVEL_CRITICAL : return BLACK    BOLD RED_BG "FTL" RESET;
60
0
    default                    : return GREEN    BOLD        "UNK" RESET;
61
20.8M
#endif
62
      // clang-format on
63
20.8M
  }
64
20.8M
}
65
66
#if PW_LOG_SHOW_FILENAME
67
const 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
86
20.8M
void (*write_log)(std::string_view) = [](std::string_view log) {
87
20.8M
  sys_io::WriteLine(log)
88
20.8M
      .IgnoreError();  // TODO: b/242598609 - Handle Status properly
89
20.8M
};
90
91
}  // namespace
92
93
// This is a fully loaded, inefficient-at-the-callsite, log implementation.
94
extern "C" void pw_Log(int level,
95
                       unsigned int flags,
96
                       const char* module_name,
97
                       const char* file_name,
98
                       int line_number,
99
                       const char* function_name,
100
                       const char* message,
101
20.8M
                       ...) {
102
20.8M
  va_list args;
103
20.8M
  va_start(args, message);
104
20.8M
  pw_Log_HandleMessageVaList(level,
105
20.8M
                             flags,
106
20.8M
                             module_name,
107
20.8M
                             file_name,
108
20.8M
                             line_number,
109
20.8M
                             function_name,
110
20.8M
                             message,
111
20.8M
                             args);
112
20.8M
  va_end(args);
113
20.8M
}
114
115
extern "C" void pw_Log_HandleMessageVaList(int level,
116
                                           unsigned int flags,
117
                                           const char* module_name,
118
                                           const char* file_name,
119
                                           int line_number,
120
                                           const char* function_name,
121
                                           const char* message,
122
20.8M
                                           va_list args) {
123
  // Accumulate the log message in this buffer, then output it.
124
20.8M
  pw::StringBuffer<PW_LOG_BASIC_ENTRY_SIZE> buffer;
125
126
  // Column: Timestamp
127
  // Note that this macro method defaults to a no-op.
128
20.8M
  PW_LOG_APPEND_TIMESTAMP(buffer);
129
130
  // Column: Filename
131
#if PW_LOG_SHOW_FILENAME
132
  buffer.Format(" %-30s:%4d |", GetFileBasename(file_name), line_number);
133
#else
134
20.8M
  static_cast<void>(file_name);
135
20.8M
  static_cast<void>(line_number);
136
20.8M
#endif
137
138
  // Column: Function
139
#if PW_LOG_SHOW_FUNCTION
140
  buffer.Format(" %-30s |", function_name);
141
#else
142
20.8M
  static_cast<void>(function_name);
143
20.8M
#endif
144
145
  // Column: Module
146
#if PW_LOG_SHOW_MODULE
147
  buffer << " " BOLD;
148
  buffer.Format("%3s", module_name);
149
  buffer << RESET " ";
150
#else
151
20.8M
  static_cast<void>(module_name);
152
20.8M
#endif  // PW_LOG_SHOW_MODULE
153
154
  // Column: Flag
155
#if PW_LOG_SHOW_FLAG
156
#if PW_EMOJI
157
  buffer << (flags ? "🚩" : "  ");
158
#else
159
  buffer << (flags ? "*" : "|");
160
#endif  // PW_EMOJI
161
  buffer << " ";
162
#else
163
20.8M
  static_cast<void>(flags);
164
20.8M
#endif  // PW_LOG_SHOW_FLAG
165
166
  // Column: Level
167
20.8M
  buffer << LogLevelToLogLevelName(level) << "  ";
168
169
  // Column: Message
170
20.8M
  buffer.FormatVaList(message, args);
171
172
  // All done; flush the log.
173
20.8M
  write_log(buffer);
174
20.8M
}
175
176
0
void SetOutput(void (*log_output)(std::string_view log)) {
177
0
  write_log = log_output;
178
0
}
179
180
}  // namespace pw::log_basic