1 /******************************************************************************
3 * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "base/logger.hpp"
21 #include "base/logger-ti.cpp"
22 #include "base/application.hpp"
23 #include "base/streamlogger.hpp"
24 #include "base/configtype.hpp"
25 #include "base/utility.hpp"
26 #include "base/objectlock.hpp"
27 #include "base/context.hpp"
28 #include "base/scriptglobal.hpp"
31 using namespace icinga;
33 template Log& Log::operator<<(const Value&);
34 template Log& Log::operator<<(const String&);
35 template Log& Log::operator<<(const std::string&);
36 template Log& Log::operator<<(const bool&);
37 template Log& Log::operator<<(const unsigned int&);
38 template Log& Log::operator<<(const int&);
39 template Log& Log::operator<<(const unsigned long&);
40 template Log& Log::operator<<(const long&);
41 template Log& Log::operator<<(const double&);
43 REGISTER_TYPE(Logger);
45 std::set<Logger::Ptr> Logger::m_Loggers;
46 boost::mutex Logger::m_Mutex;
47 bool Logger::m_ConsoleLogEnabled = true;
48 bool Logger::m_TimestampEnabled = true;
49 LogSeverity Logger::m_ConsoleLogSeverity = LogInformation;
51 INITIALIZE_ONCE([]() {
52 ScriptGlobal::Set("System.LogDebug", LogDebug, true);
53 ScriptGlobal::Set("System.LogNotice", LogNotice, true);
54 ScriptGlobal::Set("System.LogInformation", LogInformation, true);
55 ScriptGlobal::Set("System.LogWarning", LogWarning, true);
56 ScriptGlobal::Set("System.LogCritical", LogCritical, true);
60 * Constructor for the Logger class.
62 void Logger::Start(bool runtimeCreated)
64 ObjectImpl<Logger>::Start(runtimeCreated);
66 boost::mutex::scoped_lock lock(m_Mutex);
67 m_Loggers.insert(this);
70 void Logger::Stop(bool runtimeRemoved)
73 boost::mutex::scoped_lock lock(m_Mutex);
74 m_Loggers.erase(this);
77 ObjectImpl<Logger>::Stop(runtimeRemoved);
80 std::set<Logger::Ptr> Logger::GetLoggers()
82 boost::mutex::scoped_lock lock(m_Mutex);
87 * Retrieves the minimum severity for this logger.
89 * @returns The minimum severity.
91 LogSeverity Logger::GetMinSeverity() const
93 String severity = GetSeverity();
94 if (severity.IsEmpty())
95 return LogInformation;
97 LogSeverity ls = LogInformation;
100 ls = Logger::StringToSeverity(severity);
101 } catch (const std::exception&) { /* use the default level */ }
108 * Converts a severity enum value to a string.
110 * @param severity The severity value.
112 String Logger::SeverityToString(LogSeverity severity)
120 return "information";
126 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid severity."));
131 * Converts a string to a severity enum value.
133 * @param severity The severity.
135 LogSeverity Logger::StringToSeverity(const String& severity)
137 if (severity == "debug")
139 else if (severity == "notice")
141 else if (severity == "information")
142 return LogInformation;
143 else if (severity == "warning")
145 else if (severity == "critical")
148 BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid severity: " + severity));
151 void Logger::DisableConsoleLog()
153 m_ConsoleLogEnabled = false;
156 void Logger::EnableConsoleLog()
158 m_ConsoleLogEnabled = true;
161 bool Logger::IsConsoleLogEnabled()
163 return m_ConsoleLogEnabled;
166 void Logger::SetConsoleLogSeverity(LogSeverity logSeverity)
168 m_ConsoleLogSeverity = logSeverity;
171 LogSeverity Logger::GetConsoleLogSeverity()
173 return m_ConsoleLogSeverity;
176 void Logger::DisableTimestamp()
178 m_TimestampEnabled = false;
181 void Logger::EnableTimestamp()
183 m_TimestampEnabled = true;
186 bool Logger::IsTimestampEnabled()
188 return m_TimestampEnabled;
191 void Logger::ValidateSeverity(const Lazy<String>& lvalue, const ValidationUtils& utils)
193 ObjectImpl<Logger>::ValidateSeverity(lvalue, utils);
196 StringToSeverity(lvalue());
198 BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + lvalue()));
202 Log::Log(LogSeverity severity, String facility, const String& message)
203 : m_Severity(severity), m_Facility(std::move(facility))
208 Log::Log(LogSeverity severity, String facility)
209 : m_Severity(severity), m_Facility(std::move(facility))
213 * Writes the message to the application's log.
218 entry.Timestamp = Utility::GetTime();
219 entry.Severity = m_Severity;
220 entry.Facility = m_Facility;
221 entry.Message = m_Buffer.str();
223 if (m_Severity >= LogWarning) {
224 ContextTrace context;
226 if (context.GetLength() > 0) {
227 std::ostringstream trace;
229 entry.Message += "\nContext:" + trace.str();
233 for (const Logger::Ptr& logger : Logger::GetLoggers()) {
234 ObjectLock llock(logger);
236 if (!logger->IsActive())
239 if (entry.Severity >= logger->GetMinSeverity())
240 logger->ProcessLogEntry(entry);
242 #ifdef I2_DEBUG /* I2_DEBUG */
243 /* Always flush, don't depend on the timer. Enable this for development sprints. */
245 #endif /* I2_DEBUG */
248 if (Logger::IsConsoleLogEnabled() && entry.Severity >= Logger::GetConsoleLogSeverity()) {
249 StreamLogger::ProcessLogEntry(std::cout, entry);
251 /* "Console" might be a pipe/socket (systemd, daemontools, docker, ...),
252 * then cout will not flush lines automatically. */
253 std::cout << std::flush;
257 Log& Log::operator<<(const char *val)