xref: /openbmc/bmcweb/http/logging.hpp (revision 04e438cbad66838724d78ce12f28aff1fb892a63)
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