/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include /** * Log a message to the specified logger. * * This macro avoids evaluating the log arguments unless the log level check * succeeds. * * Beware that the logger argument is evaluated twice, so this argument should * be an expression with no side-effects. */ #define FB_LOG(logger, level, ...) \ FB_LOG_IMPL( \ logger, \ ::folly::LogLevel::level, \ ::folly::LogStreamProcessor::APPEND, \ ##__VA_ARGS__) /** * Log a message to the specified logger, using a fmt::format() string. * * The arguments will be processed using fmt::format(). The format syntax * is similar to Python format strings. * * This macro avoids evaluating the log arguments unless the log level check * succeeds. * * Beware that the logger argument is evaluated twice, so this argument should * be an expression with no side-effects. */ #define FB_LOGF(logger, level, fmt, arg1, ...) \ FB_LOG_IMPL( \ logger, \ ::folly::LogLevel::level, \ ::folly::LogStreamProcessor::FORMAT, \ fmt, \ arg1, \ ##__VA_ARGS__) /** * FB_LOG_RAW() can be used by callers that want to pass in the log level as a * variable, and/or who want to explicitly specify the filename and line * number. * * This is useful for callers implementing their own log wrapper functions * that want to pass in their caller's filename and line number rather than * their own. * * The log level parameter must be an explicitly qualified LogLevel value, or a * LogLevel variable. (This differs from FB_LOG() and FB_LOGF() which accept * an unqualified LogLevel name.) */ #define FB_LOG_RAW(logger, level, filename, linenumber, functionName, ...) \ FB_LOG_RAW_IMPL( \ logger, \ level, \ filename, \ linenumber, \ functionName, \ ::folly::LogStreamProcessor::APPEND, \ ##__VA_ARGS__) /** * FB_LOGF_RAW() is similar to FB_LOG_RAW(), but formats the log arguments * using fmt::format(). */ #define FB_LOGF_RAW( \ logger, level, filename, linenumber, functionName, fmt, arg1, ...) \ FB_LOG_RAW_IMPL( \ logger, \ level, \ filename, \ linenumber, \ functionName, \ ::folly::LogStreamProcessor::FORMAT, \ fmt, \ arg1, \ ##__VA_ARGS__) /** * Helper macro for implementing FB_LOG() and FB_LOGF(). * * This macro generally should not be used directly by end users. */ #define FB_LOG_IMPL(logger, level, type, ...) \ (!(logger).getCategory()->logCheck(level)) \ ? ::folly::logDisabledHelper( \ ::folly::bool_constant<::folly::isLogLevelFatal(level)>{}) \ : ::folly::LogStreamVoidify<::folly::isLogLevelFatal(level)>{} & \ ::folly::LogStreamProcessor{ \ (logger).getCategory(), \ (level), \ __FILE__, \ __LINE__, \ __func__, \ (type), \ ##__VA_ARGS__} \ .stream() /** * Helper macro for implementing FB_LOG_RAW() and FB_LOGF_RAW(). * * This macro generally should not be used directly by end users. * * This is very similar to FB_LOG_IMPL(), but since the level may be a variable * instead of a compile-time constant, we cannot detect at compile time if this * is a fatal log message or not. */ #define FB_LOG_RAW_IMPL( \ logger, level, filename, line, functionName, type, ...) \ (!(logger).getCategory()->logCheck(level)) \ ? static_cast(0) \ : ::folly::LogStreamVoidify{} & \ ::folly::LogStreamProcessor{ \ (logger).getCategory(), \ (level), \ (filename), \ (line), \ (functionName), \ (type), \ ##__VA_ARGS__} \ .stream() namespace folly { class LoggerDB; class LogMessage; /** * Logger is the class you will use to specify the log category when logging * messages with FB_LOG(). * * Logger is really just a small wrapper class that contains a pointer to the * appropriate LogCategory object. It primarily exists as syntactic sugar to * allow for easily looking up LogCategory objects. */ class Logger { public: /** * Construct a Logger for the given category name. * * A LogCategory object for this category will be created if one does not * already exist. */ explicit Logger(folly::StringPiece name); /** * Construct a Logger pointing to an existing LogCategory object. */ explicit Logger(LogCategory* cat); /** * Construct a Logger for a specific LoggerDB object, rather than the main * singleton. * * This is primarily intended for use in unit tests. */ Logger(LoggerDB* db, folly::StringPiece name); /** * Get the LogCategory that this Logger refers to. */ LogCategory* getCategory() const { return category_; } private: LogCategory* const category_{nullptr}; }; } // namespace folly