third_party.pigweed.src/pw_log_basic/log_basic.cc
Keir Mierle af5e358b00 pw_log: Logging module first steps
This starts a logging module facade, with a frontend and a dumb IO based
backend. The initial version is lacking many features, like an API to
control enabling or disabling logs.

Change-Id: I3075aed33d9600a1190ca5237b5f7cfcfdc8f2ed
2020-01-17 12:42:05 -08:00

142 lines
4.0 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2020 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
// This is a very basic direct output log implementation with no buffering.
#include "pw_log_basic/log_basic.h"
#include <cstring>
#include "pw_dumb_io/dumb_io.h"
#include "pw_log/levels.h"
#include "pw_string/string_builder.h"
// ANSI color constants to control the terminal. Not Windows compatible.
// clang-format off
#define MAGENTA "\033[35m"
#define YELLOW "\033[33m"
#define RED "\033[31m"
#define GREEN "\033[32m"
#define BLUE "\033[96m"
#define BLACK "\033[30m"
#define YELLOW_BG "\033[43m"
#define WHITE_BG "\033[47m"
#define RED_BG "\033[41m"
#define BOLD "\033[1m"
#define RESET "\033[0m"
// clang-format on
// TODO(pwbug/17): Expose these through the config system.
#define PW_USE_EMOJIS 1
#define PW_LOG_SHOW_FILENAME 0
#define PW_LOG_SHOW_FLAG 0
namespace {
const char* LogLevelToLogLevelName(int level) {
switch (level) {
// clang-format off
#if PW_USE_EMOJIS
case PW_LOG_LEVEL_DEBUG : return "👾" RESET;
case PW_LOG_LEVEL_INFO : return " " RESET;
case PW_LOG_LEVEL_WARN : return "⚠️ " RESET;
case PW_LOG_LEVEL_ERROR : return "" RESET;
case PW_LOG_LEVEL_CRITICAL : return "☠️ " RESET;
default: return "" RESET;
#else
case PW_LOG_LEVEL_DEBUG : return BLUE BOLD "DBG" RESET;
case PW_LOG_LEVEL_INFO : return MAGENTA BOLD "INF" RESET;
case PW_LOG_LEVEL_WARN : return YELLOW BOLD "WRN" RESET;
case PW_LOG_LEVEL_ERROR : return RED BOLD "ERR" RESET;
case PW_LOG_LEVEL_CRITICAL : return BLACK BOLD RED_BG "FTL" RESET;
default : return GREEN BOLD "UNK" RESET;
#endif
// clang-format on
}
}
#if PW_LOG_SHOW_FILENAME
const char* GetFileBasename(const char* filename) {
int length = std::strlen(filename);
if (length == 0) {
return filename;
}
// Start on the last character.
// TODO(pwbug/38): This part of the function doesn't work for Windows paths.
const char* basename = filename + std::strlen(filename) - 1;
while (basename != filename && *basename != '/') {
basename--;
}
if (*basename == '/') {
basename++;
}
return basename;
}
#endif // PW_LOG_SHOW_FILENAME
} // namespace
// This is a fully loaded, inefficient-at-the-callsite, log implementation.
extern "C" void pw_Log(int level,
unsigned int flags,
const char* module_name,
const char* file_name,
int line_number,
const char* function_name,
const char* message,
...) {
PW_UNUSED(function_name);
PW_UNUSED(line_number);
// Accumulate the log message in this buffer, then output it.
pw::StringBuffer<150> buffer;
// Column: Filename
#if PW_SHOW_FILENAME
buffer.Format(" %-30s |", GetFileBasename(file_name));
#else
PW_UNUSED(file_name);
#endif
// Column: Module
buffer << " " BOLD;
buffer.Format("%3s", module_name);
buffer << RESET " ";
// Column: Flag
#if PW_LOG_SHOW_FLAG
#if PW_USE_EMOJIS
buffer << (flags ? "🚩" : " ");
#else
buffer << (flags ? "*" : "|");
#endif // PW_USE_EMOJIS
buffer << " ";
#else
PW_UNUSED(flags);
#endif // PW_LOG_SHOW_FLAG
// Column: Level
buffer << LogLevelToLogLevelName(level) << " ";
// Column: Message
va_list args;
va_start(args, message);
buffer.Format(message, args);
va_end(args);
// All done; flush the log.
pw::dumb_io::WriteLine(buffer.view());
}