Commit 8c0d65fe authored by Victor Zverovich's avatar Victor Zverovich Committed by Facebook Github Bot

Remove unused legacy logging API

Summary:
Remove legacy logging API (`XLOGC` and friends) because it is not used anywhere
and is not fully safe being varargs-based. The code that needs to be converted
from `printf`-based logging can use fmt's `printf` API which is fully type-safe.

Reviewed By: simpkins

Differential Revision: D15036094

fbshipit-source-id: 3919e5d4eb7994ed0db4fa47bada111ab0dca505
parent 3beebd30
...@@ -577,7 +577,6 @@ if (BUILD_TESTS) ...@@ -577,7 +577,6 @@ if (BUILD_TESTS)
TEST log_message_test SOURCES LogMessageTest.cpp TEST log_message_test SOURCES LogMessageTest.cpp
TEST log_name_test SOURCES LogNameTest.cpp TEST log_name_test SOURCES LogNameTest.cpp
TEST log_stream_test SOURCES LogStreamTest.cpp TEST log_stream_test SOURCES LogStreamTest.cpp
TEST printf_test SOURCES PrintfTest.cpp
TEST rate_limiter_test SOURCES RateLimiterTest.cpp TEST rate_limiter_test SOURCES RateLimiterTest.cpp
TEST standard_log_handler_test SOURCES StandardLogHandlerTest.cpp TEST standard_log_handler_test SOURCES StandardLogHandlerTest.cpp
TEST xlog_test TEST xlog_test
......
...@@ -70,16 +70,6 @@ XLOGF(DBG1, "cannot engage {} thruster: {}", thruster.name(), err.what()); ...@@ -70,16 +70,6 @@ XLOGF(DBG1, "cannot engage {} thruster: {}", thruster.name(), err.what());
This uses [`folly::format()`](https://github.com/facebook/folly/blob/master/folly/docs/Format.md) This uses [`folly::format()`](https://github.com/facebook/folly/blob/master/folly/docs/Format.md)
to perform the formatting internally. to perform the formatting internally.
## `printf`-style string formatting
To help existing projects convert from older logging APIs, `XLOGC()` and
`FB_LOGC()` macros exist to support C-style `printf()` format strings.
You must include `folly/logging/printf.h` to access these macros.
```
XLOGC(DBG1, "failed to engage thruster %d: %s", thruster.number(), err.what());
```
# Log Category Selection # Log Category Selection
The `XLOG()` macro automatically selects a log category to log to based on the The `XLOG()` macro automatically selects a log category to log to based on the
......
/*
* Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/logging/printf.h>
#include <cstdarg>
#include <folly/Conv.h>
#include <folly/String.h>
namespace folly {
std::string loggingFormatPrintf(const char* format, ...) noexcept {
va_list ap;
va_start(ap, format);
SCOPE_EXIT {
va_end(ap);
};
try {
return stringVPrintf(format, ap);
} catch (const std::exception&) {
// We don't bother including the exception message here.
// The exceptions thrown by stringVPrintf() don't normally have much useful
// information regarding what precisely went wrong.
return folly::to<std::string>(
"error formatting printf-style log message: ", format);
}
}
} // namespace folly
/*
* Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
/*
* C-style printf-like macros for the logging library.
*
* These are defined in their own separate header file to discourage their use
* in new code. These macros make it somewhat easier to convert existing code
* using printf()-like statements to the logging library. However, new code
* should generally prefer to use one of the other macro forms instead
* (simple argument concatenation, folly::format based, or iostream-like).
*
* These use a "C" suffix to the macro name since these use C-style format
* syntax. (The "F" suffix is used for folly:format()-style.)
*/
#include <folly/logging/Logger.h>
#include <folly/logging/xlog.h>
namespace folly {
std::string loggingFormatPrintf(
FOLLY_PRINTF_FORMAT const char* format,
...) noexcept FOLLY_PRINTF_FORMAT_ATTR(1, 2);
} // namespace folly
/**
* Log a message to the specified logger using a printf-style format string.
*/
#define FB_LOGC(logger, level, fmt, ...) \
FB_LOG(logger, level, ::folly::loggingFormatPrintf(fmt, ##__VA_ARGS__))
/**
* Log a message to the file's default log category using a printf-style format
* string.
*/
#define XLOGC(level, fmt, ...) \
XLOG_IMPL( \
::folly::LogLevel::level, \
::folly::LogStreamProcessor::APPEND, \
::folly::loggingFormatPrintf(fmt, ##__VA_ARGS__))
/**
* Log a message using a printf-style format string if and only if the
* specified condition predicate evaluates to true. Note that the condition
* is *only* evaluated if the log-level check passes.
*/
#define XLOGC_IF(level, cond, fmt, ...) \
XLOG_IF_IMPL( \
::folly::LogLevel::level, \
cond, \
::folly::LogStreamProcessor::APPEND, \
::folly::loggingFormatPrintf(fmt, ##__VA_ARGS__))
/*
* Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/logging/printf.h>
#include <folly/logging/test/TestLogHandler.h>
#include <folly/portability/GTest.h>
using namespace folly;
using std::make_shared;
TEST(PrintfTest, printfStyleMacros) {
LoggerDB db{LoggerDB::TESTING};
Logger logger{&db, "test"};
auto* category = logger.getCategory();
auto handler = make_shared<TestLogHandler>();
category->addHandler(handler);
category->setLevel(LogLevel::DBG, true);
Logger foo{&db, "test.foo.bar"};
Logger foobar{&db, "test.foo.bar"};
Logger footest{&db, "test.foo.test"};
Logger footest1234{&db, "test.foo.test.1234"};
Logger other{&db, "test.other"};
db.setLevel("test", LogLevel::ERR);
db.setLevel("test.foo", LogLevel::DBG2);
db.setLevel("test.foo.test", LogLevel::DBG7);
auto& messages = handler->getMessages();
// test.other's effective level should be INFO, so a DBG0
// message to it should be discarded
FB_LOGC(other, DBG0, "this should be discarded: %d", 5);
ASSERT_EQ(0, messages.size());
// Disabled log messages should not evaluate their arguments
bool argumentEvaluated = false;
auto getValue = [&] {
argumentEvaluated = true;
return 5;
};
FB_LOGC(foobar, DBG3, "discarded message: %d", getValue());
EXPECT_FALSE(argumentEvaluated);
FB_LOGC(foobar, DBG1, "this message should pass: %d", getValue());
ASSERT_EQ(1, messages.size());
EXPECT_EQ("this message should pass: 5", messages[0].first.getMessage());
EXPECT_TRUE(argumentEvaluated);
messages.clear();
// The FB_LOGC() macro should work even if the format string does not contain
// any format sequences. Ideally people would just use FB_LOG() if they
// aren't actually formatting anything, but making FB_LOGC() work in this
// scenario still makes it easier for people to switch legacy printf-style
// code to FB_LOGC().
FB_LOGC(foobar, DBG1, "no actual format arguments");
ASSERT_EQ(1, messages.size());
EXPECT_EQ("no actual format arguments", messages[0].first.getMessage());
messages.clear();
// Similar checks with XLOGC()
auto* xlogCategory = XLOG_GET_CATEGORY();
xlogCategory->addHandler(handler);
xlogCategory->setLevel(LogLevel::DBG5, true);
argumentEvaluated = false;
XLOGC(DBG9, "failing log check: %d", getValue());
EXPECT_FALSE(argumentEvaluated);
XLOGC(DBG5, "passing log: %03d", getValue());
ASSERT_EQ(1, messages.size());
EXPECT_EQ("passing log: 005", messages[0].first.getMessage());
EXPECT_TRUE(argumentEvaluated);
messages.clear();
XLOGC(DBG1, "no xlog format arguments");
ASSERT_EQ(1, messages.size());
EXPECT_EQ("no xlog format arguments", messages[0].first.getMessage());
messages.clear();
XLOGC_IF(DBG1, false, "no xlog format arguments");
ASSERT_EQ(0, messages.size());
XLOGC_IF(DBG1, true, "xlog format arguments");
ASSERT_EQ(1, messages.size());
messages.clear();
argumentEvaluated = false;
XLOGC_IF(DBG1, true, "xlog format string %d", getValue());
ASSERT_EQ(1, messages.size());
EXPECT_TRUE(argumentEvaluated);
messages.clear();
argumentEvaluated = false;
XLOGC_IF(DBG1, false, "xlog format string %d", getValue());
ASSERT_EQ(0, messages.size());
EXPECT_FALSE(argumentEvaluated);
messages.clear();
// more complex conditional expressions
std::array<bool, 2> conds = {{false, true}};
for (unsigned i = 0; i < conds.size(); i++) {
for (unsigned j = 0; j < conds.size(); j++) {
argumentEvaluated = false;
XLOGC_IF(
DBG1, conds[i] && conds[j], "testing conditional %d", getValue());
EXPECT_EQ((conds[i] && conds[j]) ? 1 : 0, messages.size());
messages.clear();
if (conds[i] && conds[j]) {
EXPECT_TRUE(argumentEvaluated);
} else {
EXPECT_FALSE(argumentEvaluated);
}
argumentEvaluated = false;
XLOGC_IF(
DBG1, conds[i] || conds[j], "testing conditional %d", getValue());
EXPECT_EQ((conds[i] || conds[j]) ? 1 : 0, messages.size());
messages.clear();
if (conds[i] || conds[j]) {
EXPECT_TRUE(argumentEvaluated);
} else {
EXPECT_FALSE(argumentEvaluated);
}
}
}
XLOGC_IF(DBG1, 0x6 & 0x2, "More conditional 1");
EXPECT_EQ(1, messages.size());
messages.clear();
XLOGC_IF(DBG1, 0x6 | 0x2, "More conditional 2");
EXPECT_EQ(1, messages.size());
messages.clear();
XLOGC_IF(DBG1, 0x6 | 0x2 ? true : false, "More conditional 3");
EXPECT_EQ(1, messages.size());
messages.clear();
XLOGC_IF(DBG1, 0x6 | 0x2 ? true : false, "More conditional 3");
EXPECT_EQ(1, messages.size());
messages.clear();
XLOGC_IF(DBG1, 0x3 & 0x4 ? true : false, "More conditional 4");
EXPECT_EQ(0, messages.size());
messages.clear();
XLOGC_IF(DBG1, false ? true : false, "More conditional 5");
EXPECT_EQ(0, messages.size());
messages.clear();
// Errors attempting to format the message should not throw
FB_LOGC(footest1234, ERR, "width overflow: %999999999999999999999d", 5);
ASSERT_EQ(1, messages.size());
EXPECT_EQ(
"error formatting printf-style log message: "
"width overflow: %999999999999999999999d",
messages[0].first.getMessage());
messages.clear();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment