Fix issues

Signed-off-by: JCW <a1q123456@users.noreply.github.com>
This commit is contained in:
JCW
2025-09-02 20:04:14 +01:00
parent c2aae2d846
commit 1a2b7e9b94
3 changed files with 71 additions and 66 deletions

View File

@@ -23,6 +23,7 @@
#include <xrpl/beast/utility/instrumentation.h> #include <xrpl/beast/utility/instrumentation.h>
#include <charconv> #include <charconv>
#include <shared_mutex>
#include <source_location> #include <source_location>
#include <sstream> #include <sstream>
#include <string> #include <string>
@@ -84,140 +85,140 @@ namespace detail {
class SimpleJsonWriter class SimpleJsonWriter
{ {
public: public:
explicit SimpleJsonWriter(std::string& stream) : stream_(stream) explicit SimpleJsonWriter(std::string& buffer) : buffer_(buffer)
{ {
} }
void void
startObject() const startObject() const
{ {
stream_.push_back('{'); buffer_.push_back('{');
} }
void void
endObject() const endObject() const
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
stream_.pop_back(); buffer_.pop_back();
stream_.append("},"sv); buffer_.append("},"sv);
} }
void void
writeKey(std::string_view key) const writeKey(std::string_view key) const
{ {
writeString(key); writeString(key);
stream_.back() = ':'; buffer_.back() = ':';
} }
void void
startArray() const startArray() const
{ {
stream_.push_back('['); buffer_.push_back('[');
} }
void void
endArray() const endArray() const
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
stream_.pop_back(); buffer_.pop_back();
stream_.append("],"sv); buffer_.append("],"sv);
} }
void void
writeString(std::string_view str) const writeString(std::string_view str) const
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
stream_.push_back('"'); buffer_.push_back('"');
escape(str, stream_); escape(str, buffer_);
stream_.append("\","sv); buffer_.append("\","sv);
} }
std::string_view std::string_view
writeInt(std::int8_t val) const writeInt(std::int8_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeInt(std::int16_t val) const writeInt(std::int16_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeInt(std::int32_t val) const writeInt(std::int32_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeInt(std::int64_t val) const writeInt(std::int64_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeUInt(std::size_t val) const writeUInt(std::size_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeUInt(std::uint8_t val) const writeUInt(std::uint8_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeUInt(std::uint16_t val) const writeUInt(std::uint16_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeUInt(std::uint32_t val) const writeUInt(std::uint32_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeUInt(std::uint64_t val) const writeUInt(std::uint64_t val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeDouble(double val) const writeDouble(double val) const
{ {
return pushNumber(val, stream_); return pushNumber(val, buffer_);
} }
std::string_view std::string_view
writeBool(bool val) const writeBool(bool val) const
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
auto str = val ? "true,"sv : "false,"sv; auto str = val ? "true,"sv : "false,"sv;
stream_.append(str); buffer_.append(str);
return str; return str;
} }
void void
writeNull() const writeNull() const
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
stream_.append("null,"sv); buffer_.append("null,"sv);
} }
void void
writeRaw(std::string_view str) const writeRaw(std::string_view str) const
{ {
stream_.append(str); buffer_.append(str);
} }
[[nodiscard]] std::string_view [[nodiscard]] std::string_view
finish() finish()
{ {
return std::string_view{stream_.c_str(), stream_.size() - 1}; return std::string_view{buffer_.c_str(), buffer_.size() - 1};
} }
private: private:
template <typename T> template <typename T>
static std::string_view static std::string_view
pushNumber(T val, std::string& stream) pushNumber(T val, std::string& str)
{ {
thread_local char buffer[128]; thread_local char buffer[128];
auto result = std::to_chars(std::begin(buffer), std::end(buffer), val); auto result = std::to_chars(std::begin(buffer), std::end(buffer), val);
auto ptr = result.ptr; auto ptr = result.ptr;
*ptr = ','; *ptr = ',';
auto len = ptr - std::begin(buffer); auto len = ptr - std::begin(buffer);
stream.append(buffer, len + 1); str.append(buffer, len + 1);
return {buffer, static_cast<size_t>(len)}; return {buffer, static_cast<size_t>(len)};
} }
static void static void
escape(std::string_view str, std::string& os) escape(std::string_view str, std::string& buffer)
{ {
static constexpr char HEX[] = "0123456789ABCDEF"; static constexpr char HEX[] = "0123456789ABCDEF";
@@ -240,36 +241,36 @@ private:
// Flush the preceding safe run in one go. // Flush the preceding safe run in one go.
if (chunk != p) if (chunk != p)
os.append(chunk, p - chunk); buffer.append(chunk, p - chunk);
switch (c) switch (c)
{ {
case '"': case '"':
os.append("\\\"", 2); buffer.append("\\\"", 2);
break; break;
case '\\': case '\\':
os.append("\\\\", 2); buffer.append("\\\\", 2);
break; break;
case '\b': case '\b':
os.append("\\b", 2); buffer.append("\\b", 2);
break; break;
case '\f': case '\f':
os.append("\\f", 2); buffer.append("\\f", 2);
break; break;
case '\n': case '\n':
os.append("\\n", 2); buffer.append("\\n", 2);
break; break;
case '\r': case '\r':
os.append("\\r", 2); buffer.append("\\r", 2);
break; break;
case '\t': case '\t':
os.append("\\t", 2); buffer.append("\\t", 2);
break; break;
default: { default: {
// Other C0 controls -> \u00XX (JSON compliant) // Other C0 controls -> \u00XX (JSON compliant)
char buf[6]{ char buf[6]{
'\\', 'u', '0', '0', HEX[(c >> 4) & 0xF], HEX[c & 0xF]}; '\\', 'u', '0', '0', HEX[(c >> 4) & 0xF], HEX[c & 0xF]};
os.append(buf, 6); buffer.append(buf, 6);
break; break;
} }
} }
@@ -280,10 +281,10 @@ private:
// Flush trailing safe run // Flush trailing safe run
if (chunk != p) if (chunk != p)
os.append(chunk, p - chunk); buffer.append(chunk, p - chunk);
} }
std::string& stream_; std::string& buffer_;
}; };
} // namespace detail } // namespace detail
@@ -369,7 +370,7 @@ private:
std::string m_name; std::string m_name;
std::string m_attributesJson; std::string m_attributesJson;
static std::string globalLogAttributesJson_; static std::string globalLogAttributesJson_;
static std::mutex globalLogAttributesMutex_; static std::shared_mutex globalLogAttributesMutex_;
static bool m_jsonLogsEnabled; static bool m_jsonLogsEnabled;
static thread_local JsonLogContext currentJsonLogContext_; static thread_local JsonLogContext currentJsonLogContext_;
@@ -624,14 +625,14 @@ public:
Journal(Journal const& other, TAttributesFactory&& attributesFactory) Journal(Journal const& other, TAttributesFactory&& attributesFactory)
: m_name(other.m_name), m_sink(other.m_sink) : m_name(other.m_name), m_sink(other.m_sink)
{ {
std::string stream{other.m_attributesJson}; std::string buffer{other.m_attributesJson};
detail::SimpleJsonWriter writer{stream}; detail::SimpleJsonWriter writer{buffer};
if (other.m_attributesJson.empty()) if (other.m_attributesJson.empty())
{ {
writer.startObject(); writer.startObject();
} }
attributesFactory(writer); attributesFactory(writer);
m_attributesJson = std::move(stream); m_attributesJson = std::move(buffer);
} }
/** Create a journal that writes to the specified sink. */ /** Create a journal that writes to the specified sink. */
@@ -648,11 +649,11 @@ public:
TAttributesFactory&& attributesFactory) TAttributesFactory&& attributesFactory)
: m_name(name), m_sink(&sink) : m_name(name), m_sink(&sink)
{ {
std::string stream; std::string buffer;
detail::SimpleJsonWriter writer{stream}; detail::SimpleJsonWriter writer{buffer};
writer.startObject(); writer.startObject();
attributesFactory(writer); attributesFactory(writer);
m_attributesJson = std::move(stream); m_attributesJson = std::move(buffer);
} }
Journal& Journal&
@@ -758,7 +759,7 @@ public:
static void static void
resetGlobalAttributes() resetGlobalAttributes()
{ {
std::lock_guard lock(globalLogAttributesMutex_); std::unique_lock lock(globalLogAttributesMutex_);
globalLogAttributesJson_.clear(); globalLogAttributesJson_.clear();
} }
@@ -766,17 +767,17 @@ public:
static void static void
addGlobalAttributes(TAttributesFactory&& factory) addGlobalAttributes(TAttributesFactory&& factory)
{ {
std::lock_guard lock(globalLogAttributesMutex_); std::unique_lock lock(globalLogAttributesMutex_);
auto isEmpty = globalLogAttributesJson_.empty(); auto isEmpty = globalLogAttributesJson_.empty();
std::string stream{std::move(globalLogAttributesJson_)}; std::string buffer{std::move(globalLogAttributesJson_)};
detail::SimpleJsonWriter writer{stream}; detail::SimpleJsonWriter writer{buffer};
if (isEmpty) if (isEmpty)
{ {
writer.startObject(); writer.startObject();
} }
factory(writer); factory(writer);
globalLogAttributesJson_ = std::move(stream); globalLogAttributesJson_ = std::move(buffer);
} }
}; };

