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.
16 #include <folly/Conv.h>
17 #include <folly/experimental/logging/LogCategory.h>
18 #include <folly/experimental/logging/Logger.h>
19 #include <folly/experimental/logging/LoggerDB.h>
20 #include <folly/experimental/logging/test/TestLogHandler.h>
21 #include <folly/portability/GTest.h>
23 using namespace folly;
24 using std::make_shared;
25 using std::shared_ptr;
28 TEST(LogCategory, effectiveLevel) {
29 LoggerDB db{LoggerDB::TESTING};
30 Logger foo{&db, "foo"};
31 Logger foo2{&db, "..foo.."};
32 EXPECT_EQ(foo.getCategory(), foo2.getCategory());
34 EXPECT_EQ(LogLevel::ERROR, db.getCategory("")->getLevel());
35 EXPECT_EQ(LogLevel::ERROR, db.getCategory("")->getEffectiveLevel());
37 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.bar")->getLevel());
38 EXPECT_EQ(LogLevel::ERROR, db.getCategory("foo.bar")->getEffectiveLevel());
40 db.setLevel(".foo", LogLevel::WARN);
41 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.bar")->getLevel());
42 EXPECT_EQ(LogLevel::WARN, db.getCategory("foo.bar")->getEffectiveLevel());
44 db.setLevel(".", LogLevel::DBG0);
45 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.bar")->getLevel());
46 EXPECT_EQ(LogLevel::DBG0, db.getCategory("foo.bar")->getEffectiveLevel());
48 // Test a newly created category under .foo
49 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.test.1234")->getLevel());
51 LogLevel::DBG0, db.getCategory("foo.test.1234")->getEffectiveLevel());
53 // Test a category that does not inherit its parent's log level
54 auto noinherit = db.getCategory("foo.test.noinherit");
55 EXPECT_EQ(LogLevel::MAX_LEVEL, noinherit->getLevel());
56 EXPECT_EQ(LogLevel::DBG0, noinherit->getEffectiveLevel());
57 noinherit->setLevel(LogLevel::CRITICAL, false);
58 EXPECT_EQ(LogLevel::CRITICAL, noinherit->getEffectiveLevel());
60 // Modify the root logger's level
61 db.setLevel(".", LogLevel::ERROR);
62 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.test.1234")->getLevel());
64 LogLevel::WARN, db.getCategory("foo.test.1234")->getEffectiveLevel());
65 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.test")->getLevel());
66 EXPECT_EQ(LogLevel::WARN, db.getCategory("foo.test")->getEffectiveLevel());
67 EXPECT_EQ(LogLevel::WARN, db.getCategory("foo")->getLevel());
68 EXPECT_EQ(LogLevel::WARN, db.getCategory("foo")->getEffectiveLevel());
70 LogLevel::CRITICAL, db.getCategory("foo.test.noinherit")->getLevel());
73 db.getCategory("foo.test.noinherit")->getEffectiveLevel());
75 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("bar.foo.test")->getLevel());
77 LogLevel::ERROR, db.getCategory("bar.foo.test")->getEffectiveLevel());
80 void testNumHandlers(size_t numHandlers) {
81 SCOPED_TRACE(folly::to<string>("num_handlers= ", numHandlers));
82 LoggerDB db{LoggerDB::TESTING};
83 db.setLevel("", LogLevel::DEBUG);
85 // Create the requested number of handlers for the foo.bar category
86 Logger foobar{&db, "foo.bar"};
87 std::vector<shared_ptr<TestLogHandler>> handlers;
88 for (size_t n = 0; n < numHandlers; ++n) {
89 handlers.emplace_back(make_shared<TestLogHandler>());
90 foobar.getCategory()->addHandler(handlers.back());
93 // Add a handler to the root category, to confirm that messages are
94 // propagated up to the root correctly.
95 auto rootHandler = make_shared<TestLogHandler>();
96 auto rootCategory = db.getCategory("");
97 rootCategory->addHandler(rootHandler);
99 // Log a message to a child of the foobar category
100 Logger childLogger{&db, "foo.bar.child"};
101 FB_LOG(childLogger, WARN, "beware");
103 // Make sure the message showed up at all of the handlers
104 for (const auto& handler : handlers) {
105 auto& messages = handler->getMessages();
106 ASSERT_EQ(1, messages.size());
107 EXPECT_EQ("beware", messages[0].first.getMessage());
108 EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
109 EXPECT_EQ(childLogger.getCategory(), messages[0].first.getCategory());
110 EXPECT_EQ(foobar.getCategory(), messages[0].second);
113 auto& messages = rootHandler->getMessages();
114 ASSERT_EQ(1, messages.size());
115 EXPECT_EQ("beware", messages[0].first.getMessage());
116 EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
117 EXPECT_EQ(childLogger.getCategory(), messages[0].first.getCategory());
118 EXPECT_EQ(rootCategory, messages[0].second);
121 // Now log a message directly to foobar
122 FB_LOG(foobar, DBG1, "just testing");
123 for (const auto& handler : handlers) {
124 auto& messages = handler->getMessages();
125 ASSERT_EQ(2, messages.size());
126 EXPECT_EQ("just testing", messages[1].first.getMessage());
127 EXPECT_EQ(LogLevel::DBG1, messages[1].first.getLevel());
128 EXPECT_EQ(foobar.getCategory(), messages[1].first.getCategory());
129 EXPECT_EQ(foobar.getCategory(), messages[1].second);
132 auto& messages = rootHandler->getMessages();
133 ASSERT_EQ(2, messages.size());
134 EXPECT_EQ("just testing", messages[1].first.getMessage());
135 EXPECT_EQ(LogLevel::DBG1, messages[1].first.getLevel());
136 EXPECT_EQ(foobar.getCategory(), messages[1].first.getCategory());
137 EXPECT_EQ(rootCategory, messages[1].second);
140 // Log a message to a sibling of foobar
141 Logger siblingLogger{&db, "foo.sibling"};
142 FB_LOG(siblingLogger, ERROR, "oh noes");
143 for (const auto& handler : handlers) {
144 auto& messages = handler->getMessages();
145 EXPECT_EQ(2, messages.size());
148 auto& messages = rootHandler->getMessages();
149 ASSERT_EQ(3, messages.size());
150 EXPECT_EQ("oh noes", messages[2].first.getMessage());
151 EXPECT_EQ(LogLevel::ERROR, messages[2].first.getLevel());
152 EXPECT_EQ(siblingLogger.getCategory(), messages[2].first.getCategory());
153 EXPECT_EQ(rootCategory, messages[2].second);
157 TEST(LogCategory, numHandlers) {
158 // The LogCategory code behaves differently when there are 5 or fewer
159 // LogHandlers attached to a category vs when ther are more.
161 // Test with fewer than 5 handlers.
165 // Test with exactly 5 handlers, as well as one fewer and one more, just
166 // to make sure we catch any corner cases.
171 // Test with significantly more than 5 handlers.