|
|
|
|
@@ -1,16 +1,22 @@
|
|
|
|
|
#include <xrpl/basics/Logger.h>
|
|
|
|
|
|
|
|
|
|
#include <xrpl/basics/Log.h>
|
|
|
|
|
#include <xrpl/basics/Number.h>
|
|
|
|
|
#include <xrpl/basics/StructuredLogging.h>
|
|
|
|
|
#include <xrpl/protocol/XRPAmount.h>
|
|
|
|
|
|
|
|
|
|
#include <fmt/format.h>
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
#include <spdlog/common.h>
|
|
|
|
|
#include <spdlog/sinks/ostream_sink.h>
|
|
|
|
|
#include <spdlog/spdlog.h>
|
|
|
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <regex>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <string_view>
|
|
|
|
|
|
|
|
|
|
using namespace xrpl;
|
|
|
|
|
|
|
|
|
|
@@ -25,7 +31,7 @@ protected:
|
|
|
|
|
void
|
|
|
|
|
initLogging(bool jsonMode, Severity severity = Severity::TRC)
|
|
|
|
|
{
|
|
|
|
|
LoggingConfiguration config{
|
|
|
|
|
LoggingConfiguration const config{
|
|
|
|
|
.enableConsole = false,
|
|
|
|
|
.directory = std::nullopt,
|
|
|
|
|
.isAsync = false,
|
|
|
|
|
@@ -48,7 +54,7 @@ protected:
|
|
|
|
|
escapeRegex(std::string_view s)
|
|
|
|
|
{
|
|
|
|
|
std::string result;
|
|
|
|
|
for (char c : s)
|
|
|
|
|
for (char const c : s)
|
|
|
|
|
{
|
|
|
|
|
if (std::string_view(R"(\^$.|?*+()[]{}-)").find(c) != std::string_view::npos)
|
|
|
|
|
result += '\\';
|
|
|
|
|
@@ -98,7 +104,7 @@ protected:
|
|
|
|
|
TEST_F(LoggerFixture, plain_text_simple_message)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("TestChannel");
|
|
|
|
|
Logger const logger("TestChannel");
|
|
|
|
|
logger.info() << "hello world";
|
|
|
|
|
expectText("TestChannel", "NFO", "hello world");
|
|
|
|
|
}
|
|
|
|
|
@@ -106,7 +112,7 @@ TEST_F(LoggerFixture, plain_text_simple_message)
|
|
|
|
|
TEST_F(LoggerFixture, plain_text_multiple_values)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("TestChannel2");
|
|
|
|
|
Logger const logger("TestChannel2");
|
|
|
|
|
logger.info() << "count=" << 42 << " active=" << true;
|
|
|
|
|
expectText("TestChannel2", "NFO", "count=42 active=true");
|
|
|
|
|
}
|
|
|
|
|
@@ -114,7 +120,7 @@ TEST_F(LoggerFixture, plain_text_multiple_values)
|
|
|
|
|
TEST_F(LoggerFixture, plain_text_with_parameter)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("TestChannel3");
|
|
|
|
|
Logger const logger("TestChannel3");
|
|
|
|
|
logger.info() << "tx " << log::param("hash", "ABC");
|
|
|
|
|
// In plain text mode, parameter value is just streamed
|
|
|
|
|
expectText("TestChannel3", "NFO", "tx ABC");
|
|
|
|
|
@@ -125,7 +131,7 @@ TEST_F(LoggerFixture, plain_text_with_parameter)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_simple_message)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("JsonChannel");
|
|
|
|
|
Logger const logger("JsonChannel");
|
|
|
|
|
logger.info() << "hello world";
|
|
|
|
|
expectJson("JsonChannel", "NFO", "\"hello world\"");
|
|
|
|
|
}
|
|
|
|
|
@@ -133,7 +139,7 @@ TEST_F(LoggerFixture, json_mode_simple_message)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_with_parameters)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("JsonChannel2");
|
|
|
|
|
Logger const logger("JsonChannel2");
|
|
|
|
|
logger.info() << "processing " << log::param("tx_hash", std::string("ABC123"))
|
|
|
|
|
<< " amount=" << log::param("amount", 42);
|
|
|
|
|
expectJson(
|
|
|
|
|
@@ -146,7 +152,7 @@ TEST_F(LoggerFixture, json_mode_with_parameters)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_no_parameters)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("JsonChannel3");
|
|
|
|
|
Logger const logger("JsonChannel3");
|
|
|
|
|
logger.info() << "simple message";
|
|
|
|
|
expectJson("JsonChannel3", "NFO", "\"simple message\"");
|
|
|
|
|
}
|
|
|
|
|
@@ -154,7 +160,7 @@ TEST_F(LoggerFixture, json_mode_no_parameters)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_bool_parameter)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("JsonChannel4");
|
|
|
|
|
Logger const logger("JsonChannel4");
|
|
|
|
|
logger.info() << "status " << log::param("active", true);
|
|
|
|
|
expectJson("JsonChannel4", "NFO", "\"status true\", \"values\": {\"active\":true}");
|
|
|
|
|
}
|
|
|
|
|
@@ -165,7 +171,7 @@ TEST_F(LoggerFixture, severity_filtering)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false, Severity::WRN);
|
|
|
|
|
|
|
|
|
|
Logger logger("FilterChannel");
|
|
|
|
|
Logger const logger("FilterChannel");
|
|
|
|
|
logger.info() << "should not appear";
|
|
|
|
|
EXPECT_TRUE(output_.str().empty());
|
|
|
|
|
|
|
|
|
|
@@ -178,7 +184,7 @@ TEST_F(LoggerFixture, severity_filtering)
|
|
|
|
|
TEST_F(LoggerFixture, text_mode_xrp_amount)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("AmountChannel");
|
|
|
|
|
Logger const logger("AmountChannel");
|
|
|
|
|
logger.info() << "balance: " << XRPAmount{1000};
|
|
|
|
|
expectText("AmountChannel", "NFO", "balance: 1000");
|
|
|
|
|
}
|
|
|
|
|
@@ -186,7 +192,7 @@ TEST_F(LoggerFixture, text_mode_xrp_amount)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_xrp_amount)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("AmountChannel");
|
|
|
|
|
Logger const logger("AmountChannel");
|
|
|
|
|
logger.info() << "balance " << XRPAmount{500};
|
|
|
|
|
expectJson("AmountChannel", "NFO", "\"balance 500\"");
|
|
|
|
|
}
|
|
|
|
|
@@ -194,7 +200,7 @@ TEST_F(LoggerFixture, json_mode_xrp_amount)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_xrp_amount_parameter)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("AmountChannel");
|
|
|
|
|
Logger const logger("AmountChannel");
|
|
|
|
|
logger.info() << "tx" << log::param("fee", XRPAmount{10});
|
|
|
|
|
expectJson("AmountChannel", "NFO", "\"tx10\", \"values\": {\"fee\":\"10\"}");
|
|
|
|
|
}
|
|
|
|
|
@@ -202,7 +208,7 @@ TEST_F(LoggerFixture, json_mode_xrp_amount_parameter)
|
|
|
|
|
TEST_F(LoggerFixture, text_mode_number)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("NumberChannel");
|
|
|
|
|
Logger const logger("NumberChannel");
|
|
|
|
|
logger.info() << "result: " << Number{42};
|
|
|
|
|
expectText("NumberChannel", "NFO", "result: 42");
|
|
|
|
|
}
|
|
|
|
|
@@ -210,7 +216,7 @@ TEST_F(LoggerFixture, text_mode_number)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_number)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("NumberChannel");
|
|
|
|
|
Logger const logger("NumberChannel");
|
|
|
|
|
logger.info() << "value " << Number{25, -3};
|
|
|
|
|
expectJson("NumberChannel", "NFO", "\"value 0.025\"");
|
|
|
|
|
}
|
|
|
|
|
@@ -218,7 +224,7 @@ TEST_F(LoggerFixture, json_mode_number)
|
|
|
|
|
TEST_F(LoggerFixture, json_mode_number_parameter)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("NumberChannel");
|
|
|
|
|
Logger const logger("NumberChannel");
|
|
|
|
|
logger.info() << "calc" << log::param("rate", Number{100});
|
|
|
|
|
expectJson("NumberChannel", "NFO", "\"calc100\", \"values\": {\"rate\":\"100\"}");
|
|
|
|
|
}
|
|
|
|
|
@@ -228,7 +234,7 @@ TEST_F(LoggerFixture, json_mode_number_parameter)
|
|
|
|
|
TEST_F(LoggerFixture, severity_codes_in_default_format)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("Test");
|
|
|
|
|
Logger const logger("Test");
|
|
|
|
|
|
|
|
|
|
logger.trace() << "t";
|
|
|
|
|
logger.debug() << "d";
|
|
|
|
|
@@ -274,8 +280,8 @@ TEST_F(LoggerFixture, build_json_pattern_extends_existing)
|
|
|
|
|
TEST_F(LoggerFixture, child_logger_inherits_context_params)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger parent("Parent");
|
|
|
|
|
Logger child(parent, "Child", log::param("peer_id", std::string("abc")));
|
|
|
|
|
Logger const parent("Parent");
|
|
|
|
|
Logger const child(parent, "Child", log::param("peer_id", std::string("abc")));
|
|
|
|
|
child.info() << "hello";
|
|
|
|
|
expectJson("Child", "NFO", "\"hello\", \"values\": {\"peer_id\":\"abc\"}");
|
|
|
|
|
}
|
|
|
|
|
@@ -283,8 +289,8 @@ TEST_F(LoggerFixture, child_logger_inherits_context_params)
|
|
|
|
|
TEST_F(LoggerFixture, child_logger_merges_context_and_message_params)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger parent("Parent");
|
|
|
|
|
Logger child(parent, "Child", log::param("peer_id", std::string("abc")));
|
|
|
|
|
Logger const parent("Parent");
|
|
|
|
|
Logger const child(parent, "Child", log::param("peer_id", std::string("abc")));
|
|
|
|
|
child.info() << "event" << log::param("count", 42);
|
|
|
|
|
expectJson("Child", "NFO", "\"event42\", \"values\": {\"peer_id\":\"abc\",\"count\":42}");
|
|
|
|
|
}
|
|
|
|
|
@@ -292,9 +298,9 @@ TEST_F(LoggerFixture, child_logger_merges_context_and_message_params)
|
|
|
|
|
TEST_F(LoggerFixture, grandchild_logger_accumulates_context)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger root("Root");
|
|
|
|
|
Logger child(root, "Child", log::param("trace_id", std::string("t1")));
|
|
|
|
|
Logger grandchild(child, "Grandchild", log::param("span_id", std::string("s1")));
|
|
|
|
|
Logger const root("Root");
|
|
|
|
|
Logger const child(root, "Child", log::param("trace_id", std::string("t1")));
|
|
|
|
|
Logger const grandchild(child, "Grandchild", log::param("span_id", std::string("s1")));
|
|
|
|
|
grandchild.info() << "deep";
|
|
|
|
|
expectJson(
|
|
|
|
|
"Grandchild", "NFO", "\"deep\", \"values\": {\"trace_id\":\"t1\",\"span_id\":\"s1\"}");
|
|
|
|
|
@@ -303,8 +309,8 @@ TEST_F(LoggerFixture, grandchild_logger_accumulates_context)
|
|
|
|
|
TEST_F(LoggerFixture, context_params_in_text_mode)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger parent("Parent");
|
|
|
|
|
Logger child(parent, "Child", log::param("peer_id", std::string("abc")));
|
|
|
|
|
Logger const parent("Parent");
|
|
|
|
|
Logger const child(parent, "Child", log::param("peer_id", std::string("abc")));
|
|
|
|
|
child.info() << "hello";
|
|
|
|
|
// In text mode, context params are shown as [key=val] prefix
|
|
|
|
|
expectText("Child", "NFO", "[peer_id=abc] hello");
|
|
|
|
|
@@ -313,9 +319,9 @@ TEST_F(LoggerFixture, context_params_in_text_mode)
|
|
|
|
|
TEST_F(LoggerFixture, context_params_text_mode_multiple)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger root("Root");
|
|
|
|
|
Logger child(root, "Child", log::param("trace_id", std::string("t1")));
|
|
|
|
|
Logger grandchild(child, "GC", log::param("span_id", std::string("s1")));
|
|
|
|
|
Logger const root("Root");
|
|
|
|
|
Logger const child(root, "Child", log::param("trace_id", std::string("t1")));
|
|
|
|
|
Logger const grandchild(child, "GC", log::param("span_id", std::string("s1")));
|
|
|
|
|
grandchild.info() << "deep";
|
|
|
|
|
expectText("GC", "NFO", "[trace_id=t1 span_id=s1] deep");
|
|
|
|
|
}
|
|
|
|
|
@@ -325,7 +331,7 @@ TEST_F(LoggerFixture, context_params_text_mode_multiple)
|
|
|
|
|
TEST_F(LoggerFixture, scrubs_seed)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("Scrub");
|
|
|
|
|
Logger const logger("Scrub");
|
|
|
|
|
logger.info() << R"({"seed":"sEdTM1uX8pu2do5XvTnutH6HsouMaM2"})";
|
|
|
|
|
// 31 chars in the seed value → 31 asterisks
|
|
|
|
|
expectText("Scrub", "NFO", R"({"seed":"*******************************"})");
|
|
|
|
|
@@ -334,7 +340,7 @@ TEST_F(LoggerFixture, scrubs_seed)
|
|
|
|
|
TEST_F(LoggerFixture, scrubs_master_key)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("Scrub2");
|
|
|
|
|
Logger const logger("Scrub2");
|
|
|
|
|
logger.info() << R"({"master_key":"SOME_SECRET_VALUE"})";
|
|
|
|
|
expectText("Scrub2", "NFO", R"({"master_key":"*****************"})");
|
|
|
|
|
}
|
|
|
|
|
@@ -342,7 +348,7 @@ TEST_F(LoggerFixture, scrubs_master_key)
|
|
|
|
|
TEST_F(LoggerFixture, scrubs_passphrase)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("Scrub3");
|
|
|
|
|
Logger const logger("Scrub3");
|
|
|
|
|
logger.info() << R"({"passphrase":"my_secret_pass"})";
|
|
|
|
|
expectText("Scrub3", "NFO", R"({"passphrase":"**************"})");
|
|
|
|
|
}
|
|
|
|
|
@@ -350,7 +356,7 @@ TEST_F(LoggerFixture, scrubs_passphrase)
|
|
|
|
|
TEST_F(LoggerFixture, scrubs_seed_json_mode)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("ScrubJson");
|
|
|
|
|
Logger const logger("ScrubJson");
|
|
|
|
|
logger.info() << R"({"seed":"sEdTM1uX8pu2do5XvTnutH6HsouMaM2"})";
|
|
|
|
|
// In JSON mode the message is wrapped in quotes, but scrubbing still works
|
|
|
|
|
expectJson("ScrubJson", "NFO", "\"{\"seed\":\"*******************************\"}\"");
|
|
|
|
|
@@ -359,7 +365,7 @@ TEST_F(LoggerFixture, scrubs_seed_json_mode)
|
|
|
|
|
TEST_F(LoggerFixture, scrubs_master_key_json_mode)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("ScrubJson2");
|
|
|
|
|
Logger const logger("ScrubJson2");
|
|
|
|
|
logger.info() << R"({"master_key":"SOME_SECRET_VALUE"})";
|
|
|
|
|
expectJson("ScrubJson2", "NFO", "\"{\"master_key\":\"*****************\"}\"");
|
|
|
|
|
}
|
|
|
|
|
@@ -369,7 +375,7 @@ TEST_F(LoggerFixture, scrubs_master_key_json_mode)
|
|
|
|
|
TEST_F(LoggerFixture, truncates_oversized_message)
|
|
|
|
|
{
|
|
|
|
|
initLogging(false);
|
|
|
|
|
Logger logger("Trunc");
|
|
|
|
|
Logger const logger("Trunc");
|
|
|
|
|
// 12 * 1024 = 12288 max chars; create a message larger than that
|
|
|
|
|
static constexpr std::size_t kMAX = 12 * 1024;
|
|
|
|
|
std::string const bigMessage(13000, 'x');
|
|
|
|
|
@@ -384,7 +390,7 @@ TEST_F(LoggerFixture, truncates_oversized_message)
|
|
|
|
|
TEST_F(LoggerFixture, truncates_oversized_message_json)
|
|
|
|
|
{
|
|
|
|
|
initLogging(true);
|
|
|
|
|
Logger logger("Trunc");
|
|
|
|
|
Logger const logger("Trunc");
|
|
|
|
|
static constexpr std::size_t kMAX = 12 * 1024;
|
|
|
|
|
std::string const bigMessage(13000, 'x');
|
|
|
|
|
logger.info() << bigMessage << log::param("key", std::string("value"));
|
|
|
|
|
|