2 * Copyright 2004-present Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <folly/Conv.h>
19 #include <folly/CppAttributes.h>
20 #include <folly/Range.h>
21 #include <folly/Synchronized.h>
24 #include <unordered_map>
27 #include <folly/experimental/logging/LogName.h>
33 class LogHandlerFactory;
34 enum class LogLevel : uint32_t;
37 * LoggerDB stores the set of LogCategory objects.
42 * Get the main LoggerDB singleton.
44 static LoggerDB* get();
49 * Get the LogCategory for the specified name.
51 * This creates the LogCategory for the specified name if it does not exist
54 LogCategory* getCategory(folly::StringPiece name);
57 * Get the LogCategory for the specified name, if it already exists.
59 * This returns nullptr if no LogCategory has been created yet for the
62 LogCategory* FOLLY_NULLABLE getCategoryOrNull(folly::StringPiece name);
65 * Set the log level for the specified category.
67 * Messages logged to a specific log category will be ignored unless the
68 * message log level is greater than the LogCategory's effective log level.
70 * If inherit is true, LogCategory's effective log level is the minimum of
71 * its level and it's parent category's effective log level. If inherit is
72 * false, the LogCategory's effective log level is simply its log level.
73 * (Setting inherit to false is necessary if you want a child LogCategory to
74 * use a less verbose level than its parent categories.)
76 void setLevel(folly::StringPiece name, LogLevel level, bool inherit = true);
77 void setLevel(LogCategory* category, LogLevel level, bool inherit = true);
80 * Apply a configuration string specifying a series a log levels.
82 * The string format is a comma separated list of <name>=<level> sections.
83 * e.g.: "foo=DBG3,log.bar=WARN"
85 * Returns a list of error messages for each error encountered trying to
86 * parse the config string. The return value will be an empty vector if no
87 * errors were encountered.
89 std::vector<std::string> processConfigString(folly::StringPiece config);
92 * Remove all registered LogHandlers on all LogCategory objects.
94 * This is called on the main LoggerDB object during shutdown.
96 void cleanupHandlers();
99 * Call flush() on all LogHandler objects registered on any LogCategory in
102 * Returns the number of registered LogHandlers.
104 size_t flushAllHandlers();
107 * Register a LogHandlerFactory.
109 * The LogHandlerFactory will be used to create LogHandler objects from a
110 * LogConfig object during updateConfig() and resetConfig() calls.
112 * Only one factory can be registered for a given handler type name.
113 * LogHandlerFactory::getType() returns the handler type supported by this
116 * If an existing LogHandlerFactory is already registered with this type name
117 * and replaceExisting is false a std::range_error will be thrown.
118 * Otherwise, if replaceExisting is true, the new factory will replace the
121 void registerHandlerFactory(
122 std::unique_ptr<LogHandlerFactory> factory,
123 bool replaceExisting = false);
126 * Remove a registered LogHandlerFactory.
128 * The type parameter should be the name of the handler type, as returned by
129 * LogHandlerFactory::getType().
131 * Throws std::range_error if no handler factory with this type name exists.
133 void unregisterHandlerFactory(folly::StringPiece type);
136 * Initialize the LogCategory* and std::atomic<LogLevel> used by an XLOG()
139 * Returns the current effective LogLevel of the category.
142 folly::StringPiece categoryName,
143 std::atomic<LogLevel>* xlogCategoryLevel,
144 LogCategory** xlogCategory);
145 LogCategory* xlogInitCategory(
146 folly::StringPiece categoryName,
147 LogCategory** xlogCategory,
148 std::atomic<bool>* isInitialized);
150 enum TestConstructorArg { TESTING };
153 * Construct a LoggerDB for testing purposes.
155 * Most callers should not need this function, and should use
156 * LoggerDB::get() to obtain the main LoggerDB singleton. This function
157 * exists mainly to allow testing LoggerDB objects in unit tests.
158 * It requires an explicit argument just to prevent callers from calling it
161 explicit LoggerDB(TestConstructorArg);
164 * internalWarning() is used to report a problem when something goes wrong
165 * internally in the logging library.
167 * We can't log these messages through the normal logging flow since logging
170 * Example scenarios where this is used:
171 * - We fail to write to a log file (for instance, when the disk is full)
172 * - A LogHandler throws an unexpected exception
174 template <typename... Args>
175 static void internalWarning(
176 folly::StringPiece file,
178 Args&&... args) noexcept {
180 file, lineNumber, folly::to<std::string>(std::forward<Args>(args)...));
183 using InternalWarningHandler =
184 void (*)(folly::StringPiece file, int lineNumber, std::string&&);
187 * Set a function to be called when the logging library generates an internal
190 * The supplied handler should never throw exceptions.
192 * If a null handler is supplied, the default built-in handler will be used.
194 * The default handler reports the message with _CrtDbgReport(_CRT_WARN) on
195 * Windows, and prints the message to stderr on other platforms. It also
196 * rate limits messages if they are arriving too quickly.
198 static void setInternalWarningHandler(InternalWarningHandler handler);
201 using LoggerNameMap = std::unordered_map<
203 std::unique_ptr<LogCategory>,
207 using HandlerFactoryMap =
208 std::unordered_map<std::string, std::unique_ptr<LogHandlerFactory>>;
209 using HandlerMap = std::unordered_map<std::string, std::weak_ptr<LogHandler>>;
211 HandlerFactoryMap factories;
215 // Forbidden copy constructor and assignment operator
216 LoggerDB(LoggerDB const&) = delete;
217 LoggerDB& operator=(LoggerDB const&) = delete;
220 LogCategory* getOrCreateCategoryLocked(
221 LoggerNameMap& loggersByName,
222 folly::StringPiece name);
223 LogCategory* createCategoryLocked(
224 LoggerNameMap& loggersByName,
225 folly::StringPiece name,
226 LogCategory* parent);
228 static void internalWarningImpl(
229 folly::StringPiece filename,
231 std::string&& msg) noexcept;
232 static void defaultInternalWarningImpl(
233 folly::StringPiece filename,
235 std::string&& msg) noexcept;
238 * A map of LogCategory objects by name.
240 * Lookups can be performed using arbitrary StringPiece values that do not
241 * have to be in canonical form.
243 folly::Synchronized<LoggerNameMap> loggersByName_;
246 * The LogHandlers and LogHandlerFactories.
248 folly::Synchronized<HandlerInfo> handlerInfo_;
250 static std::atomic<InternalWarningHandler> warningHandler_;