Skip to content

Commit

Permalink
Merge #1451: [RPC] Add logging RPC
Browse files Browse the repository at this point in the history
f66e50e [Doc] Add logging RPC to release notes (random-zebra)
bf55911 allow libevent logging to be updated during runtime (random-zebra)
ec43b51 Set BCLog::LIBEVENT correctly for old libevent versions. (random-zebra)
cbaf724 [rpc] Add logging rpc (random-zebra)

Pull request description:

  Implemented on top of:
  - [x] #1449
  - [x] #1437
  - [x] #1439
  - [x] #1450

  Backports bitcoin#10150

  > Adds an RPC to get/set active logging categories.
  First commit allows all categories except libevent to be reconfigured during runtime.
  Second commit modifies InitHTTPServer() to allow leveldb logging to be reconfigured during runtime.

ACKs for top commit:
  furszy:
    Really nice 👍 , ACK f66e50e .
  Fuzzbawls:
    ACK f66e50e

Tree-SHA512: 7b735628d341fb8661eb76f57dadc78e69ea63c62edb778450b3d9e3b7137ce06e08ceab835967b923401a9687e5b2605722a9f256e6ed85fc372a0e46086b8f
  • Loading branch information
random-zebra committed Apr 6, 2020
2 parents cb6d15a + f66e50e commit 1fa5156
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 12 deletions.
6 changes: 5 additions & 1 deletion doc/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ The following commands have been removed from the RPC interface:
### Newly introduced commands

The following new commands have been added to the RPC interface:
- `...`
- `logging` <br>Gets and sets the logging configuration.<br>
When called without an argument, returns the list of categories that are currently being debug logged.<br>
When called with arguments, adds or removes categories from debug logging.<br>
E.g. `logging "[\"all\"]" "[\"http\"]""`


Details about each new command can be found below.

Expand Down
29 changes: 21 additions & 8 deletions src/httpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,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);
#endif
// 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;
}

#ifdef WIN32
evthread_use_windows_threads();
#else
Expand Down Expand Up @@ -439,6 +438,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;

Expand Down
4 changes: 4 additions & 0 deletions src/httpserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(HTTPRequest* req, const std::string &)> HTTPRequestHandler;
/** Register handler for prefix.
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
{"listunspent", 1},
{"listunspent", 2},
{"listunspent", 3},
{"logging", 0},
{"logging", 1},
{"getblock", 1},
{"getblockheader", 1},
{"gettransaction", 1},
Expand Down
68 changes: 68 additions & 0 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "base58.h"
#include "clientversion.h"
#include "httpserver.h"
#include "init.h"
#include "main.h"
#include "masternode-sync.h"
Expand Down Expand Up @@ -582,6 +583,73 @@ UniValue setmocktime(const UniValue& params, bool fHelp)
return NullUniValue;
}

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 UniValue& params, bool fHelp)
{
if (fHelp || 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 (params.size() > 0 && params[0].isArray()) {
logCategories |= getCategoryMask(params[0]);
}

if (params.size() > 1 && params[1].isArray()) {
logCategories &= ~getCategoryMask(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;
}

#ifdef ENABLE_WALLET
UniValue getstakingstatus(const UniValue& params, bool fHelp)
{
Expand Down
1 change: 1 addition & 0 deletions src/rpc/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ static const CRPCCommand vRPCCommands[] =

/* Utility functions */
{"util", "createmultisig", &createmultisig, true, true, false},
{"util", "logging", &logging, true, false, false},
{"util", "validateaddress", &validateaddress, true, false, false}, /* uses wallet if enabled */
{"util", "verifymessage", &verifymessage, true, false, false},
{"util", "estimatefee", &estimatefee, true, true, false},
Expand Down
1 change: 1 addition & 0 deletions src/rpc/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ extern UniValue mnfinalbudget(const UniValue& params, bool fHelp);
extern UniValue checkbudgets(const UniValue& params, bool fHelp);

extern UniValue getinfo(const UniValue& params, bool fHelp); // in rpc/misc.cpp
extern UniValue logging(const UniValue& params, bool fHelp);
extern UniValue mnsync(const UniValue& params, bool fHelp);
extern UniValue spork(const UniValue& params, bool fHelp);
extern UniValue validateaddress(const UniValue& params, bool fHelp);
Expand Down
18 changes: 16 additions & 2 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,9 @@ bool fLogTimestamps = false;
bool fLogIPs = false;
volatile bool fReopenDebugLog = false;

/** 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 */
static RecursiveMutex** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line) NO_THREAD_SAFETY_ANALYSIS
Expand Down Expand Up @@ -319,6 +318,21 @@ static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine
return strStamped;
}

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;
}

int LogPrintStr(const std::string& str)
{
int ret = 0; // Returns total number of characters written
Expand Down
10 changes: 9 additions & 1 deletion src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ extern volatile bool fReopenDebugLog;
void SetupEnvironment();
bool SetupNetworking();

struct CLogCategoryActive
{
std::string category;
bool active;
};

namespace BCLog {
enum LogFlags : uint32_t {
NONE = 0,
Expand Down Expand Up @@ -95,8 +101,10 @@ 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);
/** Send a string to the log output */
Expand Down

0 comments on commit 1fa5156

Please sign in to comment.