1*04e438cbSEd Tanous #pragma once 2*04e438cbSEd Tanous 3*04e438cbSEd Tanous #include <cstdio> 4*04e438cbSEd Tanous #include <cstdlib> 5*04e438cbSEd Tanous #include <ctime> 6*04e438cbSEd Tanous #include <filesystem> 7*04e438cbSEd Tanous #include <iostream> 8*04e438cbSEd Tanous #include <sstream> 9*04e438cbSEd Tanous #include <string> 10*04e438cbSEd Tanous 11*04e438cbSEd Tanous namespace crow 12*04e438cbSEd Tanous { 13*04e438cbSEd Tanous enum class LogLevel 14*04e438cbSEd Tanous { 15*04e438cbSEd Tanous Debug = 0, 16*04e438cbSEd Tanous Info, 17*04e438cbSEd Tanous Warning, 18*04e438cbSEd Tanous Error, 19*04e438cbSEd Tanous Critical, 20*04e438cbSEd Tanous }; 21*04e438cbSEd Tanous 22*04e438cbSEd Tanous class Logger 23*04e438cbSEd Tanous { 24*04e438cbSEd Tanous private: 25*04e438cbSEd Tanous // 26*04e438cbSEd Tanous static std::string timestamp() 27*04e438cbSEd Tanous { 28*04e438cbSEd Tanous std::string date; 29*04e438cbSEd Tanous date.resize(32, '\0'); 30*04e438cbSEd Tanous time_t t = time(nullptr); 31*04e438cbSEd Tanous 32*04e438cbSEd Tanous tm myTm{}; 33*04e438cbSEd Tanous 34*04e438cbSEd Tanous gmtime_r(&t, &myTm); 35*04e438cbSEd Tanous 36*04e438cbSEd Tanous size_t sz = 37*04e438cbSEd Tanous strftime(date.data(), date.size(), "%Y-%m-%d %H:%M:%S", &myTm); 38*04e438cbSEd Tanous date.resize(sz); 39*04e438cbSEd Tanous return date; 40*04e438cbSEd Tanous } 41*04e438cbSEd Tanous 42*04e438cbSEd Tanous public: 43*04e438cbSEd Tanous Logger([[maybe_unused]] const std::string& prefix, 44*04e438cbSEd Tanous [[maybe_unused]] const std::string& filename, 45*04e438cbSEd Tanous [[maybe_unused]] const size_t line, LogLevel levelIn) : 46*04e438cbSEd Tanous level(levelIn) 47*04e438cbSEd Tanous { 48*04e438cbSEd Tanous #ifdef BMCWEB_ENABLE_LOGGING 49*04e438cbSEd Tanous stringstream << "(" << timestamp() << ") [" << prefix << " " 50*04e438cbSEd Tanous << std::filesystem::path(filename).filename() << ":" 51*04e438cbSEd Tanous << line << "] "; 52*04e438cbSEd Tanous #endif 53*04e438cbSEd Tanous } 54*04e438cbSEd Tanous ~Logger() 55*04e438cbSEd Tanous { 56*04e438cbSEd Tanous if (level >= getCurrentLogLevel()) 57*04e438cbSEd Tanous { 58*04e438cbSEd Tanous #ifdef BMCWEB_ENABLE_LOGGING 59*04e438cbSEd Tanous stringstream << std::endl; 60*04e438cbSEd Tanous std::cerr << stringstream.str(); 61*04e438cbSEd Tanous #endif 62*04e438cbSEd Tanous } 63*04e438cbSEd Tanous } 64*04e438cbSEd Tanous 65*04e438cbSEd Tanous // 66*04e438cbSEd Tanous template <typename T> 67*04e438cbSEd Tanous Logger& operator<<([[maybe_unused]] T const& value) 68*04e438cbSEd Tanous { 69*04e438cbSEd Tanous if (level >= getCurrentLogLevel()) 70*04e438cbSEd Tanous { 71*04e438cbSEd Tanous #ifdef BMCWEB_ENABLE_LOGGING 72*04e438cbSEd Tanous stringstream << value; 73*04e438cbSEd Tanous #endif 74*04e438cbSEd Tanous } 75*04e438cbSEd Tanous return *this; 76*04e438cbSEd Tanous } 77*04e438cbSEd Tanous 78*04e438cbSEd Tanous // 79*04e438cbSEd Tanous static void setLogLevel(LogLevel level) 80*04e438cbSEd Tanous { 81*04e438cbSEd Tanous getLogLevelRef() = level; 82*04e438cbSEd Tanous } 83*04e438cbSEd Tanous 84*04e438cbSEd Tanous static LogLevel getCurrentLogLevel() 85*04e438cbSEd Tanous { 86*04e438cbSEd Tanous return getLogLevelRef(); 87*04e438cbSEd Tanous } 88*04e438cbSEd Tanous 89*04e438cbSEd Tanous private: 90*04e438cbSEd Tanous // 91*04e438cbSEd Tanous static LogLevel& getLogLevelRef() 92*04e438cbSEd Tanous { 93*04e438cbSEd Tanous static auto currentLevel = static_cast<LogLevel>(1); 94*04e438cbSEd Tanous return currentLevel; 95*04e438cbSEd Tanous } 96*04e438cbSEd Tanous 97*04e438cbSEd Tanous // 98*04e438cbSEd Tanous std::ostringstream stringstream; 99*04e438cbSEd Tanous LogLevel level; 100*04e438cbSEd Tanous }; 101*04e438cbSEd Tanous } // namespace crow 102*04e438cbSEd Tanous 103*04e438cbSEd Tanous #define BMCWEB_LOG_CRITICAL \ 104*04e438cbSEd Tanous if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Critical) \ 105*04e438cbSEd Tanous crow::Logger("CRITICAL", __FILE__, __LINE__, crow::LogLevel::Critical) 106*04e438cbSEd Tanous #define BMCWEB_LOG_ERROR \ 107*04e438cbSEd Tanous if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Error) \ 108*04e438cbSEd Tanous crow::Logger("ERROR", __FILE__, __LINE__, crow::LogLevel::Error) 109*04e438cbSEd Tanous #define BMCWEB_LOG_WARNING \ 110*04e438cbSEd Tanous if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Warning) \ 111*04e438cbSEd Tanous crow::Logger("WARNING", __FILE__, __LINE__, crow::LogLevel::Warning) 112*04e438cbSEd Tanous #define BMCWEB_LOG_INFO \ 113*04e438cbSEd Tanous if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Info) \ 114*04e438cbSEd Tanous crow::Logger("INFO", __FILE__, __LINE__, crow::LogLevel::Info) 115*04e438cbSEd Tanous #define BMCWEB_LOG_DEBUG \ 116*04e438cbSEd Tanous if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Debug) \ 117*04e438cbSEd Tanous crow::Logger("DEBUG", __FILE__, __LINE__, crow::LogLevel::Debug) 118