blob: 5f268f4913bd6b1995dfbfb53c604834549fda79 [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Ed Tanous4d92cbf2017-06-22 15:41:02 -07003#include <cstdio>
4#include <cstdlib>
5#include <ctime>
James Feista0dba0f2019-07-08 10:26:14 -07006#include <filesystem>
Ed Tanous4d92cbf2017-06-22 15:41:02 -07007#include <iostream>
8#include <sstream>
Ed Tanous1e439872018-05-18 11:48:52 -07009#include <string>
Ed Tanous4d92cbf2017-06-22 15:41:02 -070010
Ed Tanous1abe55e2018-09-05 08:30:59 -070011namespace crow
12{
13enum class LogLevel
14{
Ed Tanous1abe55e2018-09-05 08:30:59 -070015 Debug = 0,
16 Info,
17 Warning,
18 Error,
19 Critical,
Ed Tanous1e439872018-05-18 11:48:52 -070020};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070021
Ed Tanouseb643c22020-10-02 14:51:22 -070022class Logger
Ed Tanous1abe55e2018-09-05 08:30:59 -070023{
24 private:
25 //
26 static std::string timestamp()
27 {
Ed Tanous271584a2019-07-09 16:24:22 -070028 std::string date;
29 date.resize(32, '\0');
Ed Tanous99131cd2019-10-24 11:12:47 -070030 time_t t = time(nullptr);
Ed Tanous4d92cbf2017-06-22 15:41:02 -070031
Ed Tanous1abe55e2018-09-05 08:30:59 -070032 tm myTm{};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070033
Ed Tanous1abe55e2018-09-05 08:30:59 -070034 gmtime_r(&t, &myTm);
Ed Tanous4d92cbf2017-06-22 15:41:02 -070035
Ed Tanous271584a2019-07-09 16:24:22 -070036 size_t sz =
37 strftime(date.data(), date.size(), "%Y-%m-%d %H:%M:%S", &myTm);
38 date.resize(sz);
39 return date;
Ed Tanous1e439872018-05-18 11:48:52 -070040 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070041
Ed Tanous1abe55e2018-09-05 08:30:59 -070042 public:
Ed Tanouseb643c22020-10-02 14:51:22 -070043 Logger([[maybe_unused]] const std::string& prefix,
Ed Tanouscb13a392020-07-25 19:02:03 +000044 [[maybe_unused]] const std::string& filename,
45 [[maybe_unused]] const size_t line, LogLevel levelIn) :
Ed Tanous271584a2019-07-09 16:24:22 -070046 level(levelIn)
Ed Tanous1abe55e2018-09-05 08:30:59 -070047 {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070048#ifdef BMCWEB_ENABLE_LOGGING
James Feista0dba0f2019-07-08 10:26:14 -070049 stringstream << "(" << timestamp() << ") [" << prefix << " "
50 << std::filesystem::path(filename).filename() << ":"
51 << line << "] ";
Ed Tanous1e439872018-05-18 11:48:52 -070052#endif
Ed Tanous1abe55e2018-09-05 08:30:59 -070053 }
Ed Tanouseb643c22020-10-02 14:51:22 -070054 ~Logger()
Ed Tanous1abe55e2018-09-05 08:30:59 -070055 {
Ed Tanouseb643c22020-10-02 14:51:22 -070056 if (level >= getCurrentLogLevel())
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 {
Ed Tanous43b761d2019-02-13 20:10:56 -080058#ifdef BMCWEB_ENABLE_LOGGING
Ed Tanous1abe55e2018-09-05 08:30:59 -070059 stringstream << std::endl;
Ed Tanous271584a2019-07-09 16:24:22 -070060 std::cerr << stringstream.str();
Ed Tanous1abe55e2018-09-05 08:30:59 -070061#endif
Ed Tanous43b761d2019-02-13 20:10:56 -080062 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070063 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070064
Ed Tanousecd6a3a2022-01-07 09:18:40 -080065 Logger(const Logger&) = delete;
66 Logger(Logger&&) = delete;
67 Logger& operator=(const Logger&) = delete;
68 Logger& operator=(const Logger&&) = delete;
69
Ed Tanous1abe55e2018-09-05 08:30:59 -070070 //
Gunnar Mills1214b7e2020-06-04 10:11:30 -050071 template <typename T>
Ed Tanouseb643c22020-10-02 14:51:22 -070072 Logger& operator<<([[maybe_unused]] T const& value)
Ed Tanous1abe55e2018-09-05 08:30:59 -070073 {
Ed Tanouseb643c22020-10-02 14:51:22 -070074 if (level >= getCurrentLogLevel())
Ed Tanous1abe55e2018-09-05 08:30:59 -070075 {
Ed Tanous43b761d2019-02-13 20:10:56 -080076#ifdef BMCWEB_ENABLE_LOGGING
Ed Tanous9b6ffca2022-01-07 09:33:43 -080077 // Somewhere in the code we're implicitly casting an array to a
78 // pointer in logging code. It's non-trivial to find, so disable
79 // the check here for now
80 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
Ed Tanous1abe55e2018-09-05 08:30:59 -070081 stringstream << value;
Ed Tanous1abe55e2018-09-05 08:30:59 -070082#endif
Ed Tanous43b761d2019-02-13 20:10:56 -080083 }
Ed Tanous1abe55e2018-09-05 08:30:59 -070084 return *this;
85 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070086
Ed Tanous1abe55e2018-09-05 08:30:59 -070087 //
88 static void setLogLevel(LogLevel level)
89 {
90 getLogLevelRef() = level;
91 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070092
Ed Tanouseb643c22020-10-02 14:51:22 -070093 static LogLevel getCurrentLogLevel()
Ed Tanous1abe55e2018-09-05 08:30:59 -070094 {
95 return getLogLevelRef();
96 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070097
Ed Tanous1abe55e2018-09-05 08:30:59 -070098 private:
99 //
100 static LogLevel& getLogLevelRef()
101 {
102 static auto currentLevel = static_cast<LogLevel>(1);
103 return currentLevel;
104 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700105
106 //
107 std::ostringstream stringstream;
108 LogLevel level;
Ed Tanous1e439872018-05-18 11:48:52 -0700109};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700110} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700111
Ed Tanous600d2392022-01-07 09:32:03 -0800112// The logging functions currently use macros. Now that we have c++20, ideally
113// they'd use source_location with fixed functions, but for the moment, disable
114// the check.
115
116// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700117#define BMCWEB_LOG_CRITICAL \
Ed Tanouseb643c22020-10-02 14:51:22 -0700118 if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Critical) \
119 crow::Logger("CRITICAL", __FILE__, __LINE__, crow::LogLevel::Critical)
Ed Tanous600d2392022-01-07 09:32:03 -0800120
121// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700122#define BMCWEB_LOG_ERROR \
Ed Tanouseb643c22020-10-02 14:51:22 -0700123 if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Error) \
124 crow::Logger("ERROR", __FILE__, __LINE__, crow::LogLevel::Error)
Ed Tanous600d2392022-01-07 09:32:03 -0800125
126// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700127#define BMCWEB_LOG_WARNING \
Ed Tanouseb643c22020-10-02 14:51:22 -0700128 if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Warning) \
129 crow::Logger("WARNING", __FILE__, __LINE__, crow::LogLevel::Warning)
Ed Tanous600d2392022-01-07 09:32:03 -0800130
131// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700132#define BMCWEB_LOG_INFO \
Ed Tanouseb643c22020-10-02 14:51:22 -0700133 if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Info) \
134 crow::Logger("INFO", __FILE__, __LINE__, crow::LogLevel::Info)
Ed Tanous600d2392022-01-07 09:32:03 -0800135
136// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700137#define BMCWEB_LOG_DEBUG \
Ed Tanouseb643c22020-10-02 14:51:22 -0700138 if (crow::Logger::getCurrentLogLevel() <= crow::LogLevel::Debug) \
139 crow::Logger("DEBUG", __FILE__, __LINE__, crow::LogLevel::Debug)