View File

@@ -22,13 +22,14 @@
#include <ios> #include <ios>
#include <ostream> #include <ostream>
#include <ranges> #include <ranges>
#include <shared_mutex>
#include <string> #include <string>
#include <thread> #include <thread>
namespace beast { namespace beast {
std::string Journal::globalLogAttributesJson_; std::string Journal::globalLogAttributesJson_;
std::mutex Journal::globalLogAttributesMutex_; std::shared_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_{};
@@ -150,13 +151,16 @@ Journal::JsonLogContext::reset(
writer().endObject(); writer().endObject();
} }
if (!globalLogAttributesJson_.empty())
{ {
writer().writeKey("GlobalParams"); std::shared_lock lock(globalLogAttributesMutex_);
writer().writeRaw(std::string_view{ if (!globalLogAttributesJson_.empty())
std::begin(globalLogAttributesJson_), {
std::end(globalLogAttributesJson_)}); writer().writeKey("GlobalParams");
writer().endObject(); writer().writeRaw(std::string_view{
std::begin(globalLogAttributesJson_),
std::end(globalLogAttributesJson_)});
writer().endObject();
}
} }
writer().writeKey("MessageParams"); writer().writeKey("MessageParams");

View File

@@ -231,32 +231,32 @@ TEST_CASE("Global attributes inheritable")
TEST_CASE("Test JsonWriter") TEST_CASE("Test JsonWriter")
{ {
{ {
std::string stream; std::string buffer;
beast::detail::SimpleJsonWriter writer{stream}; beast::detail::SimpleJsonWriter writer{buffer};
writer.writeString("\n"); writer.writeString("\n");
CHECK(writer.finish() == "\"\\n\""); CHECK(writer.finish() == "\"\\n\"");
} }
{ {
std::string stream; std::string buffer;
beast::detail::SimpleJsonWriter writer{stream}; beast::detail::SimpleJsonWriter writer{buffer};
writer.writeString("\t"); writer.writeString("\t");
CHECK(writer.finish() == "\"\\t\""); CHECK(writer.finish() == "\"\\t\"");
} }
{ {
std::string stream; std::string buffer;
beast::detail::SimpleJsonWriter writer{stream}; beast::detail::SimpleJsonWriter writer{buffer};
writer.writeString(std::string_view{"\0", 1}); writer.writeString(std::string_view{"\0", 1});
CHECK(writer.finish() == "\"\\u0000\""); CHECK(writer.finish() == "\"\\u0000\"");
} }
{ {
std::string stream; std::string buffer;
beast::detail::SimpleJsonWriter writer{stream}; beast::detail::SimpleJsonWriter writer{buffer};
writer.writeString("\"\\"); writer.writeString("\"\\");
CHECK(writer.finish() == "\"\\\"\\\\\""); CHECK(writer.finish() == "\"\\\"\\\\\"");