#include #include #include #include #include #include #include std::shared_ptr g_server_logger; std::shared_ptr g_cracker_logger; #define SERVER_TRACE(...) g_server_logger->trace(__VA_ARGS__) #define SERVER_DEBUG(...) g_server_logger->debug(__VA_ARGS__) #define SERVER_INFO(...) g_server_logger->info(__VA_ARGS__) #define SERVER_WARN(...) g_server_logger->warn(__VA_ARGS__) #define SERVER_ERROR(...) g_server_logger->error(__VA_ARGS__) #define SERVER_CRITICAL(...) g_server_logger->critical(__VA_ARGS__) #define CRACKER_TRACE(...) g_cracker_logger->trace(__VA_ARGS__) #define CRACKER_DEBUG(...) g_cracker_logger->debug(__VA_ARGS__) #define CRACKER_INFO(...) g_cracker_logger->info(__VA_ARGS__) #define CRACKER_WARN(...) g_cracker_logger->warn(__VA_ARGS__) #define CRACKER_ERROR(...) g_cracker_logger->error(__VA_ARGS__) #define CRACKER_CRITICAL(...) g_cracker_logger->critical(__VA_ARGS__) void init_logger() { std::vector server_sinks { std::make_shared(), std::make_shared("server.log") }; std::vector cracker_sinks { std::make_shared(), std::make_shared("cracker.log") }; g_server_logger = std::make_shared("Server", server_sinks.begin(), server_sinks.end()); g_cracker_logger = std::make_shared("Cracker", cracker_sinks.begin(), cracker_sinks.end()); } void set_logger_level(std::shared_ptr& logger, spdlog::level::level_enum level) { logger->set_level(level); for (auto& child : logger->sinks()) { child->set_level(level); } } enum LOG_LEVEL { TRACE_LEVEL = 0, DEBUG_LEVEL, INFO_LEVEL, WARN_LEVEL, ERROR_LEVEL, FATAL_LEVEL, }; void run_server( int port, spdlog::level::level_enum log_level = spdlog::level::info, bool verbose = false ) { if (verbose) { set_logger_level(g_server_logger, spdlog::level::trace); } set_logger_level(g_cracker_logger, log_level); httplib::Server svr; svr.Post("/log", [](const httplib::Request& req, httplib::Response& res) { Json::Reader reader; Json::Value req_json; if (!reader.parse(req.body, req_json)) { SERVER_WARN("Invalid log request: {}", req.body); res.status = 400; return; } auto level_val = req_json["level"]; auto message_val = req_json["message"]; if (level_val.isNull() || message_val.isNull() || !level_val.isInt() || !message_val.isString()) { SERVER_WARN("Invalid log request: {}", req.body); res.status = 400; return; } auto level = level_val.asInt(); auto message = message_val.asString(); switch (level) { case TRACE_LEVEL: CRACKER_TRACE(message); break; case DEBUG_LEVEL: CRACKER_DEBUG(message); break; case INFO_LEVEL: CRACKER_INFO(message); break; case WARN_LEVEL: CRACKER_WARN(message); break; case ERROR_LEVEL: CRACKER_ERROR(message); break; case FATAL_LEVEL: CRACKER_CRITICAL(message); break; default: SERVER_WARN("Invalid log [level={}, message={}]", level, message); break; } res.status = 200; }); SERVER_INFO("Server started on port: {}", port); svr.listen("0.0.0.0", port); } int main(int argc, char* argv[]) { init_logger(); cxxopts::Options options("BlCrackLogger"); options.add_options() ("p,port", "Port to listen on", cxxopts::value()->default_value("7539")) ("l,level", "Cracker's log level", cxxopts::value()->default_value("info"), "log level (trace, debug, info, warn, error, fatal)") ("v,verbose", "Enable verbose output", cxxopts::value()->default_value("false")) ("h,help", "Print usage"); auto result = options.parse(argc, argv); if (result.count("help")) { std::cout << options.help() << std::endl; exit(0); } auto port = result["port"].as(); auto log_level_str = result["level"].as(); spdlog::level::level_enum log_level = spdlog::level::info; if (log_level_str == "trace") { log_level = spdlog::level::trace; } else if (log_level_str == "debug") { log_level = spdlog::level::debug; } else if (log_level_str == "info") { log_level = spdlog::level::info; } else if (log_level_str == "warn") { log_level = spdlog::level::warn; } else if (log_level_str == "error") { log_level = spdlog::level::err; } else if (log_level_str == "fatal") { log_level = spdlog::level::critical; } else { SERVER_WARN("Invalid log level: {}, using info level instead", log_level_str); } SERVER_INFO("Cracker's log level: {}", log_level_str); auto verbose = result["verbose"].as(); run_server(port, log_level, verbose); spdlog::shutdown(); return 0; }