mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Compare commits
9 Commits
a1q123456/
...
a1q123456/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3eaf9564f6 | ||
|
|
e9d8412161 | ||
|
|
d4c6b97a51 | ||
|
|
7472e0f926 | ||
|
|
7cec53e248 | ||
|
|
59b5a1a26c | ||
|
|
fc1fc894cd | ||
|
|
cb352f5ec6 | ||
|
|
21a5260bb7 |
@@ -52,6 +52,7 @@ target_link_libraries(xrpl.libpb
|
||||
add_library(xrpl.imports.main INTERFACE)
|
||||
|
||||
find_package(RapidJSON)
|
||||
find_package(yyjson)
|
||||
|
||||
target_link_libraries(xrpl.imports.main
|
||||
INTERFACE
|
||||
@@ -77,7 +78,7 @@ add_module(xrpl beast)
|
||||
target_link_libraries(xrpl.libxrpl.beast PUBLIC
|
||||
xrpl.imports.main
|
||||
xrpl.libpb
|
||||
rapidjson
|
||||
yyjson::yyjson
|
||||
)
|
||||
|
||||
# Level 02
|
||||
|
||||
@@ -30,7 +30,8 @@ class Xrpl(ConanFile):
|
||||
'openssl/3.5.2',
|
||||
'soci/4.0.3',
|
||||
'zlib/1.3.1',
|
||||
"rapidjson/1.1.0"
|
||||
"rapidjson/1.1.0",
|
||||
"yyjson/0.10.0"
|
||||
]
|
||||
|
||||
test_requires = [
|
||||
|
||||
@@ -68,11 +68,11 @@ private:
|
||||
operator=(Sink const&) = delete;
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
write(beast::severities::Severity level, std::string&& text)
|
||||
override;
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override;
|
||||
};
|
||||
|
||||
@@ -156,9 +156,10 @@ private:
|
||||
private:
|
||||
std::unique_ptr<std::ofstream> m_stream;
|
||||
boost::filesystem::path m_path;
|
||||
std::mutex mutable fileMutex_;
|
||||
};
|
||||
|
||||
std::mutex mutable mutex_;
|
||||
std::mutex mutable sinkSetMutex_;
|
||||
std::map<
|
||||
std::string,
|
||||
std::unique_ptr<beast::Journal::Sink>,
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <boost/json.hpp>
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <source_location>
|
||||
#include <sstream>
|
||||
@@ -97,7 +97,7 @@ enum Severity {
|
||||
kNone = kDisabled
|
||||
};
|
||||
|
||||
std::string
|
||||
std::string_view
|
||||
to_string(Severity severity);
|
||||
} // namespace severities
|
||||
|
||||
@@ -129,23 +129,26 @@ public:
|
||||
ripple::log::LogParameter<T> const& param);
|
||||
|
||||
class Sink;
|
||||
|
||||
class JsonLogAttributes
|
||||
{
|
||||
public:
|
||||
using AttributeFields = rapidjson::Value;
|
||||
using AttributeFields = boost::json::value;
|
||||
|
||||
JsonLogAttributes();
|
||||
JsonLogAttributes(JsonLogAttributes const& other);
|
||||
JsonLogAttributes(JsonLogAttributes&& other);
|
||||
|
||||
JsonLogAttributes&
|
||||
operator=(JsonLogAttributes const& other);
|
||||
|
||||
JsonLogAttributes&
|
||||
operator=(JsonLogAttributes&& other);
|
||||
|
||||
void
|
||||
setModuleName(std::string const& name);
|
||||
|
||||
[[nodiscard]] static JsonLogAttributes
|
||||
combine(AttributeFields const& a, AttributeFields const& b);
|
||||
void
|
||||
combine(AttributeFields const& from);
|
||||
|
||||
AttributeFields&
|
||||
contextValues()
|
||||
@@ -159,35 +162,43 @@ public:
|
||||
return contextValues_;
|
||||
}
|
||||
|
||||
rapidjson::MemoryPoolAllocator<>&
|
||||
allocator()
|
||||
{
|
||||
return allocator_;
|
||||
}
|
||||
|
||||
private:
|
||||
AttributeFields contextValues_;
|
||||
rapidjson::MemoryPoolAllocator<> allocator_;
|
||||
|
||||
friend class Journal;
|
||||
};
|
||||
|
||||
struct JsonLogContext
|
||||
class JsonLogContext
|
||||
{
|
||||
std::source_location location = {};
|
||||
rapidjson::Value messageParams;
|
||||
rapidjson::MemoryPoolAllocator<> allocator;
|
||||
std::source_location location_ = {};
|
||||
boost::json::value attributes_;
|
||||
|
||||
public:
|
||||
JsonLogContext() = default;
|
||||
|
||||
void
|
||||
reset(std::source_location location_) noexcept
|
||||
boost::json::value&
|
||||
messageParams()
|
||||
{
|
||||
location = location_;
|
||||
messageParams = rapidjson::Value{};
|
||||
messageParams.SetObject();
|
||||
allocator.Clear();
|
||||
return attributes_.as_object()["Params"];
|
||||
}
|
||||
|
||||
boost::json::value&
|
||||
attributes()
|
||||
{
|
||||
return attributes_;
|
||||
}
|
||||
|
||||
std::source_location&
|
||||
location()
|
||||
{
|
||||
return location_;
|
||||
}
|
||||
|
||||
void
|
||||
reset(
|
||||
std::source_location location,
|
||||
severities::Severity severity,
|
||||
std::optional<JsonLogAttributes> const& attributes) noexcept;
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -204,14 +215,13 @@ private:
|
||||
// Invariant: m_sink always points to a valid Sink
|
||||
Sink* m_sink = nullptr;
|
||||
|
||||
static void
|
||||
initMessageContext(std::source_location location);
|
||||
void
|
||||
initMessageContext(
|
||||
std::source_location location,
|
||||
severities::Severity severity) const;
|
||||
|
||||
static std::string
|
||||
formatLog(
|
||||
std::string const& message,
|
||||
severities::Severity severity,
|
||||
std::optional<JsonLogAttributes> const& attributes = std::nullopt);
|
||||
formatLog(std::string&& message);
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -265,7 +275,7 @@ public:
|
||||
level is below the current threshold().
|
||||
*/
|
||||
virtual void
|
||||
write(Severity level, std::string const& text) = 0;
|
||||
write(Severity level, std::string&& text) = 0;
|
||||
|
||||
/** Bypass filter and write text to the sink at the specified severity.
|
||||
* Always write the message, but maintain the same formatting as if
|
||||
@@ -275,7 +285,7 @@ public:
|
||||
* @param text Text to write to sink.
|
||||
*/
|
||||
virtual void
|
||||
writeAlways(Severity level, std::string const& text) = 0;
|
||||
writeAlways(Severity level, std::string&& text) = 0;
|
||||
|
||||
private:
|
||||
Severity thresh_;
|
||||
@@ -304,25 +314,16 @@ public:
|
||||
{
|
||||
public:
|
||||
ScopedStream(ScopedStream const& other)
|
||||
: ScopedStream(other.m_attributes, other.m_sink, other.m_level)
|
||||
: ScopedStream(other.m_sink, other.m_level)
|
||||
{
|
||||
}
|
||||
|
||||
ScopedStream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Sink& sink,
|
||||
Severity level);
|
||||
ScopedStream(Sink& sink, Severity level);
|
||||
|
||||
template <typename T>
|
||||
ScopedStream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Stream const& stream,
|
||||
T const& t);
|
||||
ScopedStream(Stream const& stream, T const& t);
|
||||
|
||||
ScopedStream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Stream const& stream,
|
||||
std::ostream& manip(std::ostream&));
|
||||
ScopedStream(Stream const& stream, std::ostream& manip(std::ostream&));
|
||||
|
||||
ScopedStream&
|
||||
operator=(ScopedStream const&) = delete;
|
||||
@@ -343,7 +344,6 @@ public:
|
||||
operator<<(T const& t) const;
|
||||
|
||||
private:
|
||||
std::optional<JsonLogAttributes> m_attributes;
|
||||
Sink& m_sink;
|
||||
Severity const m_level;
|
||||
std::ostringstream mutable m_ostream;
|
||||
@@ -378,11 +378,7 @@ public:
|
||||
|
||||
Constructor is inlined so checking active() very inexpensive.
|
||||
*/
|
||||
Stream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Sink& sink,
|
||||
Severity level)
|
||||
: m_attributes(std::move(attributes)), m_sink(sink), m_level(level)
|
||||
Stream(Sink& sink, Severity level) : m_sink(sink), m_level(level)
|
||||
{
|
||||
XRPL_ASSERT(
|
||||
m_level < severities::kDisabled,
|
||||
@@ -390,8 +386,7 @@ public:
|
||||
}
|
||||
|
||||
/** Construct or copy another Stream. */
|
||||
Stream(Stream const& other)
|
||||
: Stream(other.m_attributes, other.m_sink, other.m_level)
|
||||
Stream(Stream const& other) : Stream(other.m_sink, other.m_level)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -438,7 +433,6 @@ public:
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
std::optional<JsonLogAttributes> m_attributes;
|
||||
Sink& m_sink;
|
||||
Severity m_level;
|
||||
};
|
||||
@@ -460,18 +454,15 @@ public:
|
||||
Journal(
|
||||
Journal const& other,
|
||||
std::optional<JsonLogAttributes> attributes = std::nullopt)
|
||||
: m_sink(other.m_sink)
|
||||
: m_attributes(other.m_attributes)
|
||||
, m_sink(other.m_sink)
|
||||
{
|
||||
if (attributes.has_value())
|
||||
m_attributes = std::move(attributes.value());
|
||||
if (other.m_attributes.has_value())
|
||||
{
|
||||
if (m_attributes.has_value())
|
||||
m_attributes = JsonLogAttributes::combine(
|
||||
other.m_attributes->contextValues_,
|
||||
m_attributes->contextValues_);
|
||||
if (m_attributes)
|
||||
m_attributes->combine(attributes->contextValues_);
|
||||
else
|
||||
m_attributes = other.m_attributes;
|
||||
m_attributes = std::move(attributes);
|
||||
}
|
||||
}
|
||||
/** Create a journal that writes to the specified sink. */
|
||||
@@ -516,9 +507,11 @@ public:
|
||||
|
||||
/** Returns a stream for this sink, with the specified severity level. */
|
||||
Stream
|
||||
stream(Severity level) const
|
||||
stream(Severity level, std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
return Stream(m_attributes, *m_sink, level);
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location, level);
|
||||
return Stream(*m_sink, level);
|
||||
}
|
||||
|
||||
/** Returns `true` if any message would be logged at this severity level.
|
||||
@@ -537,50 +530,48 @@ public:
|
||||
trace(std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location);
|
||||
return {m_attributes, *m_sink, severities::kTrace};
|
||||
initMessageContext(location, severities::kTrace);
|
||||
return {*m_sink, severities::kTrace};
|
||||
}
|
||||
|
||||
Stream
|
||||
debug(std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location);
|
||||
return {m_attributes, *m_sink, severities::kDebug};
|
||||
initMessageContext(location, severities::kDebug);
|
||||
return {*m_sink, severities::kDebug};
|
||||
}
|
||||
|
||||
Stream
|
||||
info(std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location);
|
||||
return {m_attributes, *m_sink, severities::kInfo};
|
||||
initMessageContext(location, severities::kInfo);
|
||||
return {*m_sink, severities::kInfo};
|
||||
}
|
||||
|
||||
Stream
|
||||
warn(std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
char const* a = "a";
|
||||
rapidjson::Value v{a, 1};
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location);
|
||||
return {m_attributes, *m_sink, severities::kWarning};
|
||||
initMessageContext(location, severities::kWarning);
|
||||
return {*m_sink, severities::kWarning};
|
||||
}
|
||||
|
||||
Stream
|
||||
error(std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location);
|
||||
return {m_attributes, *m_sink, severities::kError};
|
||||
initMessageContext(location, severities::kError);
|
||||
return {*m_sink, severities::kError};
|
||||
}
|
||||
|
||||
Stream
|
||||
fatal(std::source_location location = std::source_location::current()) const
|
||||
{
|
||||
if (m_jsonLogsEnabled)
|
||||
initMessageContext(location);
|
||||
return {m_attributes, *m_sink, severities::kFatal};
|
||||
initMessageContext(location, severities::kFatal);
|
||||
return {*m_sink, severities::kFatal};
|
||||
}
|
||||
/** @} */
|
||||
|
||||
@@ -599,9 +590,7 @@ public:
|
||||
{
|
||||
globalLogAttributes_ = JsonLogAttributes{};
|
||||
}
|
||||
globalLogAttributes_ = JsonLogAttributes::combine(
|
||||
globalLogAttributes_->contextValues(),
|
||||
globalLogAttributes.contextValues());
|
||||
globalLogAttributes_->combine(globalLogAttributes.contextValues());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -617,11 +606,8 @@ static_assert(std::is_nothrow_destructible<Journal>::value == true, "");
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
Journal::ScopedStream::ScopedStream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Stream const& stream,
|
||||
T const& t)
|
||||
: ScopedStream(std::move(attributes), stream.sink(), stream.level())
|
||||
Journal::ScopedStream::ScopedStream(Stream const& stream, T const& t)
|
||||
: ScopedStream(stream.sink(), stream.level())
|
||||
{
|
||||
m_ostream << t;
|
||||
}
|
||||
@@ -640,7 +626,7 @@ template <typename T>
|
||||
Journal::ScopedStream
|
||||
Journal::Stream::operator<<(T const& t) const
|
||||
{
|
||||
return {m_attributes, *this, t};
|
||||
return {*this, t};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -715,39 +701,21 @@ using logwstream = basic_logstream<wchar_t>;
|
||||
namespace ripple::log {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
setJsonValue(
|
||||
rapidjson::Value& object,
|
||||
rapidjson::MemoryPoolAllocator<>& allocator,
|
||||
boost::json::value& object,
|
||||
char const* name,
|
||||
T&& value,
|
||||
std::ostream* outStream)
|
||||
{
|
||||
using ValueType = std::decay_t<T>;
|
||||
rapidjson::Value jsonValue;
|
||||
if constexpr (std::constructible_from<
|
||||
rapidjson::Value,
|
||||
ValueType,
|
||||
rapidjson::MemoryPoolAllocator<>&>)
|
||||
auto& root = object.as_object();
|
||||
|
||||
if constexpr (std::constructible_from<boost::json::value, ValueType>)
|
||||
{
|
||||
jsonValue = rapidjson::Value{value, allocator};
|
||||
if (outStream)
|
||||
{
|
||||
(*outStream) << value;
|
||||
}
|
||||
}
|
||||
else if constexpr (std::constructible_from<rapidjson::Value, ValueType>)
|
||||
{
|
||||
jsonValue = rapidjson::Value{value};
|
||||
if (outStream)
|
||||
{
|
||||
(*outStream) << value;
|
||||
}
|
||||
}
|
||||
else if constexpr (std::same_as<ValueType, std::string>)
|
||||
{
|
||||
jsonValue = rapidjson::Value{value.c_str(), allocator};
|
||||
root[name] = std::forward<T>(value);
|
||||
if (outStream)
|
||||
{
|
||||
(*outStream) << value;
|
||||
@@ -758,16 +726,13 @@ setJsonValue(
|
||||
std::ostringstream oss;
|
||||
oss << value;
|
||||
|
||||
jsonValue = rapidjson::Value{oss.str().c_str(), allocator};
|
||||
root[name] = oss.str();
|
||||
|
||||
if (outStream)
|
||||
{
|
||||
(*outStream) << oss.str();
|
||||
}
|
||||
}
|
||||
|
||||
object.AddMember(
|
||||
rapidjson::StringRef(name), std::move(jsonValue), allocator);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
@@ -778,8 +743,7 @@ operator<<(std::ostream& os, LogParameter<T> const& param)
|
||||
if (!beast::Journal::m_jsonLogsEnabled)
|
||||
return os;
|
||||
detail::setJsonValue(
|
||||
beast::Journal::currentJsonLogContext_.messageParams,
|
||||
beast::Journal::currentJsonLogContext_.allocator,
|
||||
beast::Journal::currentJsonLogContext_.messageParams(),
|
||||
param.name_,
|
||||
param.value_,
|
||||
&os);
|
||||
@@ -793,8 +757,7 @@ operator<<(std::ostream& os, LogField<T> const& param)
|
||||
if (!beast::Journal::m_jsonLogsEnabled)
|
||||
return os;
|
||||
detail::setJsonValue(
|
||||
beast::Journal::currentJsonLogContext_.messageParams,
|
||||
beast::Journal::currentJsonLogContext_.allocator,
|
||||
beast::Journal::currentJsonLogContext_.messageParams(),
|
||||
param.name_,
|
||||
param.value_,
|
||||
nullptr);
|
||||
@@ -822,11 +785,7 @@ attributes(Pair&&... pairs)
|
||||
beast::Journal::JsonLogAttributes result;
|
||||
|
||||
(detail::setJsonValue(
|
||||
result.contextValues(),
|
||||
result.allocator(),
|
||||
pairs.first,
|
||||
pairs.second,
|
||||
nullptr),
|
||||
result.contextValues(), pairs.first, pairs.second, nullptr),
|
||||
...);
|
||||
|
||||
return result;
|
||||
|
||||
@@ -88,14 +88,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
write(beast::severities::Severity level, std::string&& text) override
|
||||
{
|
||||
using beast::Journal;
|
||||
sink_.write(level, prefix_ + text);
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity level, std::string const& text) override
|
||||
writeAlways(severities::Severity level, std::string&& text) override
|
||||
{
|
||||
using beast::Journal;
|
||||
sink_.writeAlways(level, prefix_ + text);
|
||||
|
||||
@@ -47,20 +47,20 @@ Logs::Sink::Sink(
|
||||
}
|
||||
|
||||
void
|
||||
Logs::Sink::write(beast::severities::Severity level, std::string const& text)
|
||||
Logs::Sink::write(beast::severities::Severity level, std::string&& text)
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
|
||||
logs_.write(level, partition_, text, console());
|
||||
logs_.write(level, partition_, std::move(text), console());
|
||||
}
|
||||
|
||||
void
|
||||
Logs::Sink::writeAlways(
|
||||
beast::severities::Severity level,
|
||||
std::string const& text)
|
||||
std::string&& text)
|
||||
{
|
||||
logs_.write(level, partition_, text, console());
|
||||
logs_.write(level, partition_, std::move(text), console());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -88,9 +88,13 @@ Logs::File::open(boost::filesystem::path const& path)
|
||||
|
||||
if (stream->good())
|
||||
{
|
||||
std::lock_guard lock(fileMutex_);
|
||||
m_path = path;
|
||||
|
||||
m_stream = std::move(stream);
|
||||
size_t const bufsize = 256 * 1024;
|
||||
static char buf[bufsize];
|
||||
m_stream->rdbuf()->pubsetbuf(buf, bufsize);
|
||||
|
||||
wasOpened = true;
|
||||
}
|
||||
@@ -109,12 +113,14 @@ Logs::File::closeAndReopen()
|
||||
void
|
||||
Logs::File::close()
|
||||
{
|
||||
std::lock_guard lock(fileMutex_);
|
||||
m_stream = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Logs::File::write(char const* text)
|
||||
{
|
||||
std::lock_guard lock(fileMutex_);
|
||||
if (m_stream != nullptr)
|
||||
(*m_stream) << text;
|
||||
}
|
||||
@@ -122,10 +128,10 @@ Logs::File::write(char const* text)
|
||||
void
|
||||
Logs::File::writeln(char const* text)
|
||||
{
|
||||
std::lock_guard lock(fileMutex_);
|
||||
if (m_stream != nullptr)
|
||||
{
|
||||
(*m_stream) << text;
|
||||
(*m_stream) << std::endl;
|
||||
(*m_stream) << text << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +151,7 @@ Logs::open(boost::filesystem::path const& pathToLogFile)
|
||||
beast::Journal::Sink&
|
||||
Logs::get(std::string const& name)
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard lock(sinkSetMutex_);
|
||||
auto const result = sinks_.emplace(name, makeSink(name, thresh_));
|
||||
return *result.first->second;
|
||||
}
|
||||
@@ -173,7 +179,7 @@ Logs::threshold() const
|
||||
void
|
||||
Logs::threshold(beast::severities::Severity thresh)
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard lock(sinkSetMutex_);
|
||||
thresh_ = thresh;
|
||||
for (auto& sink : sinks_)
|
||||
sink.second->threshold(thresh);
|
||||
@@ -183,7 +189,7 @@ std::vector<std::pair<std::string, std::string>>
|
||||
Logs::partition_severities() const
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> list;
|
||||
std::lock_guard lock(mutex_);
|
||||
std::lock_guard lock(sinkSetMutex_);
|
||||
list.reserve(sinks_.size());
|
||||
for (auto const& [name, sink] : sinks_)
|
||||
list.emplace_back(name, toString(fromSeverity(sink->threshold())));
|
||||
@@ -199,7 +205,6 @@ Logs::write(
|
||||
{
|
||||
std::string s;
|
||||
format(s, text, level, partition);
|
||||
std::lock_guard lock(mutex_);
|
||||
file_.writeln(s);
|
||||
if (!silent_)
|
||||
std::cerr << s << '\n';
|
||||
@@ -211,7 +216,6 @@ Logs::write(
|
||||
std::string
|
||||
Logs::rotate()
|
||||
{
|
||||
std::lock_guard lock(mutex_);
|
||||
bool const wasOpened = file_.closeAndReopen();
|
||||
if (wasOpened)
|
||||
return "The log file was closed and reopened.";
|
||||
@@ -332,11 +336,11 @@ Logs::format(
|
||||
beast::severities::Severity severity,
|
||||
std::string const& partition)
|
||||
{
|
||||
output.reserve(message.size() + partition.size() + 100);
|
||||
|
||||
output = message;
|
||||
if (!beast::Journal::isStructuredJournalEnabled())
|
||||
{
|
||||
output = to_string(std::chrono::system_clock::now());
|
||||
output.reserve(output.size() + partition.size() + 100);
|
||||
output += to_string(std::chrono::system_clock::now());
|
||||
|
||||
output += " ";
|
||||
if (!partition.empty())
|
||||
@@ -369,8 +373,6 @@ Logs::format(
|
||||
}
|
||||
}
|
||||
|
||||
output += message;
|
||||
|
||||
// Limit the maximum length of the output
|
||||
if (output.size() > maximumMessageCharacters)
|
||||
{
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
#include <rapidjson/writer.h>
|
||||
|
||||
#include <ios>
|
||||
#include <ostream>
|
||||
#include <ranges>
|
||||
@@ -77,12 +73,12 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(severities::Severity, std::string const&) override
|
||||
write(severities::Severity, std::string&&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity, std::string const&) override
|
||||
writeAlways(severities::Severity, std::string&&) override
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -98,7 +94,7 @@ Journal::getNullSink()
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::string
|
||||
std::string_view
|
||||
severities::to_string(Severity severity)
|
||||
{
|
||||
switch (severity)
|
||||
@@ -125,13 +121,18 @@ severities::to_string(Severity severity)
|
||||
|
||||
Journal::JsonLogAttributes::JsonLogAttributes()
|
||||
{
|
||||
contextValues_.SetObject();
|
||||
contextValues_ = {};
|
||||
contextValues_.emplace_object();
|
||||
}
|
||||
|
||||
Journal::JsonLogAttributes::JsonLogAttributes(JsonLogAttributes const& other)
|
||||
{
|
||||
contextValues_.SetObject();
|
||||
contextValues_.CopyFrom(other.contextValues_, allocator_);
|
||||
contextValues_ = other.contextValues_;
|
||||
}
|
||||
|
||||
Journal::JsonLogAttributes::JsonLogAttributes(JsonLogAttributes&& other)
|
||||
{
|
||||
contextValues_ = std::move(other.contextValues_);
|
||||
}
|
||||
|
||||
Journal::JsonLogAttributes&
|
||||
@@ -141,150 +142,115 @@ Journal::JsonLogAttributes::operator=(JsonLogAttributes const& other)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
contextValues_.CopyFrom(other.contextValues_, allocator_);
|
||||
contextValues_ = other.contextValues_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Journal::JsonLogAttributes&
|
||||
Journal::JsonLogAttributes::operator=(JsonLogAttributes&& other)
|
||||
{
|
||||
if (&other == this)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
contextValues_ = std::move(other.contextValues_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
Journal::JsonLogAttributes::setModuleName(std::string const& name)
|
||||
{
|
||||
contextValues_.AddMember(
|
||||
rapidjson::StringRef("Module"),
|
||||
rapidjson::Value{name.c_str(), allocator_},
|
||||
allocator_);
|
||||
}
|
||||
|
||||
Journal::JsonLogAttributes
|
||||
Journal::JsonLogAttributes::combine(
|
||||
AttributeFields const& a,
|
||||
AttributeFields const& b)
|
||||
{
|
||||
JsonLogAttributes result;
|
||||
|
||||
result.contextValues_.CopyFrom(a, result.allocator_);
|
||||
|
||||
for (auto& member : b.GetObject())
|
||||
{
|
||||
auto val = rapidjson::Value{member.value, result.allocator_};
|
||||
if (result.contextValues_.HasMember(member.name))
|
||||
{
|
||||
result.contextValues_[member.name] = std::move(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.contextValues_.AddMember(
|
||||
rapidjson::Value{member.name, result.allocator_},
|
||||
std::move(val),
|
||||
result.allocator_);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
contextValues_.as_object()["Module"] = name;
|
||||
}
|
||||
|
||||
void
|
||||
Journal::initMessageContext(std::source_location location)
|
||||
Journal::JsonLogAttributes::combine(AttributeFields const& from)
|
||||
{
|
||||
currentJsonLogContext_.reset(location);
|
||||
for (auto& [key, value] : from.as_object())
|
||||
{
|
||||
contextValues_.as_object()[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Journal::JsonLogContext::reset(
|
||||
std::source_location location,
|
||||
severities::Severity severity,
|
||||
std::optional<JsonLogAttributes> const& attributes) noexcept
|
||||
{
|
||||
struct ThreadIdStringInitializer
|
||||
{
|
||||
std::string value;
|
||||
ThreadIdStringInitializer()
|
||||
{
|
||||
std::stringstream threadIdStream;
|
||||
threadIdStream << std::this_thread::get_id();
|
||||
value = threadIdStream.str();
|
||||
}
|
||||
};
|
||||
thread_local ThreadIdStringInitializer const threadId;
|
||||
|
||||
attributes_.emplace_null();
|
||||
location_ = location;
|
||||
if (globalLogAttributes_.has_value())
|
||||
{
|
||||
attributes_ = globalLogAttributes_->contextValues();
|
||||
|
||||
if (attributes.has_value())
|
||||
{
|
||||
for (auto& [key, value] : attributes->contextValues().as_object())
|
||||
{
|
||||
attributes_.as_object()[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (attributes.has_value())
|
||||
{
|
||||
attributes_ = attributes->contextValues();
|
||||
}
|
||||
|
||||
if (attributes_.is_null())
|
||||
{
|
||||
attributes_ = {};
|
||||
attributes_.emplace_object();
|
||||
}
|
||||
|
||||
attributes_.as_object()["Params"] = boost::json::object{};
|
||||
attributes_.as_object()["Function"] =
|
||||
currentJsonLogContext_.location().function_name();
|
||||
attributes_.as_object()["File"] =
|
||||
currentJsonLogContext_.location().file_name();
|
||||
attributes_.as_object()["Line"] = currentJsonLogContext_.location().line();
|
||||
attributes_.as_object()["ThreadId"] = threadId.value;
|
||||
attributes_.as_object()["Level"] = to_string(severity);
|
||||
attributes_.as_object()["Time"] =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
|
||||
void
|
||||
Journal::initMessageContext(
|
||||
std::source_location location,
|
||||
severities::Severity severity) const
|
||||
{
|
||||
currentJsonLogContext_.reset(location, severity, m_attributes);
|
||||
}
|
||||
|
||||
std::string
|
||||
Journal::formatLog(
|
||||
std::string const& message,
|
||||
severities::Severity severity,
|
||||
std::optional<JsonLogAttributes> const& attributes)
|
||||
Journal::formatLog(std::string&& message)
|
||||
{
|
||||
if (!m_jsonLogsEnabled)
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
rapidjson::Document doc{¤tJsonLogContext_.allocator};
|
||||
rapidjson::Value logContext;
|
||||
logContext.SetObject();
|
||||
auto& attributes = currentJsonLogContext_.attributes().as_object();
|
||||
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("Function"),
|
||||
rapidjson::StringRef(currentJsonLogContext_.location.function_name()),
|
||||
currentJsonLogContext_.allocator);
|
||||
attributes["Message"] = message;
|
||||
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("File"),
|
||||
rapidjson::StringRef(currentJsonLogContext_.location.file_name()),
|
||||
currentJsonLogContext_.allocator);
|
||||
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("Line"),
|
||||
currentJsonLogContext_.location.line(),
|
||||
currentJsonLogContext_.allocator);
|
||||
std::stringstream threadIdStream;
|
||||
threadIdStream << std::this_thread::get_id();
|
||||
auto threadIdStr = threadIdStream.str();
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("ThreadId"),
|
||||
rapidjson::StringRef(threadIdStr.c_str()),
|
||||
currentJsonLogContext_.allocator);
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("Params"),
|
||||
std::move(currentJsonLogContext_.messageParams),
|
||||
currentJsonLogContext_.allocator);
|
||||
currentJsonLogContext_.messageParams = rapidjson::Value{};
|
||||
currentJsonLogContext_.messageParams.SetObject();
|
||||
auto severityStr = to_string(severity);
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("Level"),
|
||||
rapidjson::StringRef(severityStr.c_str()),
|
||||
currentJsonLogContext_.allocator);
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("Message"),
|
||||
rapidjson::StringRef(message.c_str()),
|
||||
currentJsonLogContext_.allocator);
|
||||
logContext.AddMember(
|
||||
rapidjson::StringRef("Time"),
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count(),
|
||||
currentJsonLogContext_.allocator);
|
||||
|
||||
if (attributes.has_value())
|
||||
{
|
||||
for (auto const& [key, value] : attributes->contextValues().GetObject())
|
||||
{
|
||||
if (logContext.HasMember(key))
|
||||
continue;
|
||||
rapidjson::Value jsonValue;
|
||||
jsonValue.CopyFrom(value, currentJsonLogContext_.allocator);
|
||||
|
||||
logContext.AddMember(
|
||||
rapidjson::Value{key, currentJsonLogContext_.allocator},
|
||||
std::move(jsonValue),
|
||||
currentJsonLogContext_.allocator);
|
||||
}
|
||||
}
|
||||
|
||||
if (globalLogAttributes_)
|
||||
{
|
||||
for (auto const& [key, value] :
|
||||
globalLogAttributes_->contextValues().GetObject())
|
||||
{
|
||||
if (logContext.HasMember(key))
|
||||
continue;
|
||||
rapidjson::Value jsonValue;
|
||||
jsonValue.CopyFrom(value, currentJsonLogContext_.allocator);
|
||||
|
||||
logContext.AddMember(
|
||||
rapidjson::Value{key, currentJsonLogContext_.allocator},
|
||||
std::move(jsonValue),
|
||||
currentJsonLogContext_.allocator);
|
||||
}
|
||||
}
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer writer(buffer);
|
||||
|
||||
logContext.Accept(writer);
|
||||
|
||||
return {buffer.GetString()};
|
||||
return boost::json::serialize(attributes);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -345,34 +311,30 @@ Journal::Sink::threshold(Severity thresh)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Journal::ScopedStream::ScopedStream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Sink& sink,
|
||||
Severity level)
|
||||
: m_attributes(std::move(attributes)), m_sink(sink), m_level(level)
|
||||
Journal::ScopedStream::ScopedStream(Sink& sink, Severity level)
|
||||
: m_sink(sink), m_level(level)
|
||||
{
|
||||
// Modifiers applied from all ctors
|
||||
m_ostream << std::boolalpha << std::showbase;
|
||||
}
|
||||
|
||||
Journal::ScopedStream::ScopedStream(
|
||||
std::optional<JsonLogAttributes> attributes,
|
||||
Stream const& stream,
|
||||
std::ostream& manip(std::ostream&))
|
||||
: ScopedStream(std::move(attributes), stream.sink(), stream.level())
|
||||
: ScopedStream(stream.sink(), stream.level())
|
||||
{
|
||||
m_ostream << manip;
|
||||
}
|
||||
|
||||
Journal::ScopedStream::~ScopedStream()
|
||||
{
|
||||
std::string const& s(m_ostream.str());
|
||||
std::string s = m_ostream.str();
|
||||
if (!s.empty())
|
||||
{
|
||||
if (s == "\n")
|
||||
m_sink.write(m_level, formatLog("", m_level, m_attributes));
|
||||
m_sink.write(m_level, formatLog(""));
|
||||
else
|
||||
m_sink.write(m_level, formatLog(s, m_level, m_attributes));
|
||||
m_sink.write(m_level, formatLog(std::move(s)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,7 +349,7 @@ Journal::ScopedStream::operator<<(std::ostream& manip(std::ostream&)) const
|
||||
Journal::ScopedStream
|
||||
Journal::Stream::operator<<(std::ostream& manip(std::ostream&)) const
|
||||
{
|
||||
return {m_attributes, *this, manip};
|
||||
return {*this, manip};
|
||||
}
|
||||
|
||||
} // namespace beast
|
||||
|
||||
@@ -48,14 +48,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(severities::Severity level, std::string const&) override
|
||||
write(severities::Severity level, std::string&&) override
|
||||
{
|
||||
if (level >= threshold())
|
||||
++m_count;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity level, std::string const&) override
|
||||
writeAlways(severities::Severity level, std::string&&) override
|
||||
{
|
||||
++m_count;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
write(beast::severities::Severity level, std::string&& text) override
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
std::cout << clock_.now().time_since_epoch().count() << " " << text
|
||||
|
||||
@@ -57,7 +57,7 @@ class CaptureLogs : public Logs
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
write(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
std::lock_guard lock(strmMutex_);
|
||||
@@ -65,7 +65,7 @@ class CaptureLogs : public Logs
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
std::lock_guard lock(strmMutex_);
|
||||
|
||||
@@ -45,7 +45,7 @@ class CheckMessageLogs : public Logs
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
write(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
if (text.find(owner_.msg_) != std::string::npos)
|
||||
@@ -53,10 +53,10 @@ class CheckMessageLogs : public Logs
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
write(level, text);
|
||||
write(level, std::move(text));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
write(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
if (level < threshold())
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
suite_.log << text << std::endl;
|
||||
|
||||
@@ -49,27 +49,27 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override;
|
||||
write(beast::severities::Severity level, std::string&& text) override;
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override;
|
||||
};
|
||||
|
||||
inline void
|
||||
SuiteJournalSink::write(
|
||||
beast::severities::Severity level,
|
||||
std::string const& text)
|
||||
std::string&& text)
|
||||
{
|
||||
// Only write the string if the level at least equals the threshold.
|
||||
if (level >= threshold())
|
||||
writeAlways(level, text);
|
||||
writeAlways(level, std::move(text));
|
||||
}
|
||||
|
||||
inline void
|
||||
SuiteJournalSink::writeAlways(
|
||||
beast::severities::Severity level,
|
||||
std::string const& text)
|
||||
std::string&& text)
|
||||
{
|
||||
using namespace beast::severities;
|
||||
|
||||
@@ -137,15 +137,15 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
write(beast::severities::Severity level, std::string&& text) override
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
writeAlways(level, text);
|
||||
writeAlways(level, std::move(text));
|
||||
}
|
||||
|
||||
inline void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
strm_ << text << std::endl;
|
||||
|
||||
@@ -49,14 +49,14 @@ private:
|
||||
operator=(Sink const&) = delete;
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
write(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
logs_.logStream_ << text;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
logs_.logStream_ << text;
|
||||
@@ -195,6 +195,7 @@ TEST_CASE("Global attributes inheritable")
|
||||
|
||||
CHECK(jsonLog.IsObject());
|
||||
CHECK(jsonLog.HasMember("Field1"));
|
||||
CHECK(jsonLog.HasMember("Field2"));
|
||||
CHECK(jsonLog["Field1"].IsString());
|
||||
// Field1 should be overwritten to Value3
|
||||
CHECK(jsonLog["Field1"].GetString() == std::string{"Value3"});
|
||||
@@ -217,13 +218,13 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
write(beast::severities::Severity level, std::string&& text) override
|
||||
{
|
||||
strm_ << text;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
writeAlways(beast::severities::Severity level, std::string&& text)
|
||||
override
|
||||
{
|
||||
strm_ << text;
|
||||
@@ -412,6 +413,8 @@ TEST_CASE_FIXTURE(JsonLogStreamFixture, "TestJsonLogParams")
|
||||
"Field2",
|
||||
std::numeric_limits<std::uint64_t>::max());
|
||||
|
||||
auto test = stream().str();
|
||||
|
||||
rapidjson::Document logValue;
|
||||
logValue.Parse(stream().str().c_str());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user