logging: add XLOG() and XLOGF() logging macros
[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/CppAttributes.h>
19 #include <folly/Range.h>
20 #include <folly/Synchronized.h>
21 #include <memory>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25
26 #include <folly/experimental/logging/LogName.h>
27
28 namespace folly {
29
30 class LogCategory;
31 enum class LogLevel : uint32_t;
32
33 /**
34  * LoggerDB stores the set of LogCategory objects.
35  */
36 class LoggerDB {
37  public:
38   /**
39    * Get the main LoggerDB singleton.
40    */
41   static LoggerDB* get();
42
43   /**
44    * Get the LogCategory for the specified name.
45    *
46    * This creates the LogCategory for the specified name if it does not exist
47    * already.
48    */
49   LogCategory* getCategory(folly::StringPiece name);
50
51   /**
52    * Get the LogCategory for the specified name, if it already exists.
53    *
54    * This returns nullptr if no LogCategory has been created yet for the
55    * specified name.
56    */
57   LogCategory* FOLLY_NULLABLE getCategoryOrNull(folly::StringPiece name);
58
59   /**
60    * Set the log level for the specified category.
61    *
62    * Messages logged to a specific log category will be ignored unless the
63    * message log level is greater than the LogCategory's effective log level.
64    *
65    * If inherit is true, LogCategory's effective log level is the minimum of
66    * its level and it's parent category's effective log level.  If inherit is
67    * false, the LogCategory's effective log level is simply its log level.
68    * (Setting inherit to false is necessary if you want a child LogCategory to
69    * use a less verbose level than its parent categories.)
70    */
71   void setLevel(folly::StringPiece name, LogLevel level, bool inherit = true);
72   void setLevel(LogCategory* category, LogLevel level, bool inherit = true);
73
74   /**
75    * Apply a configuration string specifying a series a log levels.
76    *
77    * The string format is a comma separated list of <name>=<level> sections.
78    * e.g.: "foo=DBG3,log.bar=WARN"
79    *
80    * Returns a list of error messages for each error encountered trying to
81    * parse the config string.  The return value will be an empty vector if no
82    * errors were encountered.
83    */
84   std::vector<std::string> processConfigString(folly::StringPiece config);
85
86   /**
87    * Remove all registered LogHandlers on all LogCategory objects.
88    *
89    * This is called on the main LoggerDB object during shutdown.
90    */
91   void cleanupHandlers();
92
93   /**
94    * Initialize the LogCategory* and std::atomic<LogLevel> used by an XLOG()
95    * statement.
96    *
97    * Returns the current effective LogLevel of the category.
98    */
99   LogLevel xlogInit(
100       folly::StringPiece categoryName,
101       std::atomic<LogLevel>* xlogCategoryLevel,
102       LogCategory** xlogCategory);
103   LogCategory* xlogInitCategory(
104       folly::StringPiece categoryName,
105       LogCategory** xlogCategory,
106       std::atomic<bool>* isInitialized);
107
108   enum TestConstructorArg { TESTING };
109
110   /**
111    * Construct a LoggerDB for testing purposes.
112    *
113    * Most callers should not need this function, and should use
114    * LoggerDB::get() to obtain the main LoggerDB singleton.  This function
115    * exists mainly to allow testing LoggerDB objects in unit tests.
116    * It requires an explicit argument just to prevent callers from calling it
117    * unintentionally.
118    */
119   explicit LoggerDB(TestConstructorArg);
120
121  private:
122   using LoggerNameMap = std::unordered_map<
123       folly::StringPiece,
124       std::unique_ptr<LogCategory>,
125       LogName::Hash,
126       LogName::Equals>;
127
128   // Forbidden copy constructor and assignment operator
129   LoggerDB(LoggerDB const&) = delete;
130   LoggerDB& operator=(LoggerDB const&) = delete;
131
132   LoggerDB();
133   LogCategory* getOrCreateCategoryLocked(
134       LoggerNameMap& loggersByName,
135       folly::StringPiece name);
136   LogCategory* createCategoryLocked(
137       LoggerNameMap& loggersByName,
138       folly::StringPiece name,
139       LogCategory* parent);
140
141   /**
142    * A map of LogCategory objects by name.
143    *
144    * Lookups can be performed using arbitrary StringPiece values that do not
145    * have to be in canonical form.
146    */
147   folly::Synchronized<LoggerNameMap> loggersByName_;
148 };
149 }