#pragma once #include #include "spdlog/spdlog.h" #ifdef WIN32 #include "spdlog/sinks/msvc_sink.h" #include "win32.h" #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #endif #include "utf8.h" namespace jlib{ static const char g_logger_name[] = "logger"; inline void init_logger(const std::string& file_name = "") { try { std::vector sinks; #ifdef WIN32 sinks.push_back(std::make_shared()); #endif sinks.push_back(std::make_shared()); sinks.push_back(std::make_shared( #ifdef WIN32 utf8::mbcs_to_u16(file_name + ".log") #else file_name + ".log" #endif , 23, 59)); auto combined_logger = std::make_shared(g_logger_name, begin(sinks), end(sinks)); combined_logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [tid %t] [%L] %v"); spdlog::register_logger(combined_logger); } catch (const spdlog::spdlog_ex& ex) { #ifdef WIN32 char msg[1024] = { 0 }; sprintf_s(msg, "Log initialization failed: %s\n", ex.what()); OutputDebugStringA(msg); #else std::cerr << "Log initialization failed: " << ex.what() << std::endl; #endif } } #define JLOG_INFO spdlog::get(g_logger_name)->info #define JLOG_WARN spdlog::get(g_logger_name)->warn #define JLOG_ERRO spdlog::get(g_logger_name)->error #define JLOG_CRTC spdlog::get(g_logger_name)->critical #ifdef _WIN32 #define JLOG_ALL(args, ...) spdlog::get(jlib::g_logger_name)->log(spdlog::level::off, args, __VA_ARGS__) #else #define JLOG_ALL(args...) spdlog::get(jlib::g_logger_name)->log(spdlog::level::off, args) #endif /* _WIN32 */ class range_log { private: std::string msg_; std::chrono::steady_clock::time_point begin_; public: range_log(const std::string& msg) : msg_(msg) { JLOG_INFO(msg_ + " in"); begin_ = std::chrono::steady_clock::now(); } range_log(const std::wstring& msg) : msg_() { msg_ = utf8::w2a(msg); JLOG_INFO(msg_ + " in"); begin_ = std::chrono::steady_clock::now(); } ~range_log() { auto diff = std::chrono::steady_clock::now() - begin_; auto msec = std::chrono::duration_cast(diff); JLOG_INFO("{} out, duration: {}(ms)", msg_, msec.count()); } }; #define AUTO_LOG_FUNCTION jlib::range_log __log_function_object__(__func__); static const int MAX_OUT_BUFF_LEN = 4096; inline void dump_hex(const void* buff, size_t buff_len) { size_t output_len = buff_len * 6 + 64; if (output_len > MAX_OUT_BUFF_LEN) { JLOG_ERRO("dump_hex, output_len {} > MAX_OUT_BUFF_LEN {}", output_len, MAX_OUT_BUFF_LEN); return; } char output[4096] = { 0 }; char c[128] = { 0 }; std::sprintf(c, "dump_hex: buff 0x%p, buff_len %zu\n", buff, buff_len); for (size_t i = 0; i < 16; i++) { char tmp[4]; std::sprintf(tmp, "%02zX ", i); std::strcat(c, tmp); } std::strcat(output, c); std::strcat(output, "\n"); for (size_t i = 0; i < buff_len; i++) { std::sprintf(c, "%02X ", reinterpret_cast(buff)[i]); std::strcat(output, c); if (i > 0 && (i + 1) % 16 == 0) { std::strcat(output, "\n"); } } JLOG_WARN(output); } inline void dump_asc(const void* buff, size_t buff_len) { size_t output_len = buff_len * 6 + 64; if (output_len > MAX_OUT_BUFF_LEN) { JLOG_ERRO("dump_asc, output_len {} > MAX_OUT_BUFF_LEN {}", output_len, MAX_OUT_BUFF_LEN); return; } char output[4096] = { 0 }; char c[128] = { 0 }; std::sprintf(c, "dump_asc: buff 0x%p, buff_len %zu\n", buff, buff_len); for (size_t i = 0; i < 16; i++) { char tmp[4]; std::sprintf(tmp, "%02zX ", i); std::strcat(c, tmp); } std::strcat(output, c); std::strcat(output, "\n"); for (size_t i = 0; i < buff_len; i++) { std::sprintf(c, "%c ", reinterpret_cast(buff)[i]); std::strcat(output, c); if (i > 0 && (i + 1) % 16 == 0) { std::strcat(output, "\n"); } } JLOG_WARN(output); } #define JLOG_HEX(b, l) jlib::dump_hex(b, l) #define JLOG_ASC(b, l) jlib::dump_asc(b, l) }