Browse Source

Merge #10150: [rpc] Add logging rpc

7fd50c3 allow libevent logging to be updated during runtime (John Newbery)
5255aca [rpc] Add logging RPC (John Newbery)
4d9950d Set BCLog::LIBEVENT correctly for old libevent versions. (John Newbery)

Tree-SHA512: d6788a7205372c0528da71eca052910dfb055f2940ca884f422ff3db66e23a2b49c6a15b8f27d5255554fe5c5a928f5dd903fdc63b0bd6c8fa7783e77bb30fe8
0.15
Wladimir J. van der Laan 7 years ago
parent
commit
350b22497c
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 2
      src/Makefile.test.include
  2. 28
      src/httpserver.cpp
  3. 4
      src/httpserver.h
  4. 2
      src/rpc/client.cpp
  5. 71
      src/rpc/misc.cpp
  6. 17
      src/util.cpp
  7. 11
      src/util.h

2
src/Makefile.test.include

@ -97,7 +97,7 @@ endif @@ -97,7 +97,7 @@ endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS)
test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS)
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)

28
src/httpserver.cpp

@ -384,15 +384,13 @@ bool InitHTTPServer() @@ -384,15 +384,13 @@ bool InitHTTPServer()
// Redirect libevent's logging to our own log
event_set_log_callback(&libevent_log_cb);
#if LIBEVENT_VERSION_NUMBER >= 0x02010100
// If -debug=libevent, set full libevent debugging.
// Otherwise, disable all libevent debugging.
if (LogAcceptCategory(BCLog::LIBEVENT)) {
event_enable_debug_logging(EVENT_DBG_ALL);
} else {
event_enable_debug_logging(EVENT_DBG_NONE);
// Update libevent's log handling. Returns false if our version of
// libevent doesn't support debug logging, in which case we should
// clear the BCLog::LIBEVENT flag.
if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
logCategories &= ~BCLog::LIBEVENT;
}
#endif
#ifdef WIN32
evthread_use_windows_threads();
#else
@ -435,6 +433,20 @@ bool InitHTTPServer() @@ -435,6 +433,20 @@ bool InitHTTPServer()
return true;
}
bool UpdateHTTPServerLogging(bool enable) {
#if LIBEVENT_VERSION_NUMBER >= 0x02010100
if (enable) {
event_enable_debug_logging(EVENT_DBG_ALL);
} else {
event_enable_debug_logging(EVENT_DBG_NONE);
}
return true;
#else
// Can't update libevent logging if version < 02010100
return false;
#endif
}
std::thread threadHTTP;
std::future<bool> threadResult;

4
src/httpserver.h

