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