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::ERR, db.getCategory("")->getLevel());
35 EXPECT_EQ(LogLevel::ERR, db.getCategory("")->getEffectiveLevel());
37 EXPECT_EQ(LogLevel::MAX_LEVEL, db.getCategory("foo.bar")->getLevel());
38 EXPECT_EQ(LogLevel::ERR, 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::ERR);
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());
76 EXPECT_EQ(LogLevel::ERR, db.getCategory("bar.foo.test")->getEffectiveLevel());
79 void testNumHandlers(size_t numHandlers) {
80 SCOPED_TRACE(folly::to<string>("num_handlers= ", numHandlers));
81 LoggerDB db{LoggerDB::TESTING};
82 db.setLevel("", LogLevel::DEBUG);
84 // Create the requested number of handlers for the foo.bar category
85 Logger foobar{&db, "foo.bar"};
86 std::vector<shared_ptr<TestLogHandler>> handlers;
87 for (size_t n = 0; n < numHandlers; ++n) {
88 handlers.emplace_back(make_shared<TestLogHandler>());
89 foobar.getCategory()->addHandler(handlers.back());
92 // Add a handler to the root category, to confirm that messages are
93 // propagated up to the root correctly.
94 auto rootHandler = make_shared<TestLogHandler>();
95 auto rootCategory = db.getCategory("");
96 rootCategory->addHandler(rootHandler);
98 // Log a message to a child of the foobar category
99 Logger childLogger{&db, "foo.bar.child"};
100 FB_LOG(childLogger, WARN, "beware");
102 // Make sure the message showed up at all of the handlers
103 for (const auto& handler : handlers) {
104 auto& messages = handler->getMessages();
105 ASSERT_EQ(1, messages.size());
106 EXPECT_EQ("beware", messages[0].first.getMessage());
107 EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
108 EXPECT_EQ(childLogger.getCategory(), messages[0].first.getCategory());
109 EXPECT_EQ(foobar.getCategory(), messages[0].second);
112 auto& messages = rootHandler->getMessages();
113 ASSERT_EQ(1, messages.size());
114 EXPECT_EQ("beware", messages[0].first.getMessage());
115 EXPECT_EQ(LogLevel::WARN, messages[0].first.getLevel());
116 EXPECT_EQ(childLogger.getCategory(), messages[0].first.getCategory());
117 EXPECT_EQ(rootCategory, messages[0].second);
120 // Now log a message directly to foobar
121 FB_LOG(foobar, DBG1, "just testing");
122 for (const auto& handler : handlers) {
123 auto& messages = handler->getMessages();
124 ASSERT_EQ(2, messages.size());
125 EXPECT_EQ("just testing", messages[1].first.getMessage());
126 EXPECT_EQ(LogLevel::DBG1, messages[1].first.getLevel());
127 EXPECT_EQ(foobar.getCategory(), messages[1].first.getCategory());
128 EXPECT_EQ(foobar.getCategory(), messages[1].second);
131 auto& messages = rootHandler->getMessages();
132 ASSERT_EQ(2, messages.size());
133 EXPECT_EQ("just testing", messages[1].first.getMessage());
134 EXPECT_EQ(LogLevel::DBG1, messages[1].first.getLevel());
135 EXPECT_EQ(foobar.getCategory(), messages[1].first.getCategory());
136 EXPECT_EQ(rootCategory, messages[1].second);
139 // Log a message to a sibling of foobar
140 Logger siblingLogger{&db, "foo.sibling"};
141 FB_LOG(siblingLogger, ERR, "oh noes");
142 for (const auto& handler : handlers) {
143 auto& messages = handler->getMessages();
144 EXPECT_EQ(2, messages.size());
147 auto& messages = rootHandler->getMessages();
148 ASSERT_EQ(3, messages.size());
149 EXPECT_EQ("oh noes", messages[2].first.getMessage());
150 EXPECT_EQ(LogLevel::ERR, messages[2].first.getLevel());
151 EXPECT_EQ(siblingLogger.getCategory(), messages[2].first.getCategory());
152 EXPECT_EQ(rootCategory, messages[2].second);
156 TEST(LogCategory, numHandlers) {
157 // The LogCategory code behaves differently when there are 5 or fewer
158 // LogHandlers attached to a category vs when ther are more.
160 // Test with fewer than 5 handlers.
164 // Test with exactly 5 handlers, as well as one fewer and one more, just
165 // to make sure we catch any corner cases.
170 // Test with significantly more than 5 handlers.