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/Format.h>
20 #include <folly/experimental/logging/LogCategory.h>
21 #include <folly/experimental/logging/LogLevel.h>
24 * Log a message to the specified logger.
26 * This macro avoids evaluating the log arguments unless the log level check
29 #define FB_LOG(logger, level, msg, ...) \
31 const auto fbLogLevelTmp = ::folly::LogLevel::level; \
32 const auto& fbLoggerTmp = (logger); \
33 if (fbLoggerTmp.logCheck(fbLogLevelTmp)) { \
35 fbLogLevelTmp, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \
40 * Log a message to the specified logger, using a folly::format() string.
42 * The arguments will be processed using folly::format(). The format syntax
43 * is similar to Python format strings.
45 * This macro avoids evaluating the log arguments unless the log level check
48 #define FB_LOGF(logger, level, fmt, ...) \
50 const auto fbLogLevelTmp = ::folly::LogLevel::level; \
51 const auto& fbLoggerTmp = (logger); \
52 if (fbLoggerTmp.logCheck(fbLogLevelTmp)) { \
54 fbLogLevelTmp, __FILE__, __LINE__, (fmt), ##__VA_ARGS__); \
64 * Logger is the class you will normally use to log messages.
66 * The Logger is really just a small wrapper class that contains a pointer
67 * to the appropriate LogCategory object. It exists to allow for easy static
68 * initialization of log categories, as well as to provide fast checking of the
69 * current effective log level.
74 * Construct a Logger for the given category name.
76 * A LogCategory object for this category will be created if one does not
79 explicit Logger(folly::StringPiece name);
82 * Construct a Logger pointing to an existing LogCategory object.
84 explicit Logger(LogCategory* cat);
87 * Construct a Logger for a specific LoggerDB object, rather than the main
90 * This is primarily intended for use in unit tests.
92 Logger(LoggerDB* db, folly::StringPiece name);
95 * Get the effective level for this logger.
97 * This is the minimum log level of this logger, or any of its parents.
98 * Log messages below this level will be ignored, while messages at or
99 * above this level need to be processed by this logger or one of its
102 LogLevel getEffectiveLevel() const {
103 return category_->getEffectiveLevel();
107 * Check whether this Logger or any of its parent Loggers would do anything
108 * with a log message at the given level.
110 bool logCheck(LogLevel level) const {
111 // We load the effective level using std::memory_order_relaxed.
113 // We want to make log checks as lightweight as possible. It's fine if we
114 // don't immediately respond to changes made to the log level from other
115 // threads. We can wait until some other operation triggers a memory
116 // barrier before we honor the new log level setting. No other memory
117 // accesses depend on the log level value. Callers should not rely on all
118 // other threads to immediately stop logging as soon as they decrease the
119 // log level for a given category.
120 return category_->getEffectiveLevelRelaxed() <= level;
124 * Unconditionally log a message.
126 * The caller is responsible for calling logCheck() before log() to ensure
127 * that this log message should be admitted. This is typically done with one
128 * of the logging macros.
132 folly::StringPiece filename,
133 unsigned int lineNumber,
134 std::string&& msg) const;
137 folly::StringPiece filename,
138 unsigned int lineNumber,
139 folly::StringPiece msg) const;
142 * Unconditionally log a message.
144 * This concatenates the arguments into a string using
145 * folly::to<std::string>()
147 template <typename... Args>
150 folly::StringPiece filename,
151 unsigned int lineNumber,
152 Args&&... args) const {
155 msg = folly::to<std::string>(std::forward<Args>(args)...);
156 } catch (const std::exception& ex) {
157 // This most likely means there was some error converting the arguments
158 // to strings. Handle the exception here, rather than letting it
159 // propagate up, since callers generally do not expect log statements to
162 // Just log an error message letting indicating that something went wrong
163 // formatting the log message.
165 folly::to<std::string>("error constructing log message: ", ex.what());
167 log(level, filename, lineNumber, std::move(msg));
171 * Unconditionally log a message using a format string.
173 * This uses folly::format() to format the message.
175 template <typename... Args>
178 folly::StringPiece filename,
179 unsigned int lineNumber,
180 folly::StringPiece fmt,
181 Args&&... args) const {
184 msg = folly::sformat(fmt, std::forward<Args>(args)...);
185 } catch (const std::exception& ex) {
186 // This most likely means that the caller had a bug in their format
187 // string/arguments. Handle the exception here, rather than letting it
188 // propagate up, since callers generally do not expect log statements to
191 // Log the format string by itself, to help the developer at least
192 // identify the buggy format string in their code.
193 msg = folly::to<std::string>(
194 "error formatting log message: ",
199 log(level, filename, lineNumber, std::move(msg));
203 * Get the LogCategory that this Logger refers to.
205 LogCategory* getCategory() const {
210 LogCategory* const category_{nullptr};