Add file log support

master
Adam Gu 7 years ago
parent 44271eb2cc
commit 7280b09f10

@ -68,24 +68,6 @@ if(WIN32)
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
endif()
# Group sources by dir.
# Usage: source_group_by_dir(SRCS)
macro(GROUP_SOURCES_BY_DIR source_files)
set(sgbd_cur_dir ${CMAKE_CURRENT_BINARY_DIR})
foreach(sgbd_file ${${source_files}})
#message("sgbd_fpath=${sgbd_fpath}")
string(REGEX REPLACE ${sgbd_cur_dir}/\(.*\) \\1 sgbd_fpath ${sgbd_file})
string(REGEX REPLACE "\(.*\)/.*" \\1 sgbd_group_name ${sgbd_fpath})
string(COMPARE EQUAL ${sgbd_fpath} ${sgbd_group_name} sgbd_nogroup)
string(REPLACE "/" "\\" sgbd_group_name ${sgbd_group_name})
if(sgbd_nogroup)
set(sgbd_group_name "\\")
endif()
#message("group name=${sgbd_group_name}")
source_group(${sgbd_group_name} FILES ${sgbd_file})
endforeach()
endmacro()
# C++ standard requirements.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

@ -40,7 +40,7 @@ void Test(boost::asio::io_context& ioc) {
}
int main() {
LOG_INIT(0);
LOG_INIT("", webcc::LOG_CONSOLE);
boost::asio::io_context ioc;

@ -28,7 +28,7 @@ void Test() {
}
int main() {
LOG_INIT(0);
LOG_INIT("", webcc::LOG_CONSOLE);
Test();
Test();

@ -101,7 +101,7 @@ int main(int argc, char* argv[]) {
return 1;
}
LOG_INIT(0);
LOG_INIT("", webcc::LOG_CONSOLE);
std::string host = argv[1];
std::string port = argv[2];

@ -160,7 +160,7 @@ int main(int argc, char* argv[]) {
return 1;
}
LOG_INIT(0);
LOG_INIT("", webcc::LOG_CONSOLE);
std::string host = argv[1];
std::string port = argv[2];

@ -21,7 +21,7 @@ int main(int argc, char* argv[]) {
return 1;
}
LOG_INIT(0);
LOG_INIT("", webcc::LOG_FILE | webcc::LOG_CONSOLE | webcc::LOG_OVERWRITE);
unsigned short port = std::atoi(argv[1]);

@ -1,9 +1,11 @@
#include <iostream>
#include "webcc/logger.h"
#include "calc_client.h"
int main() {
LOG_INIT(0);
LOG_INIT("", webcc::LOG_CONSOLE);
CalcClient calc;

@ -17,7 +17,7 @@ int main(int argc, char* argv[]) {
return 1;
}
LOG_INIT(0);
LOG_INIT("", webcc::LOG_CONSOLE);
unsigned short port = std::atoi(argv[1]);

@ -6,20 +6,41 @@
#include <chrono>
#include <cstdarg>
#include <ctime>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include "boost/filesystem.hpp"
namespace webcc {
struct Logger {
Logger(const std::string& path, int modes) : file(nullptr), modes(modes) {
if (!path.empty()) {
if ((modes & LOG_OVERWRITE) != 0) {
file = fopen(path.c_str(), "w+");
} else {
// Append to existing file.
file = fopen(path.c_str(), "a+");
}
}
}
~Logger() {
if (file != nullptr) {
fclose(file);
}
}
FILE* file;
int modes;
std::mutex mutex;
};
// Global logger.
static Logger g_logger{ 0 };
static std::shared_ptr<Logger> g_logger;
static std::thread::id g_main_thread_id;
@ -27,8 +48,28 @@ static const char* kLevelNames[] = {
"VERB", "INFO", "WARN", "ERRO", "FATA"
};
void LogInit(int modes) {
g_logger.modes = modes;
namespace bfs = boost::filesystem;
static bfs::path InitLogPath(const std::string& dir) {
if (dir.empty()) {
return bfs::current_path() / WEBCC_LOG_FILE;
}
bfs::path path = bfs::path(dir);
if (!bfs::exists(path) || !bfs::is_directory(path)) {
boost::system::error_code ec;
if (!bfs::create_directories(path, ec) || ec) {
return bfs::path();
}
}
path /= WEBCC_LOG_FILE;
return path;
}
void LogInit(const std::string& dir, int modes) {
bfs::path path = InitLogPath(dir);
g_logger.reset(new Logger(path.string(), modes));
// Suppose LogInit() is called from the main thread.
g_main_thread_id = std::this_thread::get_id();
@ -74,21 +115,44 @@ static std::string GetThreadID() {
void LogWrite(int level, const char* file, int line, const char* format, ...) {
assert(format != nullptr);
std::lock_guard<std::mutex> lock(g_logger.mutex);
va_list va_ptr_file;
va_list va_ptr_console;
va_start(va_ptr_file, format);
va_start(va_ptr_console, format);
fprintf(stderr, "%s, %s, %5s, %24s, %4d, ",
GetTimestamp().c_str(), kLevelNames[level], GetThreadID().c_str(),
file, line);
vfprintf(stderr, format, va_ptr_console);
fprintf(stderr, "\n");
if ((g_logger->modes & LOG_FILE) != 0 && g_logger->file != nullptr) {
std::lock_guard<std::mutex> lock(g_logger->mutex);
fprintf(g_logger->file, "%s, %s, %5s, %24s, %4d, ",
GetTimestamp().c_str(), kLevelNames[level], GetThreadID().c_str(),
file, line);
vfprintf(g_logger->file, format, va_ptr_console);
fprintf(g_logger->file, "\n");
if ((g_logger->modes & LOG_FLUSH) != 0) {
fflush(g_logger->file);
}
}
if ((g_logger->modes & LOG_CONSOLE) != 0) {
std::lock_guard<std::mutex> lock(g_logger->mutex);
fprintf(stderr, "%s, %s, %5s, %24s, %4d, ",
GetTimestamp().c_str(), kLevelNames[level], GetThreadID().c_str(),
file, line);
vfprintf(stderr, format, va_ptr_console);
fprintf(stderr, "\n");
if ((g_logger.modes & FLUSH) == FLUSH) {
fflush(stderr);
if ((g_logger->modes & LOG_FLUSH) != 0) {
fflush(stderr);
}
}
va_end(va_ptr_file);
va_end(va_ptr_console);
}

@ -6,6 +6,7 @@
#if WEBCC_ENABLE_LOG
#include <cstring> // for strrchr()
#include <string>
#define WEBCC_VERB 0
#define WEBCC_INFO 1
@ -18,13 +19,20 @@
#define WEBCC_LOG_LEVEL WEBCC_WARN
#endif
#define WEBCC_LOG_FILE "webcc.log"
namespace webcc {
enum LogMode {
FLUSH = 1,
LOG_FILE = 1, // Log to file.
LOG_CONSOLE = 2, // Log to console.
LOG_FLUSH = 4, // Flush on each log.
LOG_OVERWRITE = 8, // Overwrite any existing log file.
};
void LogInit(int modes);
// Initialize logger.
// If |dir| is empty, log file will be generated in current directory.
void LogInit(const std::string& dir, int modes);
void LogWrite(int level, const char* file, int line, const char* format, ...);
@ -32,7 +40,7 @@ void LogWrite(int level, const char* file, int line, const char* format, ...);
// Initialize the logger with a level.
// E.g., LOG_INIT(FLUSH)
#define LOG_INIT(modes) webcc::LogInit(modes);
#define LOG_INIT(dir, modes) webcc::LogInit(dir, modes);
#if (defined(WIN32) || defined(_WIN64))

Loading…
Cancel
Save