| 1 | /* | 
|---|
| 2 | * Copyright 2017-present Facebook, Inc. | 
|---|
| 3 | * | 
|---|
| 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 | 
|---|
| 7 | * | 
|---|
| 8 | *   http://www.apache.org/licenses/LICENSE-2.0 | 
|---|
| 9 | * | 
|---|
| 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. | 
|---|
| 15 | */ | 
|---|
| 16 | #pragma once | 
|---|
| 17 |  | 
|---|
| 18 | #include <folly/Conv.h> | 
|---|
| 19 | #include <folly/Format.h> | 
|---|
| 20 | #include <folly/logging/LogCategory.h> | 
|---|
| 21 | #include <folly/logging/LogLevel.h> | 
|---|
| 22 | #include <folly/logging/LogStream.h> | 
|---|
| 23 | #include <folly/logging/LogStreamProcessor.h> | 
|---|
| 24 |  | 
|---|
| 25 | /** | 
|---|
| 26 | * Log a message to the specified logger. | 
|---|
| 27 | * | 
|---|
| 28 | * This macro avoids evaluating the log arguments unless the log level check | 
|---|
| 29 | * succeeds. | 
|---|
| 30 | * | 
|---|
| 31 | * Beware that the logger argument is evaluated twice, so this argument should | 
|---|
| 32 | * be an expression with no side-effects. | 
|---|
| 33 | */ | 
|---|
| 34 | #define FB_LOG(logger, level, ...)         \ | 
|---|
| 35 | FB_LOG_IMPL(                             \ | 
|---|
| 36 | logger,                              \ | 
|---|
| 37 | ::folly::LogLevel::level,            \ | 
|---|
| 38 | ::folly::LogStreamProcessor::APPEND, \ | 
|---|
| 39 | ##__VA_ARGS__) | 
|---|
| 40 |  | 
|---|
| 41 | /** | 
|---|
| 42 | * Log a message to the specified logger, using a folly::format() string. | 
|---|
| 43 | * | 
|---|
| 44 | * The arguments will be processed using folly::format().  The format syntax | 
|---|
| 45 | * is similar to Python format strings. | 
|---|
| 46 | * | 
|---|
| 47 | * This macro avoids evaluating the log arguments unless the log level check | 
|---|
| 48 | * succeeds. | 
|---|
| 49 | * | 
|---|
| 50 | * Beware that the logger argument is evaluated twice, so this argument should | 
|---|
| 51 | * be an expression with no side-effects. | 
|---|
| 52 | */ | 
|---|
| 53 | #define FB_LOGF(logger, level, fmt, arg1, ...) \ | 
|---|
| 54 | FB_LOG_IMPL(                                 \ | 
|---|
| 55 | logger,                                  \ | 
|---|
| 56 | ::folly::LogLevel::level,                \ | 
|---|
| 57 | ::folly::LogStreamProcessor::FORMAT,     \ | 
|---|
| 58 | fmt,                                     \ | 
|---|
| 59 | arg1,                                    \ | 
|---|
| 60 | ##__VA_ARGS__) | 
|---|
| 61 |  | 
|---|
| 62 | /** | 
|---|
| 63 | * FB_LOG_RAW() can be used by callers that want to pass in the log level as a | 
|---|
| 64 | * variable, and/or who want to explicitly specify the filename and line | 
|---|
| 65 | * number. | 
|---|
| 66 | * | 
|---|
| 67 | * This is useful for callers implementing their own log wrapper functions | 
|---|
| 68 | * that want to pass in their caller's filename and line number rather than | 
|---|
| 69 | * their own. | 
|---|
| 70 | * | 
|---|
| 71 | * The log level parameter must be an explicitly qualified LogLevel value, or a | 
|---|
| 72 | * LogLevel variable.  (This differs from FB_LOG() and FB_LOGF() which accept | 
|---|
| 73 | * an unqualified LogLevel name.) | 
|---|
| 74 | */ | 
|---|
| 75 | #define FB_LOG_RAW(logger, level, filename, linenumber, functionName, ...) \ | 
|---|
| 76 | FB_LOG_RAW_IMPL(                                                         \ | 
|---|
| 77 | logger,                                                              \ | 
|---|
| 78 | level,                                                               \ | 
|---|
| 79 | filename,                                                            \ | 
|---|
| 80 | linenumber,                                                          \ | 
|---|
| 81 | functionName,                                                        \ | 
|---|
| 82 | ::folly::LogStreamProcessor::APPEND,                                 \ | 
|---|
| 83 | ##__VA_ARGS__) | 
|---|
| 84 |  | 
|---|
| 85 | /** | 
|---|
| 86 | * FB_LOGF_RAW() is similar to FB_LOG_RAW(), but formats the log arguments | 
|---|
| 87 | * using folly::format(). | 
|---|
| 88 | */ | 
|---|
| 89 | #define FB_LOGF_RAW(                                                   \ | 
|---|
| 90 | logger, level, filename, linenumber, functionName, fmt, arg1, ...) \ | 
|---|
| 91 | FB_LOG_RAW_IMPL(                                                     \ | 
|---|
| 92 | logger,                                                          \ | 
|---|
| 93 | level,                                                           \ | 
|---|
| 94 | filename,                                                        \ | 
|---|
| 95 | linenumber,                                                      \ | 
|---|
| 96 | functionName,                                                    \ | 
|---|
| 97 | ::folly::LogStreamProcessor::FORMAT,                             \ | 
|---|
| 98 | fmt,                                                             \ | 
|---|
| 99 | arg1,                                                            \ | 
|---|
| 100 | ##__VA_ARGS__) | 
|---|
| 101 |  | 
|---|
| 102 | /** | 
|---|
| 103 | * Helper macro for implementing FB_LOG() and FB_LOGF(). | 
|---|
| 104 | * | 
|---|
| 105 | * This macro generally should not be used directly by end users. | 
|---|
| 106 | */ | 
|---|
| 107 | #define FB_LOG_IMPL(logger, level, type, ...)                          \ | 
|---|
| 108 | (!(logger).getCategory()->logCheck(level))                           \ | 
|---|
| 109 | ? ::folly::logDisabledHelper(                                    \ | 
|---|
| 110 | ::folly::bool_constant<::folly::isLogLevelFatal(level)>{}) \ | 
|---|
| 111 | : ::folly::LogStreamVoidify<::folly::isLogLevelFatal(level)>{} & \ | 
|---|
| 112 | ::folly::LogStreamProcessor{(logger).getCategory(),          \ | 
|---|
| 113 | (level),                         \ | 
|---|
| 114 | __FILE__,                        \ | 
|---|
| 115 | __LINE__,                        \ | 
|---|
| 116 | __func__,                        \ | 
|---|
| 117 | (type),                          \ | 
|---|
| 118 | ##__VA_ARGS__}                   \ | 
|---|
| 119 | .stream() | 
|---|
| 120 |  | 
|---|
| 121 | /** | 
|---|
| 122 | * Helper macro for implementing FB_LOG_RAW() and FB_LOGF_RAW(). | 
|---|
| 123 | * | 
|---|
| 124 | * This macro generally should not be used directly by end users. | 
|---|
| 125 | * | 
|---|
| 126 | * This is very similar to FB_LOG_IMPL(), but since the level may be a variable | 
|---|
| 127 | * instead of a compile-time constant, we cannot detect at compile time if this | 
|---|
| 128 | * is a fatal log message or not. | 
|---|
| 129 | */ | 
|---|
| 130 | #define FB_LOG_RAW_IMPL(                                      \ | 
|---|
| 131 | logger, level, filename, line, functionName, type, ...)   \ | 
|---|
| 132 | (!(logger).getCategory()->logCheck(level))                  \ | 
|---|
| 133 | ? static_cast<void>(0)                                  \ | 
|---|
| 134 | : ::folly::LogStreamVoidify<false>{} &                  \ | 
|---|
| 135 | ::folly::LogStreamProcessor{(logger).getCategory(), \ | 
|---|
| 136 | (level),                \ | 
|---|
| 137 | (filename),             \ | 
|---|
| 138 | (line),                 \ | 
|---|
| 139 | (functionName),         \ | 
|---|
| 140 | (type),                 \ | 
|---|
| 141 | ##__VA_ARGS__}          \ | 
|---|
| 142 | .stream() | 
|---|
| 143 |  | 
|---|
| 144 | namespace folly { | 
|---|
| 145 |  | 
|---|
| 146 | class LoggerDB; | 
|---|
| 147 | class LogMessage; | 
|---|
| 148 |  | 
|---|
| 149 | /** | 
|---|
| 150 | * Logger is the class you will use to specify the log category when logging | 
|---|
| 151 | * messages with FB_LOG(). | 
|---|
| 152 | * | 
|---|
| 153 | * Logger is really just a small wrapper class that contains a pointer to the | 
|---|
| 154 | * appropriate LogCategory object.  It primarily exists as syntactic sugar to | 
|---|
| 155 | * allow for easily looking up LogCategory objects. | 
|---|
| 156 | */ | 
|---|
| 157 | class Logger { | 
|---|
| 158 | public: | 
|---|
| 159 | /** | 
|---|
| 160 | * Construct a Logger for the given category name. | 
|---|
| 161 | * | 
|---|
| 162 | * A LogCategory object for this category will be created if one does not | 
|---|
| 163 | * already exist. | 
|---|
| 164 | */ | 
|---|
| 165 | explicit Logger(folly::StringPiece name); | 
|---|
| 166 |  | 
|---|
| 167 | /** | 
|---|
| 168 | * Construct a Logger pointing to an existing LogCategory object. | 
|---|
| 169 | */ | 
|---|
| 170 | explicit Logger(LogCategory* cat); | 
|---|
| 171 |  | 
|---|
| 172 | /** | 
|---|
| 173 | * Construct a Logger for a specific LoggerDB object, rather than the main | 
|---|
| 174 | * singleton. | 
|---|
| 175 | * | 
|---|
| 176 | * This is primarily intended for use in unit tests. | 
|---|
| 177 | */ | 
|---|
| 178 | Logger(LoggerDB* db, folly::StringPiece name); | 
|---|
| 179 |  | 
|---|
| 180 | /** | 
|---|
| 181 | * Get the LogCategory that this Logger refers to. | 
|---|
| 182 | */ | 
|---|
| 183 | LogCategory* getCategory() const { | 
|---|
| 184 | return category_; | 
|---|
| 185 | } | 
|---|
| 186 |  | 
|---|
| 187 | private: | 
|---|
| 188 | LogCategory* const category_{nullptr}; | 
|---|
| 189 | }; | 
|---|
| 190 | } // namespace folly | 
|---|
| 191 |  | 
|---|