Improve performance

Signed-off-by: JCW <a1q123456@users.noreply.github.com>
This commit is contained in:
JCW
2025-09-01 18:15:20 +01:00
parent 37aa933462
commit dbb14191cb
12 changed files with 293 additions and 336 deletions

View File

@@ -68,8 +68,7 @@ private:
operator=(Sink const&) = delete; operator=(Sink const&) = delete;
void void
write(beast::severities::Severity level, std::string&& text) write(beast::severities::Severity level, std::string&& text) override;
override;
void void
writeAlways(beast::severities::Severity level, std::string&& text) writeAlways(beast::severities::Severity level, std::string&& text)
@@ -187,11 +186,19 @@ public:
beast::Journal::Sink& beast::Journal::Sink&
operator[](std::string const& name); operator[](std::string const& name);
template <typename AttributesFactory>
beast::Journal beast::Journal
journal( journal(std::string const& name, AttributesFactory&& factory)
std::string const& name, {
std::optional<beast::Journal::JsonLogAttributes> attributes = return beast::Journal{
std::nullopt); get(name), name, std::forward<AttributesFactory>(factory)};
}
beast::Journal
journal(std::string const& name)
{
return beast::Journal{get(name), name};
}
beast::severities::Severity beast::severities::Severity
threshold() const; threshold() const;

View File

