#include "logger.hpp" #include "ostream_logger.hpp" #include "logger_syslog.hpp" #include "file_logger.hpp" #if defined(_WIN32) #include "win32_logger.hpp" #endif #if defined(ANDROID) #include "android_logger.hpp" #endif #include #include namespace llarp { #if defined(_WIN32) using Stream_t = Win32LogStream; #define _LOGSTREAM_INIT std::cout #else #if defined(ANDROID) using Stream_t = AndroidLogStream; #define _LOGSTREAM_INIT #else using Stream_t = OStreamLogStream; #define _LOGSTREAM_INIT true, std::cout #endif #endif LogType LogTypeFromString(const std::string& str) { if (str == "unknown") return LogType::Unknown; else if (str == "file") return LogType::File; else if (str == "syslog") return LogType::Syslog; return LogType::Unknown; } LogContext::LogContext() : logStream{std::make_unique(_LOGSTREAM_INIT)} {} LogContext& LogContext::Instance() { static LogContext ctx; return ctx; } void LogContext::DropToRuntimeLevel() { curLevel = runtimeLevel; } void LogContext::RevertRuntimeLevel() { curLevel = startupLevel; } log_timestamp::log_timestamp() : log_timestamp("%c %Z") {} log_timestamp::log_timestamp(const char* fmt) : format{fmt}, now{llarp::time_now_ms()}, delta{llarp::uptime()} {} void SetLogLevel(LogLevel lvl) { LogContext::Instance().curLevel = lvl; LogContext::Instance().runtimeLevel = lvl; } LogLevel GetLogLevel() { return LogContext::Instance().curLevel; } void LogContext::ImmediateFlush() { logStream->ImmediateFlush(); } void LogContext::Initialize( LogLevel level, LogType type, const std::string& file, const std::string& nickname, std::function io) { SetLogLevel(level); if (level == eLogTrace) LogTrace("Set log level to trace."); nodeName = nickname; FILE* logfile = nullptr; if (file == "stdout" or file == "-" or file.empty()) { logfile = stdout; } else if (type != LogType::Syslog) { logfile = ::fopen(file.c_str(), "a"); if (not logfile) { throw std::runtime_error( stringify("could not open logfile ", file, ", errno: ", strerror(errno))); } } switch (type) { case LogType::Unknown: // tolerate as fallback to LogType::File case LogType::File: if (logfile != stdout) { LogInfo("Switching logger to file ", file); std::cout << std::flush; LogContext::Instance().logStream = std::make_unique(io, logfile, 100ms, true); } else { LogInfo("Logger remains stdout"); } break; case LogType::Syslog: #if defined(_WIN32) throw std::runtime_error("syslog not supported on win32"); #else LogContext::Instance().logStream = std::make_unique(); #endif break; } } LogSilencer::LogSilencer() : LogSilencer(LogContext::Instance()) {} LogSilencer::LogSilencer(LogContext& ctx) : parent(ctx), stream(std::move(ctx.logStream)) {} LogSilencer::~LogSilencer() { parent.logStream = std::move(stream); } } // namespace llarp