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/LogMessage.h>
28 * LogStreamProcessor receives a LogStream and logs it.
30 * This class is primarily intended to be used through the FB_LOG*() macros.
31 * Its API is designed to support these macros, and is not designed for other
34 * The operator&() method is used to trigger the logging.
35 * This operator is used because it has lower precedence than <<, but higher
36 * precedence than the ? ternary operator, allowing it to bind with the correct
37 * precedence in the log macro implementations.
39 class LogStreamProcessor {
41 enum AppendType { APPEND };
42 enum FormatType { FORMAT };
45 * LogStreamProcessor constructor for use with a LOG() macro with no extra
48 * Note that the filename argument is not copied. The caller should ensure
49 * that it points to storage that will remain valid for the lifetime of the
50 * LogStreamProcessor. (This is always the case for the __FILE__
51 * preprocessor macro.)
54 const LogCategory* category,
56 folly::StringPiece filename,
57 unsigned int lineNumber,
59 : category_{category},
62 lineNumber_{lineNumber} {}
65 * LogStreamProcessor constructor for use with a LOG() macro with arguments
66 * to be concatenated with folly::to<std::string>()
68 * Note that the filename argument is not copied. The caller should ensure
69 * that it points to storage that will remain valid for the lifetime of the
70 * LogStreamProcessor. (This is always the case for the __FILE__
71 * preprocessor macro.)
73 template <typename... Args>
75 const LogCategory* category,
78 unsigned int lineNumber,
80 Args&&... args) noexcept
81 : category_{category},
84 lineNumber_{lineNumber},
85 message_{createLogString(std::forward<Args>(args)...)} {}
88 * LogStreamProcessor constructor for use with a LOG() macro with arguments
89 * to be concatenated with folly::to<std::string>()
91 * Note that the filename argument is not copied. The caller should ensure
92 * that it points to storage that will remain valid for the lifetime of the
93 * LogStreamProcessor. (This is always the case for the __FILE__
94 * preprocessor macro.)
96 template <typename... Args>
98 const LogCategory* category,
100 const char* filename,
101 unsigned int lineNumber,
103 folly::StringPiece fmt,
104 Args&&... args) noexcept
105 : category_{category},
108 lineNumber_{lineNumber},
109 message_{formatLogString(fmt, std::forward<Args>(args)...)} {}
112 * This version of operator&() is typically used when the user specifies
113 * log arguments using the << stream operator. The operator<<() generally
114 * returns a std::ostream&
116 void operator&(std::ostream& stream) noexcept;
119 * This version of operator&() is used when no extra arguments are specified
120 * with the << operator. In this case the & operator is applied directly to
121 * the temporary LogStream object.
123 void operator&(LogStream&& stream) noexcept;
126 std::string extractMessageString(LogStream& stream) noexcept;
129 * Construct a log message string using folly::to<std::string>()
131 * This function attempts to avoid throwing exceptions. If an error occurs
132 * during formatting, a message including the error details is returned
133 * instead. This is done to help ensure that log statements do not generate
134 * exceptions, but instead just log an error string when something goes wrong.
136 template <typename... Args>
137 std::string createLogString(Args&&... args) noexcept {
139 return folly::to<std::string>(std::forward<Args>(args)...);
140 } catch (const std::exception& ex) {
141 // This most likely means there was some error converting the arguments
142 // to strings. Handle the exception here, rather than letting it
143 // propagate up, since callers generally do not expect log statements to
146 // Just log an error message letting indicating that something went wrong
147 // formatting the log message.
148 return folly::to<std::string>(
149 "error constructing log message: ", ex.what());
154 * Construct a log message string using folly::sformat()
156 * This function attempts to avoid throwing exceptions. If an error occurs
157 * during formatting, a message including the error details is returned
158 * instead. This is done to help ensure that log statements do not generate
159 * exceptions, but instead just log an error string when something goes wrong.
161 template <typename... Args>
162 std::string formatLogString(folly::StringPiece fmt, Args&&... args) noexcept {
164 return folly::sformat(fmt, std::forward<Args>(args)...);
165 } catch (const std::exception& ex) {
166 // This most likely means that the caller had a bug in their format
167 // string/arguments. Handle the exception here, rather than letting it
168 // propagate up, since callers generally do not expect log statements to
171 // Log the format string by itself, to help the developer at least
172 // identify the buggy format string in their code.
173 return folly::to<std::string>(
174 "error formatting log message: ",
176 "; format string: \"",
182 const LogCategory* const category_;
183 LogLevel const level_;
184 folly::StringPiece filename_;
185 unsigned int lineNumber_;
186 std::string message_;