blob: 368548f9c02691737ced77c86800ae45cd13413c [file] [log] [blame]
Ed Tanous7045c8d2017-04-03 10:04:37 -07001#pragma once
2
Myung Bae662aa6e2023-01-10 14:20:28 -06003#include "bmcweb_config.h"
4
5#include <algorithm>
6#include <array>
Ed Tanous4d92cbf2017-06-22 15:41:02 -07007#include <cstdio>
8#include <cstdlib>
9#include <ctime>
James Feista0dba0f2019-07-08 10:26:14 -070010#include <filesystem>
Ed Tanous4d92cbf2017-06-22 15:41:02 -070011#include <iostream>
12#include <sstream>
Ed Tanous1e439872018-05-18 11:48:52 -070013#include <string>
Myung Bae662aa6e2023-01-10 14:20:28 -060014#include <string_view>
Ed Tanous4d92cbf2017-06-22 15:41:02 -070015
Ed Tanous1abe55e2018-09-05 08:30:59 -070016namespace crow
17{
18enum class LogLevel
19{
Myung Bae662aa6e2023-01-10 14:20:28 -060020 Disabled = 0,
21 Debug,
Ed Tanous1abe55e2018-09-05 08:30:59 -070022 Info,
23 Warning,
24 Error,
25 Critical,
Ed Tanous1e439872018-05-18 11:48:52 -070026};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070027
Myung Bae662aa6e2023-01-10 14:20:28 -060028// Mapping of the external loglvl name to internal loglvl
29constexpr std::array<std::pair<std::string_view, crow::LogLevel>, 7>
30 mapLogLevelFromName{{{"disabled", crow::LogLevel::Disabled},
31 {"enabled", crow::LogLevel::Debug},
32 {"debug", crow::LogLevel::Debug},
33 {"info", crow::LogLevel::Info},
34 {"warning", crow::LogLevel::Warning},
35 {"error", crow::LogLevel::Error},
36 {"critical", crow::LogLevel::Critical}}};
37
38constexpr crow::LogLevel getLogLevelFromName(std::string_view name)
39{
40 const auto* iter =
41 std::find_if(begin(mapLogLevelFromName), end(mapLogLevelFromName),
42 [&name](const auto& v) { return v.first == name; });
43 if (iter != end(mapLogLevelFromName))
44 {
45 return iter->second;
46 }
47 return crow::LogLevel::Disabled;
48}
49
50// configured bmcweb LogLevel
51constexpr crow::LogLevel bmcwebCurrentLoggingLevel =
52 getLogLevelFromName(bmcwebLoggingLevel);
53
Ed Tanouseb643c22020-10-02 14:51:22 -070054class Logger
Ed Tanous1abe55e2018-09-05 08:30:59 -070055{
56 private:
57 //
58 static std::string timestamp()
59 {
Ed Tanous271584a2019-07-09 16:24:22 -070060 std::string date;
61 date.resize(32, '\0');
Ed Tanous99131cd2019-10-24 11:12:47 -070062 time_t t = time(nullptr);
Ed Tanous4d92cbf2017-06-22 15:41:02 -070063
Ed Tanous1abe55e2018-09-05 08:30:59 -070064 tm myTm{};
Ed Tanous4d92cbf2017-06-22 15:41:02 -070065
Ed Tanous1abe55e2018-09-05 08:30:59 -070066 gmtime_r(&t, &myTm);
Ed Tanous4d92cbf2017-06-22 15:41:02 -070067
Patrick Williams89492a12023-05-10 07:51:34 -050068 size_t sz = strftime(date.data(), date.size(), "%Y-%m-%d %H:%M:%S",
69 &myTm);
Ed Tanous271584a2019-07-09 16:24:22 -070070 date.resize(sz);
71 return date;
Ed Tanous1e439872018-05-18 11:48:52 -070072 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070073
Ed Tanous1abe55e2018-09-05 08:30:59 -070074 public:
Ed Tanouseb643c22020-10-02 14:51:22 -070075 Logger([[maybe_unused]] const std::string& prefix,
Ed Tanouscb13a392020-07-25 19:02:03 +000076 [[maybe_unused]] const std::string& filename,
Myung Bae662aa6e2023-01-10 14:20:28 -060077 [[maybe_unused]] const size_t line)
Ed Tanous1abe55e2018-09-05 08:30:59 -070078 {
James Feista0dba0f2019-07-08 10:26:14 -070079 stringstream << "(" << timestamp() << ") [" << prefix << " "
80 << std::filesystem::path(filename).filename() << ":"
81 << line << "] ";
Ed Tanous1abe55e2018-09-05 08:30:59 -070082 }
Ed Tanouseb643c22020-10-02 14:51:22 -070083 ~Logger()
Ed Tanous1abe55e2018-09-05 08:30:59 -070084 {
Myung Bae662aa6e2023-01-10 14:20:28 -060085 stringstream << std::endl;
86 std::cerr << stringstream.str();
Ed Tanous1abe55e2018-09-05 08:30:59 -070087 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -070088
Ed Tanousecd6a3a2022-01-07 09:18:40 -080089 Logger(const Logger&) = delete;
90 Logger(Logger&&) = delete;
91 Logger& operator=(const Logger&) = delete;
92 Logger& operator=(const Logger&&) = delete;
93
Ed Tanous1abe55e2018-09-05 08:30:59 -070094 //
Gunnar Mills1214b7e2020-06-04 10:11:30 -050095 template <typename T>
Patrick Williams89492a12023-05-10 07:51:34 -050096 Logger& operator<<([[maybe_unused]] const T& value)
Ed Tanous1abe55e2018-09-05 08:30:59 -070097 {
Myung Bae662aa6e2023-01-10 14:20:28 -060098 // Somewhere in the code we're implicitly casting an array to a
99 // pointer in logging code. It's non-trivial to find,
100 // so disable the check here for now
101 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
102 stringstream << value;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700103 return *this;
104 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700105
Myung Bae662aa6e2023-01-10 14:20:28 -0600106 constexpr static LogLevel getCurrentLogLevel()
Ed Tanous1abe55e2018-09-05 08:30:59 -0700107 {
Myung Bae662aa6e2023-01-10 14:20:28 -0600108 return bmcwebCurrentLoggingLevel;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700109 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700110
Myung Bae662aa6e2023-01-10 14:20:28 -0600111 constexpr static bool isLoggingEnabled()
Ed Tanous1abe55e2018-09-05 08:30:59 -0700112 {
Myung Bae662aa6e2023-01-10 14:20:28 -0600113 return getCurrentLogLevel() >= crow::LogLevel::Debug;
114 }
115
116 constexpr static bool checkLoggingLevel(const LogLevel level)
117 {
118 return isLoggingEnabled() && (getCurrentLogLevel() <= level);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700119 }
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700120
Ed Tanous1abe55e2018-09-05 08:30:59 -0700121 private:
122 //
Ed Tanous1abe55e2018-09-05 08:30:59 -0700123 std::ostringstream stringstream;
Ed Tanous1e439872018-05-18 11:48:52 -0700124};
Ed Tanous1abe55e2018-09-05 08:30:59 -0700125} // namespace crow
Ed Tanous4d92cbf2017-06-22 15:41:02 -0700126
Patrick Williamseb8a3992023-05-12 09:57:16 -0500127// Disable clang-tidy warnings about unused macros.
128// NOLINTBEGIN(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)
129
Ed Tanous600d2392022-01-07 09:32:03 -0800130// The logging functions currently use macros. Now that we have c++20, ideally
131// they'd use source_location with fixed functions, but for the moment, disable
132// the check.
Ed Tanous1abe55e2018-09-05 08:30:59 -0700133#define BMCWEB_LOG_CRITICAL \
Myung Bae662aa6e2023-01-10 14:20:28 -0600134 if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Critical)) \
135 crow::Logger("CRITICAL", __FILE__, __LINE__)
Ed Tanous600d2392022-01-07 09:32:03 -0800136
Ed Tanous1abe55e2018-09-05 08:30:59 -0700137#define BMCWEB_LOG_ERROR \
Myung Bae662aa6e2023-01-10 14:20:28 -0600138 if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Error)) \
139 crow::Logger("ERROR", __FILE__, __LINE__)
Ed Tanous600d2392022-01-07 09:32:03 -0800140
Ed Tanous1abe55e2018-09-05 08:30:59 -0700141#define BMCWEB_LOG_WARNING \
Myung Bae662aa6e2023-01-10 14:20:28 -0600142 if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Warning)) \
143 crow::Logger("WARNING", __FILE__, __LINE__)
Ed Tanous600d2392022-01-07 09:32:03 -0800144
Ed Tanous1abe55e2018-09-05 08:30:59 -0700145#define BMCWEB_LOG_INFO \
Myung Bae662aa6e2023-01-10 14:20:28 -0600146 if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Info)) \
147 crow::Logger("INFO", __FILE__, __LINE__)
Ed Tanous600d2392022-01-07 09:32:03 -0800148
Ed Tanous1abe55e2018-09-05 08:30:59 -0700149#define BMCWEB_LOG_DEBUG \
Myung Bae662aa6e2023-01-10 14:20:28 -0600150 if constexpr (crow::Logger::checkLoggingLevel(crow::LogLevel::Debug)) \
151 crow::Logger("DEBUG", __FILE__, __LINE__)
Patrick Williamseb8a3992023-05-12 09:57:16 -0500152
153// NOLINTEND(cppcoreguidelines-macro-usage, clang-diagnostic-unused-macros)