Add file log support
This commit is contained in:
@@ -68,24 +68,6 @@ if(WIN32)
|
|||||||
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
||||||
endif()
|
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.
|
# C++ standard requirements.
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ void Test(boost::asio::io_context& ioc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
boost::asio::io_context ioc;
|
boost::asio::io_context ioc;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ void Test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
Test();
|
Test();
|
||||||
Test();
|
Test();
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
std::string host = argv[1];
|
std::string host = argv[1];
|
||||||
std::string port = argv[2];
|
std::string port = argv[2];
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
std::string host = argv[1];
|
std::string host = argv[1];
|
||||||
std::string port = argv[2];
|
std::string port = argv[2];
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_FILE | webcc::LOG_CONSOLE | webcc::LOG_OVERWRITE);
|
||||||
|
|
||||||
unsigned short port = std::atoi(argv[1]);
|
unsigned short port = std::atoi(argv[1]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
#include "calc_client.h"
|
#include "calc_client.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
CalcClient calc;
|
CalcClient calc;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ int main(int argc, char* argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INIT(0);
|
LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
unsigned short port = std::atoi(argv[1]);
|
unsigned short port = std::atoi(argv[1]);
|
||||||
|
|
||||||
|
|||||||
+76
-12
@@ -6,20 +6,41 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include "boost/filesystem.hpp"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
struct Logger {
|
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;
|
int modes;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global logger.
|
// Global logger.
|
||||||
static Logger g_logger{ 0 };
|
static std::shared_ptr<Logger> g_logger;
|
||||||
|
|
||||||
static std::thread::id g_main_thread_id;
|
static std::thread::id g_main_thread_id;
|
||||||
|
|
||||||
@@ -27,8 +48,28 @@ static const char* kLevelNames[] = {
|
|||||||
"VERB", "INFO", "WARN", "ERRO", "FATA"
|
"VERB", "INFO", "WARN", "ERRO", "FATA"
|
||||||
};
|
};
|
||||||
|
|
||||||
void LogInit(int modes) {
|
namespace bfs = boost::filesystem;
|
||||||
g_logger.modes = modes;
|
|
||||||
|
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.
|
// Suppose LogInit() is called from the main thread.
|
||||||
g_main_thread_id = std::this_thread::get_id();
|
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, ...) {
|
void LogWrite(int level, const char* file, int line, const char* format, ...) {
|
||||||
assert(format != nullptr);
|
assert(format != nullptr);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(g_logger.mutex);
|
va_list va_ptr_file;
|
||||||
|
|
||||||
va_list va_ptr_console;
|
va_list va_ptr_console;
|
||||||
|
|
||||||
|
va_start(va_ptr_file, format);
|
||||||
va_start(va_ptr_console, format);
|
va_start(va_ptr_console, format);
|
||||||
|
|
||||||
fprintf(stderr, "%s, %s, %5s, %24s, %4d, ",
|
if ((g_logger->modes & LOG_FILE) != 0 && g_logger->file != nullptr) {
|
||||||
GetTimestamp().c_str(), kLevelNames[level], GetThreadID().c_str(),
|
std::lock_guard<std::mutex> lock(g_logger->mutex);
|
||||||
file, line);
|
|
||||||
vfprintf(stderr, format, va_ptr_console);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
|
|
||||||
if ((g_logger.modes & FLUSH) == FLUSH) {
|
fprintf(g_logger->file, "%s, %s, %5s, %24s, %4d, ",
|
||||||
fflush(stderr);
|
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 & LOG_FLUSH) != 0) {
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(va_ptr_file);
|
||||||
va_end(va_ptr_console);
|
va_end(va_ptr_console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-3
@@ -6,6 +6,7 @@
|
|||||||
#if WEBCC_ENABLE_LOG
|
#if WEBCC_ENABLE_LOG
|
||||||
|
|
||||||
#include <cstring> // for strrchr()
|
#include <cstring> // for strrchr()
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#define WEBCC_VERB 0
|
#define WEBCC_VERB 0
|
||||||
#define WEBCC_INFO 1
|
#define WEBCC_INFO 1
|
||||||
@@ -18,13 +19,20 @@
|
|||||||
#define WEBCC_LOG_LEVEL WEBCC_WARN
|
#define WEBCC_LOG_LEVEL WEBCC_WARN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WEBCC_LOG_FILE "webcc.log"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
enum LogMode {
|
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, ...);
|
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.
|
// Initialize the logger with a level.
|
||||||
// E.g., LOG_INIT(FLUSH)
|
// 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))
|
#if (defined(WIN32) || defined(_WIN64))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user