blob: d85b52490c419b414f94b0ab85d56bec9d6974e9 [file] [log] [blame]
Junxiao Shi7d054272016-08-04 17:00:41 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
dmcoomese062a182017-06-12 11:10:31 -05002/*
Alexander Afanasyev354f3822017-03-27 15:26:41 -05003 * Copyright (c) 2013-2017 Regents of the University of California.
Junxiao Shi7d054272016-08-04 17:00:41 +00004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#ifndef NDN_UTIL_LOGGING_HPP
23#define NDN_UTIL_LOGGING_HPP
24
25#include "../common.hpp"
26
Alexander Afanasyeved1e99d2016-11-05 09:59:35 -060027#ifdef HAVE_NDN_CXX_CUSTOM_LOGGER
28#include "ndn-cxx-custom-logging.hpp"
29#else
30
Junxiao Shi7d054272016-08-04 17:00:41 +000031#include <boost/log/sinks.hpp>
32#include <mutex>
33#include <unordered_map>
34
35namespace ndn {
36namespace util {
37
38enum class LogLevel;
39class Logger;
40
41/** \brief controls the logging facility
42 *
43 * \note Public static methods are thread safe.
44 * Non-public methods are not guaranteed to be thread safe.
45 */
46class Logging : noncopyable
47{
48public:
49 /** \brief register a new logger
Junxiao Shi1fe7ce52016-08-08 05:48:02 +000050 * \note App should declare a new logger with \p NDN_LOG_INIT macro.
Junxiao Shi7d054272016-08-04 17:00:41 +000051 */
52 static void
53 addLogger(Logger& logger);
54
Alexander Afanasyev354f3822017-03-27 15:26:41 -050055 /** \brief get list of names of all registered loggers
56 */
57 static std::set<std::string>
58 getLoggerNames();
59
Junxiao Shi7d054272016-08-04 17:00:41 +000060 /** \brief set severity level
dmcoomese062a182017-06-12 11:10:31 -050061 * \param prefix logger prefix; this can be a specific logger name, a general prefix like ndn.a.*
62 * to apply a setting for all modules that contain this prefix, or "*" for all modules
Junxiao Shi7d054272016-08-04 17:00:41 +000063 * \param level minimum severity level
64 *
65 * Log messages are output only if its severity is greater than the set minimum severity level.
66 * Initial default severity level is \p LogLevel::NONE which enables FATAL only.
Junxiao Shi7d054272016-08-04 17:00:41 +000067 */
68 static void
dmcoomese062a182017-06-12 11:10:31 -050069 setLevel(const std::string& prefix, LogLevel level);
Junxiao Shi7d054272016-08-04 17:00:41 +000070
71 /** \brief set severity levels with a config string
72 * \param config colon-separate key=value pairs
73 * \throw std::invalid_argument config string is malformed
74 *
75 * \code
76 * Logging::setSeverityLevels("*=INFO:Face=DEBUG:NfdController=WARN");
77 * \endcode
78 * is equivalent to
79 * \code
80 * Logging::setSeverityLevel("*", LogLevel::INFO);
81 * Logging::setSeverityLevel("Face", LogLevel::DEBUG);
82 * Logging::setSeverityLevel("NfdController", LogLevel::WARN);
83 * \endcode
84 */
85 static void
86 setLevel(const std::string& config);
87
88 /** \brief set log destination
89 * \param os a stream for log output
90 *
91 * Initial destination is \p std::clog .
92 */
93 static void
94 setDestination(shared_ptr<std::ostream> os);
95
96 /** \brief set log destination
97 * \param os a stream for log output; caller must ensure this is valid
98 * until setDestination is invoked again or program exits
99 *
100 * This is equivalent to setDestination(shared_ptr<std::ostream>(&os, nullDeleter))
101 */
102 static void
103 setDestination(std::ostream& os);
104
105 /** \brief flush log backend
106 *
107 * This ensures log messages are written to the destination stream.
108 */
109 static void
110 flush();
111
112private:
113 Logging();
114
115 void
116 addLoggerImpl(Logger& logger);
117
Alexander Afanasyev354f3822017-03-27 15:26:41 -0500118 std::set<std::string>
dmcoomese062a182017-06-12 11:10:31 -0500119 getLoggerNamesImpl() const;
120
121 /**
122 * \brief finds the appropriate LogLevel for a logger
123 * \param moduleName name of logger
124 *
125 * This searches m_enabledLevel map to determine which LogLevel is appropriate for
126 * the incoming logger. It looks for the most specific prefix and broadens its
127 * prefix scope if a setting is not found. For example, when an incoming logger
128 * name is "ndn.a.b", it will search for "ndn.a.b" first. If this prefix is not
129 * contained in m_enabledLevel, it will search for "ndn.a.*", then "ndn.*", and
130 * finally "*". It defaults to INITIAL_DEFAULT_LEVEL if a matching prefix is not
131 * found.
132 */
133 LogLevel
134 findLevel(const std::string& moduleName) const;
Alexander Afanasyev354f3822017-03-27 15:26:41 -0500135
Junxiao Shi7d054272016-08-04 17:00:41 +0000136 void
dmcoomese062a182017-06-12 11:10:31 -0500137 setLevelImpl(const std::string& prefix, LogLevel level);
Junxiao Shi7d054272016-08-04 17:00:41 +0000138
139 void
140 setLevelImpl(const std::string& config);
141
142 void
143 setDestinationImpl(shared_ptr<std::ostream> os);
144
145 void
146 flushImpl();
147
148NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
149 static Logging&
150 get();
151
152#ifdef NDN_CXX_HAVE_TESTS
153 bool
154 removeLogger(Logger& logger);
155
Junxiao Shi7d054272016-08-04 17:00:41 +0000156 void
157 resetLevels();
158
159 shared_ptr<std::ostream>
dmcoomese062a182017-06-12 11:10:31 -0500160 getDestination() const;
161
162 void
163 setLevelImpl(const std::unordered_map<std::string, LogLevel>& prefixRules);
164
165 const std::unordered_map<std::string, LogLevel>&
166 getLevels() const;
Junxiao Shi7d054272016-08-04 17:00:41 +0000167#endif // NDN_CXX_HAVE_TESTS
168
169private:
dmcoomese062a182017-06-12 11:10:31 -0500170 mutable std::mutex m_mutex;
171 std::unordered_map<std::string, LogLevel> m_enabledLevel; ///< module prefix => minimum level
Junxiao Shi7d054272016-08-04 17:00:41 +0000172 std::unordered_multimap<std::string, Logger*> m_loggers; ///< moduleName => logger
173
174 shared_ptr<std::ostream> m_destination;
175 typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend> Sink;
176 boost::shared_ptr<Sink> m_sink;
177};
178
179inline void
180Logging::addLogger(Logger& logger)
181{
182 get().addLoggerImpl(logger);
183}
184
Alexander Afanasyev354f3822017-03-27 15:26:41 -0500185inline std::set<std::string>
186Logging::getLoggerNames()
187{
188 return get().getLoggerNamesImpl();
189}
190
Junxiao Shi7d054272016-08-04 17:00:41 +0000191inline void
dmcoomese062a182017-06-12 11:10:31 -0500192Logging::setLevel(const std::string& prefix, LogLevel level)
Junxiao Shi7d054272016-08-04 17:00:41 +0000193{
dmcoomese062a182017-06-12 11:10:31 -0500194 get().setLevelImpl(prefix, level);
Junxiao Shi7d054272016-08-04 17:00:41 +0000195}
196
197inline void
198Logging::setLevel(const std::string& config)
199{
200 get().setLevelImpl(config);
201}
202
203inline void
204Logging::setDestination(shared_ptr<std::ostream> os)
205{
dmcoomese062a182017-06-12 11:10:31 -0500206 get().setDestinationImpl(std::move(os));
Junxiao Shi7d054272016-08-04 17:00:41 +0000207}
208
209inline void
210Logging::flush()
211{
212 get().flushImpl();
213}
214
Junxiao Shi7d054272016-08-04 17:00:41 +0000215} // namespace util
216} // namespace ndn
217
Alexander Afanasyeved1e99d2016-11-05 09:59:35 -0600218#endif // HAVE_NDN_CXX_CUSTOM_LOGGER
219
Junxiao Shi7d054272016-08-04 17:00:41 +0000220#endif // NDN_UTIL_LOGGING_HPP