1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "base/logger.hpp"
4 #include "base/logger-ti.cpp"
5 #include "base/application.hpp"
6 #include "base/streamlogger.hpp"
7 #include "base/configtype.hpp"
8 #include "base/utility.hpp"
9 #include "base/objectlock.hpp"
10 #include "base/context.hpp"
11 #include "base/scriptglobal.hpp"
14 using namespace icinga;
16 template Log& Log::operator<<(const Value&);
17 template Log& Log::operator<<(const String&);
18 template Log& Log::operator<<(const std::string&);
19 template Log& Log::operator<<(const bool&);
20 template Log& Log::operator<<(const unsigned int&);
21 template Log& Log::operator<<(const int&);
22 template Log& Log::operator<<(const unsigned long&);
23 template Log& Log::operator<<(const long&);
24 template Log& Log::operator<<(const double&);
26 REGISTER_TYPE(Logger);
28 std::set<Logger::Ptr> Logger::m_Loggers;
29 boost::mutex Logger::m_Mutex;
30 bool Logger::m_ConsoleLogEnabled = true;
31 bool Logger::m_TimestampEnabled = true;
32 LogSeverity Logger::m_ConsoleLogSeverity = LogInformation;
34 INITIALIZE_ONCE([]() {
35 ScriptGlobal::Set("System.LogDebug", LogDebug, true);
36 ScriptGlobal::Set("System.LogNotice", LogNotice, true);
37 ScriptGlobal::Set("System.LogInformation", LogInformation, true);
38 ScriptGlobal::Set("System.LogWarning", LogWarning, true);
39 ScriptGlobal::Set("System.LogCritical", LogCritical, true);
43 * Constructor for the Logger class.
45 void Logger::Start(bool runtimeCreated)
47 ObjectImpl<Logger>::Start(runtimeCreated);
49 boost::mutex::scoped_lock lock(m_Mutex);
50 m_Loggers.insert(this);
53 void Logger::Stop(bool runtimeRemoved)
56 boost::mutex::scoped_lock lock(m_Mutex);
57 m_Loggers.erase(this);
60 ObjectImpl<Logger>::Stop(runtimeRemoved);
63 std::set<Logger::Ptr> Logger::GetLoggers()
65 boost::mutex::scoped_lock lock(m_Mutex);
70 * Retrieves the minimum severity for this logger.
72 * @returns The minimum severity.
74 LogSeverity Logger::GetMinSeverity() const
76 String severity = GetSeverity();
77 if (severity.IsEmpty())
78 return LogInformation;
80 LogSeverity ls = LogInformation;
83 ls = Logger::StringToSeverity(severity);
84 } catch (const std::exception&) { /* use the default level */ }
91 * Converts a severity enum value to a string.
93 * @param severity The severity value.
95 String Logger::SeverityToString(LogSeverity severity)
103 return "information";
109 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid severity."));
114 * Converts a string to a severity enum value.
116 * @param severity The severity.
118 LogSeverity Logger::StringToSeverity(const String& severity)
120 if (severity == "debug")
122 else if (severity == "notice")
124 else if (severity == "information")
125 return LogInformation;
126 else if (severity == "warning")
128 else if (severity == "critical")
131 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid severity: " + severity));
134 void Logger::DisableConsoleLog()
136 m_ConsoleLogEnabled = false;
139 void Logger::EnableConsoleLog()
141 m_ConsoleLogEnabled = true;
144 bool Logger::IsConsoleLogEnabled()
146 return m_ConsoleLogEnabled;
149 void Logger::SetConsoleLogSeverity(LogSeverity logSeverity)
151 m_ConsoleLogSeverity = logSeverity;
154 LogSeverity Logger::GetConsoleLogSeverity()
156 return m_ConsoleLogSeverity;
159 void Logger::DisableTimestamp()
161 m_TimestampEnabled = false;
164 void Logger::EnableTimestamp()
166 m_TimestampEnabled = true;
169 bool Logger::IsTimestampEnabled()
171 return m_TimestampEnabled;
174 void Logger::ValidateSeverity(const Lazy<String>& lvalue, const ValidationUtils& utils)
176 ObjectImpl<Logger>::ValidateSeverity(lvalue, utils);
179 StringToSeverity(lvalue());
181 BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + lvalue()));
185 Log::Log(LogSeverity severity, String facility, const String& message)
186 : m_Severity(severity), m_Facility(std::move(facility))
191 Log::Log(LogSeverity severity, String facility)
192 : m_Severity(severity), m_Facility(std::move(facility))
196 * Writes the message to the application's log.
201 entry.Timestamp = Utility::GetTime();
202 entry.Severity = m_Severity;
203 entry.Facility = m_Facility;
204 entry.Message = m_Buffer.str();
206 if (m_Severity >= LogWarning) {
207 ContextTrace context;
209 if (context.GetLength() > 0) {
210 std::ostringstream trace;
212 entry.Message += "\nContext:" + trace.str();
216 for (const Logger::Ptr& logger : Logger::GetLoggers()) {
217 ObjectLock llock(logger);
219 if (!logger->IsActive())
222 if (entry.Severity >= logger->GetMinSeverity())
223 logger->ProcessLogEntry(entry);
225 #ifdef I2_DEBUG /* I2_DEBUG */
226 /* Always flush, don't depend on the timer. Enable this for development sprints. */
228 #endif /* I2_DEBUG */
231 if (Logger::IsConsoleLogEnabled() && entry.Severity >= Logger::GetConsoleLogSeverity()) {
232 StreamLogger::ProcessLogEntry(std::cout, entry);
234 /* "Console" might be a pipe/socket (systemd, daemontools, docker, ...),
235 * then cout will not flush lines automatically. */
236 std::cout << std::flush;
240 Log& Log::operator<<(const char *val)