@ -32,6 +32,10 @@ void InterruptHTTPServer(); @@ -32,6 +32,10 @@ void InterruptHTTPServer();
/** Stop HTTP server */
void StopHTTPServer();
/** Change logging level for libevent. Removes BCLog::LIBEVENT from logCategories if
* libevent doesn't support debug logging.*/
bool UpdateHTTPServerLogging(bool enable);
/** Handler for requests to a certain HTTP path */
typedef std::function<bool(HTTPRequest* req, const std::string &)> HTTPRequestHandler;
/** Register handler for prefix.

2
src/rpc/client.cpp

@ -113,6 +113,8 @@ static const CRPCConvertParam vRPCConvertParams[] = @@ -113,6 +113,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getmempoolancestors", 1, "verbose" },
{ "getmempooldescendants", 1, "verbose" },
{ "bumpfee", 1, "options" },
{ "logging", 0, "include" },
{ "logging", 1, "exclude" },
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },

71
src/rpc/misc.cpp

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
#include "clientversion.h"
#include "init.h"
#include "validation.h"
#include "httpserver.h"
#include "net.h"
#include "netbase.h"
#include "rpc/blockchain.h"
@ -555,6 +556,73 @@ UniValue getmemoryinfo(const JSONRPCRequest& request) @@ -555,6 +556,73 @@ UniValue getmemoryinfo(const JSONRPCRequest& request)
}
}
uint32_t getCategoryMask(UniValue cats) {
cats = cats.get_array();
uint32_t mask = 0;
for (unsigned int i = 0; i < cats.size(); ++i) {
uint32_t flag = 0;
std::string cat = cats[i].get_str();
if (!GetLogCategory(&flag, &cat)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
}
mask |= flag;
}
return mask;
}
UniValue logging(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2) {
throw std::runtime_error(
"logging [include,...] <exclude>\n"
"Gets and sets the logging configuration.\n"
"When called without an argument, returns the list of categories that are currently being debug logged.\n"
"When called with arguments, adds or removes categories from debug logging.\n"
"The valid logging categories are: " + ListLogCategories() + "\n"
"libevent logging is configured on startup and cannot be modified by this RPC during runtime."
"Arguments:\n"
"1. \"include\" (array of strings) add debug logging for these categories.\n"
"2. \"exclude\" (array of strings) remove debug logging for these categories.\n"
"\nResult: <categories> (string): a list of the logging categories that are active.\n"
"\nExamples:\n"
+ HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
+ HelpExampleRpc("logging", "[\"all\"], \"[libevent]\"")
);
}
uint32_t originalLogCategories = logCategories;
if (request.params.size() > 0 && request.params[0].isArray()) {
logCategories |= getCategoryMask(request.params[0]);
}
if (request.params.size() > 1 && request.params[1].isArray()) {
logCategories &= ~getCategoryMask(request.params[1]);
}
// Update libevent logging if BCLog::LIBEVENT has changed.
// If the library version doesn't allow it, UpdateHTTPServerLogging() returns false,
// in which case we should clear the BCLog::LIBEVENT flag.
// Throw an error if the user has explicitly asked to change only the libevent
// flag and it failed.
uint32_t changedLogCategories = originalLogCategories ^ logCategories;
if (changedLogCategories & BCLog::LIBEVENT) {
if (!UpdateHTTPServerLogging(logCategories & BCLog::LIBEVENT)) {
logCategories &= ~BCLog::LIBEVENT;
if (changedLogCategories == BCLog::LIBEVENT) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1.");
}
}
}
UniValue result(UniValue::VOBJ);
std::vector<CLogCategoryActive> vLogCatActive = ListActiveLogCategories();
for (const auto& logCatActive : vLogCatActive) {
result.pushKV(logCatActive.category, logCatActive.active);
}
return result;
}
UniValue echo(const JSONRPCRequest& request)
{
if (request.fHelp)
@ -581,7 +649,8 @@ static const CRPCCommand commands[] = @@ -581,7 +649,8 @@ static const CRPCCommand commands[] =
/* Not shown in help */
{ "hidden", "setmocktime", &setmocktime, true, {"timestamp"}},
{ "hidden", "echo", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
{ "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
{ "hidden", "echojson", &echo, true, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
{ "hidden", "logging", &logging, true, {"include", "exclude"}},
};
void RegisterMiscRPCCommands(CRPCTable &t)

17
src/util.cpp

@ -118,7 +118,7 @@ bool fLogIPs = DEFAULT_LOGIPS; @@ -118,7 +118,7 @@ bool fLogIPs = DEFAULT_LOGIPS;
std::atomic<bool> fReopenDebugLog(false);
CTranslationInterface translationInterface;
/** Log categories bitfield. Leveldb/libevent need special handling if their flags are changed at runtime. */
/** Log categories bitfield. */
std::atomic<uint32_t> logCategories(0);
/** Init OpenSSL library multithreading support */
@ -295,6 +295,21 @@ std::string ListLogCategories() @@ -295,6 +295,21 @@ std::string ListLogCategories()
return ret;
}
std::vector<CLogCategoryActive> ListActiveLogCategories()
{
std::vector<CLogCategoryActive> ret;
for (unsigned int i = 0; i < ARRAYLEN(LogCategories); i++) {
// Omit the special cases.
if (LogCategories[i].flag != BCLog::NONE && LogCategories[i].flag != BCLog::ALL) {
CLogCategoryActive catActive;
catActive.category = LogCategories[i].category;
catActive.active = LogAcceptCategory(LogCategories[i].flag);
ret.push_back(catActive);
}
}
return ret;
}
/**
* fStartedNewLine is a state variable held by the calling context that will
* suppress printing of the timestamp when multiple calls are made that don't

11
src/util.h

@ -69,6 +69,12 @@ inline std::string _(const char* psz) @@ -69,6 +69,12 @@ inline std::string _(const char* psz)
void SetupEnvironment();
bool SetupNetworking();
struct CLogCategoryActive
{
std::string category;
bool active;
};
namespace BCLog {
enum LogFlags : uint32_t {
NONE = 0,
@ -102,9 +108,12 @@ static inline bool LogAcceptCategory(uint32_t category) @@ -102,9 +108,12 @@ static inline bool LogAcceptCategory(uint32_t category)
return (logCategories.load(std::memory_order_relaxed) & category) != 0;
}
/** Returns a string with the supported log categories */
/** Returns a string with the log categories. */
std::string ListLogCategories();
/** Returns a vector of the active log categories. */
std::vector<CLogCategoryActive> ListActiveLogCategories();
/** Return true if str parses as a log category and set the flags in f */
bool GetLogCategory(uint32_t *f, const std::string *str);

Loading…
Cancel
Save