Support terminal colors for logger.
This commit is contained in:
@@ -9,6 +9,7 @@ endif()
|
|||||||
project(webcc)
|
project(webcc)
|
||||||
|
|
||||||
option(WEBCC_ENABLE_SOAP "Enable SOAP support (need pugixml)?" ON)
|
option(WEBCC_ENABLE_SOAP "Enable SOAP support (need pugixml)?" ON)
|
||||||
|
option(WEBCC_ENABLE_TEST "Build test?" ON)
|
||||||
option(WEBCC_ENABLE_UNITTEST "Build unit test?" ON)
|
option(WEBCC_ENABLE_UNITTEST "Build unit test?" ON)
|
||||||
option(WEBCC_ENABLE_EXAMPLES "Build examples?" ON)
|
option(WEBCC_ENABLE_EXAMPLES "Build examples?" ON)
|
||||||
|
|
||||||
@@ -140,6 +141,10 @@ if(WEBCC_ENABLE_EXAMPLES)
|
|||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WEBCC_ENABLE_TEST)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WEBCC_ENABLE_UNITTEST)
|
if(WEBCC_ENABLE_UNITTEST)
|
||||||
add_subdirectory(${THIRD_PARTY_DIR}/src/gtest)
|
add_subdirectory(${THIRD_PARTY_DIR}/src/gtest)
|
||||||
add_subdirectory(unittest)
|
add_subdirectory(unittest)
|
||||||
|
|||||||
+7
-7
@@ -20,7 +20,7 @@ AlwaysBreakBeforeMultilineStrings: true
|
|||||||
AlwaysBreakTemplateDeclarations: Yes
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
BinPackArguments: true
|
BinPackArguments: true
|
||||||
BinPackParameters: true
|
BinPackParameters: true
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterClass: false
|
AfterClass: false
|
||||||
AfterControlStatement: false
|
AfterControlStatement: false
|
||||||
AfterEnum: false
|
AfterEnum: false
|
||||||
@@ -56,12 +56,12 @@ DerivePointerAlignment: false
|
|||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
FixNamespaceComments: true
|
FixNamespaceComments: true
|
||||||
ForEachMacros:
|
ForEachMacros:
|
||||||
- foreach
|
- foreach
|
||||||
- Q_FOREACH
|
- Q_FOREACH
|
||||||
- BOOST_FOREACH
|
- BOOST_FOREACH
|
||||||
IncludeBlocks: Preserve
|
IncludeBlocks: Preserve
|
||||||
IncludeCategories:
|
IncludeCategories:
|
||||||
- Regex: '^<ext/.*\.h>'
|
- Regex: '^<ext/.*\.h>'
|
||||||
Priority: 2
|
Priority: 2
|
||||||
- Regex: '^<.*\.h>'
|
- Regex: '^<.*\.h>'
|
||||||
@@ -95,9 +95,9 @@ PenaltyBreakTemplateDeclaration: 10
|
|||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyReturnTypeOnItsOwnLine: 200
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
RawStringFormats:
|
RawStringFormats:
|
||||||
- Language: Cpp
|
- Language: Cpp
|
||||||
Delimiters:
|
Delimiters:
|
||||||
- cc
|
- cc
|
||||||
- CC
|
- CC
|
||||||
- cpp
|
- cpp
|
||||||
@@ -108,12 +108,12 @@ RawStringFormats:
|
|||||||
CanonicalDelimiter: ''
|
CanonicalDelimiter: ''
|
||||||
BasedOnStyle: google
|
BasedOnStyle: google
|
||||||
- Language: TextProto
|
- Language: TextProto
|
||||||
Delimiters:
|
Delimiters:
|
||||||
- pb
|
- pb
|
||||||
- PB
|
- PB
|
||||||
- proto
|
- proto
|
||||||
- PROTO
|
- PROTO
|
||||||
EnclosingFunctions:
|
EnclosingFunctions:
|
||||||
- EqualsProto
|
- EqualsProto
|
||||||
- EquivToProto
|
- EquivToProto
|
||||||
- PARSE_PARTIAL_TEXT_PROTO
|
- PARSE_PARTIAL_TEXT_PROTO
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@@ -0,0 +1,19 @@
|
|||||||
|
# Tests
|
||||||
|
|
||||||
|
# Common libraries to link.
|
||||||
|
set(TEST_COMMON_LIBS webcc ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES}
|
||||||
|
"${CMAKE_THREAD_LIBS_INIT}")
|
||||||
|
if(WIN32)
|
||||||
|
set(TEST_COMMON_LIBS ${TEST_COMMON_LIBS} zlibstatic crypt32)
|
||||||
|
else()
|
||||||
|
set(TEST_COMMON_LIBS ${TEST_COMMON_LIBS} ${ZLIB_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
# Add `-ldl` for Linux to avoid "undefined reference to `dlopen'".
|
||||||
|
set(TEST_COMMON_LIBS ${TEST_COMMON_LIBS} ${CMAKE_DL_LIBS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(test_logger test_logger.cc)
|
||||||
|
target_link_libraries(test_logger ${TEST_COMMON_LIBS})
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
|
LOG_INFO("info");
|
||||||
|
LOG_WARN("warn");
|
||||||
|
LOG_ERRO("erro");
|
||||||
|
LOG_VERB("verb");
|
||||||
|
LOG_FATA("fata");
|
||||||
|
LOG_INFO("info");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ HttpRequestPtr HttpRequestBuilder::Build() {
|
|||||||
std::string data;
|
std::string data;
|
||||||
CreateFormData(&data, boundary);
|
CreateFormData(&data, boundary);
|
||||||
|
|
||||||
// Ingore gzip since most servers don't support it.
|
// Ingore gzip since most servers don't support it.
|
||||||
request->SetContent(std::move(data), true);
|
request->SetContent(std::move(data), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+126
-11
@@ -24,6 +24,16 @@
|
|||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static std::string g_main_thread_id;
|
||||||
|
|
||||||
|
static const char* kLevelNames[] = {
|
||||||
|
"VERB", "INFO", "WARN", "ERRO", "FATA"
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
struct Logger {
|
struct Logger {
|
||||||
Logger() : file(nullptr), modes(0) {
|
Logger() : file(nullptr), modes(0) {
|
||||||
}
|
}
|
||||||
@@ -56,11 +66,96 @@ struct Logger {
|
|||||||
// Global logger.
|
// Global logger.
|
||||||
static Logger g_logger;
|
static Logger g_logger;
|
||||||
|
|
||||||
static std::string g_main_thread_id;
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
static const char* kLevelNames[] = {
|
// The colors related code was adapted from Loguru. See:
|
||||||
"VERB", "INFO", "WARN", "ERRO", "FATA"
|
// https://github.com/emilk/loguru/blob/master/loguru.cpp
|
||||||
};
|
// Thanks to Loguru!
|
||||||
|
|
||||||
|
bool g_colorlogtostderr = true;
|
||||||
|
|
||||||
|
static const bool g_terminal_has_color = []() {
|
||||||
|
#if (defined(WIN32) || defined(_WIN64))
|
||||||
|
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||||
|
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||||
|
#endif
|
||||||
|
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
if (houtput != INVALID_HANDLE_VALUE) {
|
||||||
|
DWORD mode = 0;
|
||||||
|
GetConsoleMode(houtput, &mode);
|
||||||
|
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
return SetConsoleMode(houtput, mode) != 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
const char* term = getenv("TERM");
|
||||||
|
if (term == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strcmp(term, "cygwin") == 0 || strcmp(term, "linux") == 0 ||
|
||||||
|
strcmp(term, "rxvt-unicode-256color") == 0 ||
|
||||||
|
strcmp(term, "screen") == 0 || strcmp(term, "screen-256color") == 0 ||
|
||||||
|
strcmp(term, "tmux-256color") == 0 || strcmp(term, "xterm") == 0 ||
|
||||||
|
strcmp(term, "xterm-256color") == 0 ||
|
||||||
|
strcmp(term, "xterm-termite") == 0 || strcmp(term, "xterm-color") == 0;
|
||||||
|
#endif
|
||||||
|
}();
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define VTSEQ(ID) ("\x1b[1;" #ID "m")
|
||||||
|
#else
|
||||||
|
#define VTSEQ(ID) ("\x1b[" #ID "m")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* TerminalBlack() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(30) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalRed() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(31) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalGreen() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(32) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalYellow() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(33) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalBlue() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(34) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalPurple() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(35) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalCyan() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(36) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalLightGray() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(37) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalWhite() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(37) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalLightRed() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(91) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalDim() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(2) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formating
|
||||||
|
const char* TerminalBold() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(1) : "";
|
||||||
|
}
|
||||||
|
const char* TerminalUnderline() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(4) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// You should end each line with this!
|
||||||
|
const char* TerminalReset() {
|
||||||
|
return g_terminal_has_color ? VTSEQ(0) : "";
|
||||||
|
}
|
||||||
|
|
||||||
namespace bfs = boost::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
@@ -123,8 +218,8 @@ static std::string GetTimestamp() {
|
|||||||
ss << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S");
|
ss << std::put_time(std::localtime(&t), "%Y-%m-%d %H:%M:%S");
|
||||||
|
|
||||||
std::chrono::milliseconds milli_seconds =
|
std::chrono::milliseconds milli_seconds =
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
now.time_since_epoch());
|
now.time_since_epoch());
|
||||||
std::string micro_seconds_str = std::to_string(milli_seconds.count() % 1000);
|
std::string micro_seconds_str = std::to_string(milli_seconds.count() % 1000);
|
||||||
while (micro_seconds_str.size() < 3) {
|
while (micro_seconds_str.size() < 3) {
|
||||||
micro_seconds_str = "0" + micro_seconds_str;
|
micro_seconds_str = "0" + micro_seconds_str;
|
||||||
@@ -168,13 +263,33 @@ void LogWrite(int level, const char* file, int line, const char* format, ...) {
|
|||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
fprintf(stderr, "%s, %s, %7s, %25s, %4d, ",
|
if (g_colorlogtostderr && g_terminal_has_color) {
|
||||||
timestamp.c_str(), kLevelNames[level], thread_id.c_str(),
|
if (level < WEBCC_WARN) {
|
||||||
file, line);
|
fprintf(stderr, "%s%s%s, %s, %7s, %25s, %4d, %s",
|
||||||
|
TerminalReset(), TerminalDim(),
|
||||||
|
timestamp.c_str(), kLevelNames[level], thread_id.c_str(),
|
||||||
|
file, line,
|
||||||
|
level == WEBCC_INFO ? TerminalReset() : ""); // un-dim for INFO
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s%s%s, %s, %7s, %25s, %4d, ",
|
||||||
|
TerminalReset(),
|
||||||
|
level == WEBCC_WARN ? TerminalYellow() : TerminalRed(),
|
||||||
|
timestamp.c_str(), kLevelNames[level], thread_id.c_str(),
|
||||||
|
file, line);
|
||||||
|
}
|
||||||
|
|
||||||
vfprintf(stderr, format, args);
|
vfprintf(stderr, format, args);
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "%s\n", TerminalReset());
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "%s, %s, %7s, %25s, %4d, ",
|
||||||
|
timestamp.c_str(), kLevelNames[level], thread_id.c_str(),
|
||||||
|
file, line);
|
||||||
|
|
||||||
|
vfprintf(stderr, format, args);
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
if ((g_logger.modes & LOG_FLUSH) != 0) {
|
if ((g_logger.modes & LOG_FLUSH) != 0) {
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|||||||
Reference in New Issue
Block a user