@@ -22,15 +22,6 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <boost/asio/execution/allocator.hpp>
#include <boost/coroutine/attributes.hpp>
#include <boost/system/result.hpp>
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <deque>
#include <optional> #include <optional>
#include <source_location> #include <source_location>
#include <sstream> #include <sstream>
@@ -86,6 +77,99 @@ operator<<(std::ostream& os, LogParameter<T> const& param);
namespace beast { namespace beast {
class SimpleJsonWriter
{
public:
explicit SimpleJsonWriter(std::ostringstream& stream) : stream_(stream)
{
}
void
startObject() const
{
stream_ << "{";
}
void
endObject() const
{
stream_.seekp(-1, std::ios_base::end);
stream_ << "},";
}
void
writeKey(std::string_view key) const
{
writeString(key);
stream_.seekp(-1, std::ios_base::end);
stream_ << ":";
}
void
startArray() const
{
stream_ << "[";
}
void
endArray() const
{
stream_.seekp(-1, std::ios_base::end);
stream_ << "],";
}
void
writeString(std::string_view str) const
{
stream_ << "\"";
escape(str, stream_);
stream_ << "\",";
}
void
writeInt(std::int64_t val) const
{
stream_ << val << ",";
}
void
writeUInt(std::uint64_t val) const
{
stream_ << val << ",";
}
void
writeDouble(double val) const
{
stream_ << val << ",";
}
void
writeBool(bool val) const
{
stream_ << (val ? "true," : "false,");
}
void
writeNull() const
{
stream_ << "null" << ",";
}
void
writeRaw(std::string_view str) const
{
stream_ << str;
}
[[nodiscard]] std::string
str() const
{
auto result = stream_.str();
result.pop_back();
return result;
}
private:
static void
escape(std::string_view str, std::ostringstream& os)
{
// TODO: Support it
os << str;
}
std::ostringstream& stream_;
};
/** A namespace for easy access to logging severity values. */ /** A namespace for easy access to logging severity values. */
namespace severities { namespace severities {
/** Severity level / threshold of a Journal message. */ /** Severity level / threshold of a Journal message. */
@@ -136,94 +220,36 @@ public:
class Sink; class Sink;
class JsonLogAttributes
{
public:
using AttributeFields = rapidjson::Value;
JsonLogAttributes();
JsonLogAttributes(JsonLogAttributes const& other);
JsonLogAttributes&
operator=(JsonLogAttributes const& other);
void
setModuleName(std::string const& name);
void
combine(AttributeFields const& from);
AttributeFields&
contextValues()
{
return contextValues_;
}
[[nodiscard]] AttributeFields const&
contextValues() const
{
return contextValues_;
}
rapidjson::MemoryPoolAllocator<>&
allocator()
{
return allocator_;
}
private:
AttributeFields contextValues_;
rapidjson::MemoryPoolAllocator<> allocator_;
friend class Journal;
};
class JsonLogContext class JsonLogContext
{ {
rapidjson::StringBuffer buffer_; std::ostringstream buffer_;
rapidjson::Writer<rapidjson::StringBuffer> messageParamsWriter_; SimpleJsonWriter messageParamsWriter_;
std::optional<std::string> journalAttributesJson_;
public: public:
JsonLogContext() JsonLogContext() : messageParamsWriter_(buffer_)
: messageParamsWriter_(buffer_)
{ {
} }
rapidjson::Writer<rapidjson::StringBuffer>& SimpleJsonWriter&
writer() writer()
{ {
return messageParamsWriter_; return messageParamsWriter_;
} }
char const*
messageParams()
{
return buffer_.GetString();
}
std::optional<std::string>&
journalAttributesJson()
{
return journalAttributesJson_;
}
void void
reset( reset(
std::source_location location, std::source_location location,
severities::Severity severity, severities::Severity severity,
std::optional<std::string> const& journalAttributesJson) noexcept; std::string const& journalAttributesJson) noexcept;
}; };
private: private:
// Severity level / threshold of a Journal message. // Severity level / threshold of a Journal message.
using Severity = severities::Severity; using Severity = severities::Severity;
std::optional<JsonLogAttributes> m_attributes; std::string m_name;
std::optional<std::string> m_attributesJson; std::string m_attributesJson;
static std::optional<JsonLogAttributes> globalLogAttributes_; static std::string globalLogAttributesJson_;
static std::optional<std::string> globalLogAttributesJson_;
static std::mutex globalLogAttributesMutex_; static std::mutex globalLogAttributesMutex_;
static bool m_jsonLogsEnabled; static bool m_jsonLogsEnabled;
@@ -240,9 +266,6 @@ private:
static std::string static std::string
formatLog(std::string&& message); formatLog(std::string&& message);
void
rebuildAttributeJson();
public: public:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -471,42 +494,46 @@ public:
/** Journal has no default constructor. */ /** Journal has no default constructor. */
Journal() = delete; Journal() = delete;
template <typename TAttributesFactory> Journal(Journal const& other)
Journal( : m_name(other.m_name)
Journal const& other,
TAttributesFactory&& attributesFactory = nullptr)
: m_attributes(other.m_attributes)
, m_sink(other.m_sink)
, m_attributesJson(other.m_attributesJson) , m_attributesJson(other.m_attributesJson)
, m_sink(other.m_sink)
{ {
/*
if constexpr (!std::is_same_v<std::decay_t<TAttributesFactory>, std::nullptr_t>)
{
if (attributes.has_value())
{
if (m_attributes)
m_attributes->combine(attributes->contextValues_);
else
m_attributes = std::move(attributes);
} }
rebuildAttributeJson();
template <typename TAttributesFactory>
Journal(Journal const& other, TAttributesFactory&& attributesFactory)
: m_name(other.m_name), m_sink(other.m_sink)
{
std::ostringstream stream{other.m_attributesJson, std::ios_base::app};
SimpleJsonWriter writer{stream};
if (other.m_attributesJson.empty())
{
writer.startObject();
} }
*/ attributesFactory(writer);
m_attributesJson = stream.str();
} }
/** Create a journal that writes to the specified sink. */ /** Create a journal that writes to the specified sink. */
explicit Journal(Sink& sink, std::string const& name = {})
: m_name(name), m_sink(&sink)
{
}
/** Create a journal that writes to the specified sink. */
template <typename TAttributesFactory>
explicit Journal( explicit Journal(
Sink& sink, Sink& sink,
std::string const& name = {}, std::string const& name,
std::optional<JsonLogAttributes> attributes = std::nullopt) TAttributesFactory&& attributesFactory)
: m_sink(&sink) : m_name(name), m_sink(&sink)
{ {
if (attributes) std::ostringstream stream;
{ SimpleJsonWriter writer{stream};
m_attributes = std::move(attributes); writer.startObject();
m_attributes->setModuleName(name); attributesFactory(writer);
} m_attributesJson = stream.str();
rebuildAttributeJson();
} }
Journal& Journal&
@@ -516,8 +543,8 @@ public:
return *this; return *this;
m_sink = other.m_sink; m_sink = other.m_sink;
m_attributes = other.m_attributes; m_name = other.m_name;
rebuildAttributeJson(); m_attributesJson = other.m_attributesJson;
return *this; return *this;
} }
@@ -525,8 +552,8 @@ public:
operator=(Journal&& other) noexcept operator=(Journal&& other) noexcept
{ {
m_sink = other.m_sink; m_sink = other.m_sink;
m_attributes = std::move(other.m_attributes); m_name = std::move(other.m_name);
rebuildAttributeJson(); m_attributesJson = std::move(other.m_attributesJson);
return *this; return *this;
} }
@@ -539,7 +566,9 @@ public:
/** Returns a stream for this sink, with the specified severity level. */ /** Returns a stream for this sink, with the specified severity level. */
Stream Stream
stream(Severity level, std::source_location location = std::source_location::current()) const stream(
Severity level,
std::source_location location = std::source_location::current()) const
{ {
if (m_jsonLogsEnabled) if (m_jsonLogsEnabled)
initMessageContext(location, level); initMessageContext(location, level);
@@ -585,8 +614,6 @@ public:
Stream Stream
warn(std::source_location location = std::source_location::current()) const warn(std::source_location location = std::source_location::current()) const
{ {
char const* a = "a";
rapidjson::Value v{a, 1};
if (m_jsonLogsEnabled) if (m_jsonLogsEnabled)
initMessageContext(location, severities::kWarning); initMessageContext(location, severities::kWarning);
return {*m_sink, severities::kWarning}; return {*m_sink, severities::kWarning};
@@ -613,12 +640,26 @@ public:
resetGlobalAttributes() resetGlobalAttributes()
{ {
std::lock_guard lock(globalLogAttributesMutex_); std::lock_guard lock(globalLogAttributesMutex_);
globalLogAttributes_ = std::nullopt; globalLogAttributesJson_.clear();
globalLogAttributesJson_ = std::nullopt;
} }
template <typename TAttributesFactory>
static void static void
addGlobalAttributes(JsonLogAttributes globalLogAttributes); addGlobalAttributes(TAttributesFactory&& factory)
{
std::lock_guard lock(globalLogAttributesMutex_);
auto isEmpty = globalLogAttributesJson_.empty();
std::ostringstream stream{
std::move(globalLogAttributesJson_), std::ios_base::app};
SimpleJsonWriter writer{stream};
if (isEmpty)
{
writer.startObject();
}
factory(writer);
globalLogAttributesJson_ = stream.str();
}
}; };
#ifndef __INTELLISENSE__ #ifndef __INTELLISENSE__
@@ -728,25 +769,25 @@ using logwstream = basic_logstream<wchar_t>;
namespace ripple::log { namespace ripple::log {
namespace detail { namespace detail {
template <typename T, typename OutputStream> template <typename T>
void void
setJsonValue( setJsonValue(
rapidjson::Writer<OutputStream>& writer, beast::SimpleJsonWriter& writer,
char const* name, char const* name,
T&& value, T&& value,
std::ostream* outStream) std::ostream* outStream)
{ {
using ValueType = std::decay_t<T>; using ValueType = std::decay_t<T>;
writer.Key(name); writer.writeKey(name);
if constexpr (std::is_integral_v<ValueType>) if constexpr (std::is_integral_v<ValueType>)
{ {
if constexpr (std::is_signed_v<ValueType>) if constexpr (std::is_signed_v<ValueType>)
{ {
writer.Int64(value); writer.writeInt(value);
} }
else else
{ {
writer.Uint64(value); writer.writeUInt(value);
} }
if (outStream) if (outStream)
{ {
@@ -755,7 +796,7 @@ setJsonValue(
} }
else if constexpr (std::is_floating_point_v<ValueType>) else if constexpr (std::is_floating_point_v<ValueType>)
{ {
writer.Double(value); writer.writeDouble(value);
if (outStream) if (outStream)
{ {
@@ -764,15 +805,17 @@ setJsonValue(
} }
else if constexpr (std::is_same_v<ValueType, bool>) else if constexpr (std::is_same_v<ValueType, bool>)
{ {
writer.Bool(value); writer.writeBool(value);
if (outStream) if (outStream)
{ {
(*outStream) << value; (*outStream) << value;
} }
} }
else if constexpr (std::is_same_v<ValueType, char const*> || std::is_same_v<ValueType, char*>) else if constexpr (
std::is_same_v<ValueType, char const*> ||
std::is_same_v<ValueType, char*>)
{ {
writer.String(value); writer.writeString(value);
if (outStream) if (outStream)
{ {
(*outStream) << value; (*outStream) << value;
@@ -780,7 +823,7 @@ setJsonValue(
} }
else if constexpr (std::is_same_v<ValueType, std::string>) else if constexpr (std::is_same_v<ValueType, std::string>)
{ {
writer.String(value.c_str(), value.length()); writer.writeString(value);
if (outStream) if (outStream)
{ {
(*outStream) << value; (*outStream) << value;
@@ -791,11 +834,13 @@ setJsonValue(
std::ostringstream oss; std::ostringstream oss;
oss << value; oss << value;
writer.String(oss.str().c_str(), oss.str().length()); auto str = oss.str();
writer.writeString(str);
if (outStream) if (outStream)
{ {
(*outStream) << oss.str(); (*outStream) << str;
} }
} }
} }
@@ -847,13 +892,8 @@ template <typename... Pair>
[[nodiscard]] auto [[nodiscard]] auto
attributes(Pair&&... pairs) attributes(Pair&&... pairs)
{ {
return [&](rapidjson::Writer<rapidjson::Writer<char>>& writer) { return [&](beast::SimpleJsonWriter& writer) {
(detail::setJsonValue( (detail::setJsonValue(writer, pairs.first, pairs.second, nullptr), ...);
writer,
pairs.first,
pairs.second,
nullptr),
...);
}; };
} }

View File

@@ -56,9 +56,7 @@ Logs::Sink::write(beast::severities::Severity level, std::string&& text)
} }
void void
Logs::Sink::writeAlways( Logs::Sink::writeAlways(beast::severities::Severity level, std::string&& text)
beast::severities::Severity level,
std::string&& text)
{ {
logs_.write(level, partition_, std::move(text), console()); logs_.write(level, partition_, std::move(text), console());
} }
@@ -162,14 +160,6 @@ Logs::operator[](std::string const& name)
return get(name); return get(name);
} }
beast::Journal
Logs::journal(
std::string const& name,
std::optional<beast::Journal::JsonLogAttributes> attributes)
{
return beast::Journal{get(name), name, std::move(attributes)};
}
beast::severities::Severity beast::severities::Severity
Logs::threshold() const Logs::threshold() const
{ {

View File

@@ -19,10 +19,6 @@
#include <xrpl/beast/utility/Journal.h> #include <xrpl/beast/utility/Journal.h>
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <ios> #include <ios>
#include <ostream> #include <ostream>
#include <ranges> #include <ranges>
@@ -31,9 +27,7 @@
namespace beast { namespace beast {
std::optional<Journal::JsonLogAttributes> Journal::globalLogAttributes_; std::string Journal::globalLogAttributesJson_;
std::optional<std::string> Journal::globalLogAttributesJson_;
std::mutex Journal::globalLogAttributesMutex_; std::mutex Journal::globalLogAttributesMutex_;
bool Journal::m_jsonLogsEnabled = false; bool Journal::m_jsonLogsEnabled = false;
thread_local Journal::JsonLogContext Journal::currentJsonLogContext_{}; thread_local Journal::JsonLogContext Journal::currentJsonLogContext_{};
@@ -125,75 +119,11 @@ severities::to_string(Severity severity)
return ""; return "";
} }
Journal::JsonLogAttributes::JsonLogAttributes()
{
contextValues_.SetObject();
}
Journal::JsonLogAttributes::JsonLogAttributes(JsonLogAttributes const& other)
{
contextValues_.SetObject();
contextValues_.CopyFrom(other.contextValues_, allocator_);
}
Journal::JsonLogAttributes&
Journal::JsonLogAttributes::operator=(JsonLogAttributes const& other)
{
if (&other == this)
{
return *this;
}
contextValues_.CopyFrom(other.contextValues_, allocator_);
return *this;
}
void
Journal::JsonLogAttributes::setModuleName(std::string const& name)
{
contextValues_.AddMember(
rapidjson::StringRef("Module"),
rapidjson::Value{name.c_str(), allocator_},
allocator_);
}
void
Journal::JsonLogAttributes::combine(
AttributeFields const& from)
{
for (auto& member : from.GetObject())
{
contextValues_.RemoveMember(member.name);
contextValues_.AddMember(
rapidjson::Value{member.name, allocator_},
rapidjson::Value{member.value, allocator_},
allocator_);
}
}
void
Journal::addGlobalAttributes(JsonLogAttributes globalLogAttributes)
{
std::lock_guard lock(globalLogAttributesMutex_);
if (!globalLogAttributes_)
{
globalLogAttributes_ = JsonLogAttributes{};
}
globalLogAttributes_->combine(globalLogAttributes.contextValues());
rapidjson::StringBuffer buffer;
rapidjson::Writer writer{buffer};
globalLogAttributes_->contextValues().Accept(writer);
globalLogAttributesJson_ = {buffer.GetString()};
}
void void
Journal::JsonLogContext::reset( Journal::JsonLogContext::reset(
std::source_location location, std::source_location location,
severities::Severity severity, severities::Severity severity,
std::optional<std::string> const& journalAttributesJson) noexcept std::string const& journalAttributesJson) noexcept
{ {
struct ThreadIdStringInitializer struct ThreadIdStringInitializer
{ {
@@ -207,30 +137,45 @@ Journal::JsonLogContext::reset(
}; };
thread_local ThreadIdStringInitializer const threadId; thread_local ThreadIdStringInitializer const threadId;
journalAttributesJson_ = journalAttributesJson; buffer_.str("");
buffer_.Clear(); writer().startObject();
writer().StartObject(); if (!journalAttributesJson.empty())
{
writer().writeKey("JournalParams");
writer().writeRaw(journalAttributesJson);
writer().endObject();
}
writer().Key("Function"); if (!globalLogAttributesJson_.empty())
writer().String(location.function_name()); {
writer().writeKey("GlobalParams");
writer().writeRaw(globalLogAttributesJson_);
writer().endObject();
}
writer().Key("File"); writer().writeKey("MessageParams");
writer().String(location.file_name()); writer().startObject();
writer().Key("Line"); writer().writeKey("Function");
writer().Int64(location.line()); writer().writeString(location.function_name());
writer().Key("ThreadId"); writer().writeKey("File");
writer().String(threadId.value.c_str()); writer().writeString(location.file_name());
writer().writeKey("Line");
writer().writeInt(location.line());
writer().writeKey("ThreadId");
writer().writeString(threadId.value);
auto severityStr = to_string(severity); auto severityStr = to_string(severity);
writer().Key("Level"); writer().writeKey("Level");
writer().String(severityStr.c_str()); writer().writeString(severityStr);
writer().Key("Time"); writer().writeKey("Time");
writer().Uint64(std::chrono::duration_cast<std::chrono::milliseconds>( writer().writeUInt(std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()) std::chrono::system_clock::now().time_since_epoch())
.count()); .count());
} }
@@ -251,58 +196,16 @@ Journal::formatLog(std::string&& message)
return message; return message;
} }
currentJsonLogContext_.writer().EndObject(); auto& writer = currentJsonLogContext_.writer();
auto messageParams = currentJsonLogContext_.messageParams();
rapidjson::StringBuffer buffer; writer.endObject();
rapidjson::Writer writer(buffer);
writer.StartObject(); writer.writeKey("Message");
if (globalLogAttributesJson_.has_value()) writer.writeString(message);
{
writer.Key("GlobalParams");
writer.RawValue(
globalLogAttributesJson_->c_str(),
globalLogAttributesJson_->length(),
rapidjson::kObjectType);
}
if (currentJsonLogContext_.journalAttributesJson().has_value()) writer.endObject();
{
writer.Key("JournalParams");
writer.RawValue(
currentJsonLogContext_.journalAttributesJson()->c_str(),
currentJsonLogContext_.journalAttributesJson()->length(),
rapidjson::kObjectType);
}
writer.Key("MessageParams"); return writer.str();
writer.RawValue(messageParams, std::strlen(messageParams), rapidjson::kObjectType);
writer.Key("Message");
writer.String(message.c_str(), message.length());
writer.EndObject();
return {buffer.GetString()};
}
void
Journal::rebuildAttributeJson()
{
if (m_attributes.has_value())
{
rapidjson::StringBuffer buffer;
rapidjson::Writer writer{buffer};
m_attributes->contextValues().Accept(writer);
m_attributesJson = {buffer.GetString()};
}
else
{
m_attributesJson = {};
}
} }
void void

View File

@@ -59,8 +59,7 @@ public:
} }
void void
writeAlways(beast::severities::Severity level, std::string&& text) writeAlways(beast::severities::Severity level, std::string&& text) override
override
{ {
std::cout << clock_.now().time_since_epoch().count() << " " << text std::cout << clock_.now().time_since_epoch().count() << " " << text
<< std::endl; << std::endl;

View File

@@ -57,8 +57,7 @@ class CaptureLogs : public Logs
} }
void void
write(beast::severities::Severity level, std::string&& text) write(beast::severities::Severity level, std::string&& text) override
override
{ {
std::lock_guard lock(strmMutex_); std::lock_guard lock(strmMutex_);
strm_ << text; strm_ << text;

View File

@@ -45,8 +45,7 @@ class CheckMessageLogs : public Logs
} }
void void
write(beast::severities::Severity level, std::string&& text) write(beast::severities::Severity level, std::string&& text) override
override
{ {
if (text.find(owner_.msg_) != std::string::npos) if (text.find(owner_.msg_) != std::string::npos)
*owner_.pFound_ = true; *owner_.pFound_ = true;

View File

@@ -89,8 +89,7 @@ public:
} }
void void
write(beast::severities::Severity level, std::string&& text) write(beast::severities::Severity level, std::string&& text) override
override
{ {
if (level < threshold()) if (level < threshold())
return; return;

View File

@@ -52,14 +52,11 @@ public:
write(beast::severities::Severity level, std::string&& text) override; write(beast::severities::Severity level, std::string&& text) override;
void void
writeAlways(beast::severities::Severity level, std::string&& text) writeAlways(beast::severities::Severity level, std::string&& text) override;
override;
}; };
inline void inline void
SuiteJournalSink::write( SuiteJournalSink::write(beast::severities::Severity level, std::string&& text)
beast::severities::Severity level,
std::string&& text)
{ {
// Only write the string if the level at least equals the threshold. // Only write the string if the level at least equals the threshold.
if (level >= threshold()) if (level >= threshold())
@@ -145,8 +142,7 @@ public:
} }
inline void inline void
writeAlways(beast::severities::Severity level, std::string&& text) writeAlways(beast::severities::Severity level, std::string&& text) override
override
{ {
strm_ << text << std::endl; strm_ << text << std::endl;
} }

View File

@@ -49,8 +49,7 @@ private:
operator=(Sink const&) = delete; operator=(Sink const&) = delete;
void void
write(beast::severities::Severity level, std::string&& text) write(beast::severities::Severity level, std::string&& text) override
override
{ {
logs_.logStream_ << text; logs_.logStream_ << text;
} }
@@ -168,7 +167,8 @@ TEST_CASE("Global attributes")
CHECK(jsonLog["GlobalParams"].IsObject()); CHECK(jsonLog["GlobalParams"].IsObject());
CHECK(jsonLog["GlobalParams"].HasMember("Field1")); CHECK(jsonLog["GlobalParams"].HasMember("Field1"));
CHECK(jsonLog["GlobalParams"]["Field1"].IsString()); CHECK(jsonLog["GlobalParams"]["Field1"].IsString());
CHECK(jsonLog["GlobalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
jsonLog["GlobalParams"]["Field1"].GetString() == std::string{"Value1"});
beast::Journal::disableStructuredJournal(); beast::Journal::disableStructuredJournal();
} }
@@ -198,9 +198,14 @@ TEST_CASE("Global attributes inheritable")
CHECK(jsonLog.IsObject()); CHECK(jsonLog.IsObject());
CHECK(jsonLog["GlobalParams"].HasMember("Field1")); CHECK(jsonLog["GlobalParams"].HasMember("Field1"));
CHECK(jsonLog["GlobalParams"]["Field1"].IsString()); CHECK(jsonLog["GlobalParams"]["Field1"].IsString());
CHECK(jsonLog["GlobalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
CHECK(jsonLog["JournalParams"]["Field1"].GetString() == std::string{"Value3"}); jsonLog["GlobalParams"]["Field1"].GetString() == std::string{"Value1"});
CHECK(jsonLog["JournalParams"]["Field2"].GetString() == std::string{"Value2"}); CHECK(
jsonLog["JournalParams"]["Field1"].GetString() ==
std::string{"Value3"});
CHECK(
jsonLog["JournalParams"]["Field2"].GetString() ==
std::string{"Value2"});
beast::Journal::disableStructuredJournal(); beast::Journal::disableStructuredJournal();
} }
@@ -224,8 +229,7 @@ public:
} }
void void
writeAlways(beast::severities::Severity level, std::string&& text) writeAlways(beast::severities::Severity level, std::string&& text) override
override
{ {
strm_ << text; strm_ << text;
} }
@@ -235,9 +239,8 @@ class JsonLogStreamFixture
{ {
public: public:
JsonLogStreamFixture() JsonLogStreamFixture()
: sink_(beast::severities::kAll, logStream_), j_(sink_, "Test", log::attributes( : sink_(beast::severities::kAll, logStream_)
log::attr("Field1", "Value1") , j_(sink_, "Test", log::attributes(log::attr("Field1", "Value1")))
))
{ {
beast::Journal::enableStructuredJournal(); beast::Journal::enableStructuredJournal();
} }
@@ -267,9 +270,11 @@ private:
TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogFields") TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogFields")
{ {
beast::Journal::addGlobalAttributes(log::attributes(log::attr("Field2", "Value2"))); beast::Journal::addGlobalAttributes(
log::attributes(log::attr("Field2", "Value2")));
journal().debug() << std::boolalpha << true << std::noboolalpha << " Test " journal().debug() << std::boolalpha << true << std::noboolalpha << " Test "
<< std::boolalpha << false << log::field("Field3", "Value3"); << std::boolalpha << false
<< log::field("Field3", "Value3");
rapidjson::Document logValue; rapidjson::Document logValue;
logValue.Parse(stream().str().c_str()); logValue.Parse(stream().str().c_str());
@@ -484,7 +489,9 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributes")
logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone);
CHECK(logValue["JournalParams"]["Field1"].IsString()); CHECK(logValue["JournalParams"]["Field1"].IsString());
CHECK(logValue["JournalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
logValue["JournalParams"]["Field1"].GetString() ==
std::string{"Value1"});
CHECK(logValue["JournalParams"]["Field2"].IsNumber()); CHECK(logValue["JournalParams"]["Field2"].IsNumber());
CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2);
} }
@@ -494,9 +501,7 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributesInheritable")
beast::Journal j{ beast::Journal j{
journal(), journal(),
log::attributes(log::attr("Field1", "Value1"), log::attr("Field2", 2))}; log::attributes(log::attr("Field1", "Value1"), log::attr("Field2", 2))};
beast::Journal j2{ beast::Journal j2{j, log::attributes(log::attr("Field3", "Value3"))};
j,
log::attributes(log::attr("Field3", "Value3"), log::attr("Field2", 0))};
j2.debug() << "Test"; j2.debug() << "Test";
@@ -507,12 +512,15 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJournalAttributesInheritable")
logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone);
CHECK(logValue["JournalParams"]["Field1"].IsString()); CHECK(logValue["JournalParams"]["Field1"].IsString());
CHECK(logValue["JournalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
logValue["JournalParams"]["Field1"].GetString() ==
std::string{"Value1"});
CHECK(logValue["JournalParams"]["Field3"].IsString()); CHECK(logValue["JournalParams"]["Field3"].IsString());
CHECK(logValue["JournalParams"]["Field3"].GetString() == std::string{"Value3"}); CHECK(
// Field2 should be overwritten to 0 logValue["JournalParams"]["Field3"].GetString() ==
std::string{"Value3"});
CHECK(logValue["JournalParams"]["Field2"].IsNumber()); CHECK(logValue["JournalParams"]["Field2"].IsNumber());
CHECK(logValue["JournalParams"]["Field2"].GetInt() == 0); CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2);
} }
TEST_CASE_FIXTURE( TEST_CASE_FIXTURE(
@@ -522,9 +530,7 @@ TEST_CASE_FIXTURE(
beast::Journal j{ beast::Journal j{
journal(), journal(),
log::attributes(log::attr("Field1", "Value1"), log::attr("Field2", 2))}; log::attributes(log::attr("Field1", "Value1"), log::attr("Field2", 2))};
beast::Journal j2{ beast::Journal j2{j, log::attributes(log::attr("Field3", "Value3"))};
j,
log::attributes(log::attr("Field3", "Value3"), log::attr("Field2", 0))};
j2.debug() << "Test"; j2.debug() << "Test";
@@ -535,12 +541,16 @@ TEST_CASE_FIXTURE(
logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone);
CHECK(logValue["JournalParams"]["Field1"].IsString()); CHECK(logValue["JournalParams"]["Field1"].IsString());
CHECK(logValue["JournalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
logValue["JournalParams"]["Field1"].GetString() ==
std::string{"Value1"});
CHECK(logValue["JournalParams"]["Field3"].IsString()); CHECK(logValue["JournalParams"]["Field3"].IsString());
CHECK(logValue["JournalParams"]["Field3"].GetString() == std::string{"Value3"}); CHECK(
logValue["JournalParams"]["Field3"].GetString() ==
std::string{"Value3"});
// Field2 should be overwritten to 0 // Field2 should be overwritten to 0
CHECK(logValue["JournalParams"]["Field2"].IsNumber()); CHECK(logValue["JournalParams"]["Field2"].IsNumber());
CHECK(logValue["JournalParams"]["Field2"].GetInt() == 0); CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2);
} }
TEST_CASE_FIXTURE( TEST_CASE_FIXTURE(
@@ -564,7 +574,9 @@ TEST_CASE_FIXTURE(
logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone);
CHECK(logValue["JournalParams"]["Field1"].IsString()); CHECK(logValue["JournalParams"]["Field1"].IsString());
CHECK(logValue["JournalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
logValue["JournalParams"]["Field1"].GetString() ==
std::string{"Value1"});
CHECK(logValue["JournalParams"]["Field2"].IsNumber()); CHECK(logValue["JournalParams"]["Field2"].IsNumber());
CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2);
} }
@@ -590,7 +602,9 @@ TEST_CASE_FIXTURE(
logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone); logValue.GetParseError() == rapidjson::ParseErrorCode::kParseErrorNone);
CHECK(logValue["JournalParams"]["Field1"].IsString()); CHECK(logValue["JournalParams"]["Field1"].IsString());
CHECK(logValue["JournalParams"]["Field1"].GetString() == std::string{"Value1"}); CHECK(
logValue["JournalParams"]["Field1"].GetString() ==
std::string{"Value1"});
CHECK(logValue["JournalParams"]["Field2"].IsNumber()); CHECK(logValue["JournalParams"]["Field2"].IsNumber());
CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2); CHECK(logValue["JournalParams"]["Field2"].GetInt() == 2);
} }

View File

@@ -835,8 +835,11 @@ public:
beast::Journal beast::Journal
journal( journal(
std::string const& name, std::string const& name,
std::optional<beast::Journal::JsonLogAttributes> attributes = std::function<void(beast::SimpleJsonWriter&)> const& attributes)
std::nullopt) override; override;
beast::Journal
journal(std::string const& name) override;
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@@ -2173,11 +2176,17 @@ ApplicationImp::serverOkay(std::string& reason)
beast::Journal beast::Journal
ApplicationImp::journal( ApplicationImp::journal(
std::string const& name, std::string const& name,
std::optional<beast::Journal::JsonLogAttributes> attributes) std::function<void(beast::SimpleJsonWriter&)> const& attributes)
{ {
return logs_->journal(name, std::move(attributes)); return logs_->journal(name, std::move(attributes));
} }
beast::Journal
ApplicationImp::journal(std::string const& name)
{
return logs_->journal(name);
}
void void
ApplicationImp::setMaxDisallowedLedger() ApplicationImp::setMaxDisallowedLedger()
{ {

View File

@@ -260,8 +260,10 @@ public:
virtual beast::Journal virtual beast::Journal
journal( journal(
std::string const& name, std::string const& name,
std::optional<beast::Journal::JsonLogAttributes> attributes = std::function<void(beast::SimpleJsonWriter&)> const& attributes) = 0;
std::nullopt) = 0;
virtual beast::Journal
journal(std::string const& name) = 0;
/* Returns the number of file descriptors the application needs */ /* Returns the number of file descriptors the application needs */
virtual int virtual int