logging: fix compiler compatibility for one more constexpr function
[folly.git] / folly / experimental / logging / LoggerDB.h
1 /*
2  * Copyright 2004-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/CppAttributes.h>
20 #include <folly/Range.h>
21 #include <folly/Synchronized.h>
22 #include <memory>
23 #include <string>
24 #include <unordered_map>
25 #include <vector>
26
27 #include <folly/experimental/logging/LogName.h>
28
29 namespace folly {
30
31 class LogCategory;
32 enum class LogLevel : uint32_t;
33
34 /**
35  * LoggerDB stores the set of LogCategory objects.
36  */
37 class LoggerDB {
38  public:
39   /**
40    * Get the main LoggerDB singleton.
41    */
42   static LoggerDB* get();
43
44   /**
45    * Get the LogCategory for the specified name.
46    *
47    * This creates the LogCategory for the specified name if it does not exist
48    * already.
49    */
50   LogCategory* getCategory(folly::StringPiece name);
51
52   /**
53    * Get the LogCategory for the specified name, if it already exists.
54    *
55    * This returns nullptr if no LogCategory has been created yet for the
56    * specified name.
57    */
58   LogCategory* FOLLY_NULLABLE getCategoryOrNull(folly::StringPiece name);
59
60   /**
61    * Set the log level for the specified category.
62    *
63    * Messages logged to a specific log category will be ignored unless the
64    * message log level is greater than the LogCategory's effective log level.
65    *
66    * If inherit is true, LogCategory's effective log level is the minimum of
67    * its level and it's parent category's effective log level.  If inherit is
68    * false, the LogCategory's effective log level is simply its log level.
69    * (Setting inherit to false is necessary if you want a child LogCategory to
70    * use a less verbose level than its parent categories.)
71    */
72   void setLevel(folly::StringPiece name, LogLevel level, bool inherit = true);
73   void setLevel(LogCategory* category, LogLevel level, bool inherit = true);
74
75   /**
76    * Apply a configuration string specifying a series a log levels.
77    *
78    * The string format is a comma separated list of <name>=<level> sections.
79    * e.g.: "foo=DBG3,log.bar=WARN"
80    *
81    * Returns a list of error messages for each error encountered trying to
82    * parse the config string.  The return value will be an empty vector if no
83    * errors were encountered.
84    */
85   std::vector<std::string> processConfigString(folly::StringPiece config);
86
87   /**
88    * Remove all registered LogHandlers on all LogCategory objects.
89    *
90    * This is called on the main LoggerDB object during shutdown.
91    */
92   void cleanupHandlers();
93
94   /**
95    * Call flush() on all LogHandler objects registered on any LogCategory in
96    * this LoggerDB.
97    *
98    * Returns the number of registered LogHandlers.
99    */
100   size_t flushAllHandlers();
101
102   /**
103    * Initialize the LogCategory* and std::atomic<LogLevel> used by an XLOG()
104    * statement.
105    *
106    * Returns the current effective LogLevel of the category.
107    */
108   LogLevel xlogInit(
109       folly::StringPiece categoryName,
110       std::atomic<LogLevel>* xlogCategoryLevel,
111       LogCategory** xlogCategory);
112   LogCategory* xlogInitCategory(
113       folly::StringPiece categoryName,
114       LogCategory** xlogCategory,
115       std::atomic<bool>* isInitialized);
116
117   enum TestConstructorArg { TESTING };
118
119   /**
120    * Construct a LoggerDB for testing purposes.
121    *
122    * Most callers should not need this function, and should use
123    * LoggerDB::get() to obtain the main LoggerDB singleton.  This function
124    * exists mainly to allow testing LoggerDB objects in unit tests.
125    * It requires an explicit argument just to prevent callers from calling it
126    * unintentionally.
127    */
128   explicit LoggerDB(TestConstructorArg);
129
130   /**
131    * internalWarning() is used to report a problem when something goes wrong
132    * internally in the logging library.
133    *
134    * We can't log these messages through the normal logging flow since logging
135    * itself has failed.
136    *
137    * Example scenarios where this is used:
138    * - We fail to write to a log file (for instance, when the disk is full)
139    * - A LogHandler throws an unexpected exception
140    */
141   template <typename... Args>
142   static void internalWarning(
143       folly::StringPiece file,
144       int lineNumber,
145       Args&&... args) noexcept {
146     internalWarningImpl(
147         file, lineNumber, folly::to<std::string>(std::forward<Args>(args)...));
148   }
149
150   using InternalWarningHandler =
151       void (*)(folly::StringPiece file, int lineNumber, std::string&&);
152
153   /**
154    * Set a function to be called when the logging library generates an internal
155    * warning.
156    *
157    * The supplied handler should never throw exceptions.
158    *
159    * If a null handler is supplied, the default built-in handler will be used.
160    *
161    * The default handler reports the message with _CrtDbgReport(_CRT_WARN) on
162    * Windows, and prints the message to stderr on other platforms.  It also
163    * rate limits messages if they are arriving too quickly.
164    */
165   static void setInternalWarningHandler(InternalWarningHandler handler);
166
167  private:
168   using LoggerNameMap = std::unordered_map<
169       folly::StringPiece,
170       std::unique_ptr<LogCategory>,
171       LogName::Hash,
172       LogName::Equals>;
173
174   // Forbidden copy constructor and assignment operator
175   LoggerDB(LoggerDB const&) = delete;
176   LoggerDB& operator=(LoggerDB const&) = delete;
177
178   LoggerDB();
179   LogCategory* getOrCreateCategoryLocked(
180       LoggerNameMap& loggersByName,
181       folly::StringPiece name);
182   LogCategory* createCategoryLocked(
183       LoggerNameMap& loggersByName,
184       folly::StringPiece name,
185       LogCategory* parent);
186
187   static void internalWarningImpl(
188       folly::StringPiece filename,
189       int lineNumber,
190       std::string&& msg) noexcept;
191   static void defaultInternalWarningImpl(
192       folly::StringPiece filename,
193       int lineNumber,
194       std::string&& msg) noexcept;
195
196   /**
197    * A map of LogCategory objects by name.
198    *
199    * Lookups can be performed using arbitrary StringPiece values that do not
200    * have to be in canonical form.
201    */
202   folly::Synchronized<LoggerNameMap> loggersByName_;
203
204   static std::atomic<InternalWarningHandler> warningHandler_;
205 };
206 }