mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
Remove unrelated changes
Signed-off-by: JCW <a1q123456@users.noreply.github.com>
This commit is contained in:
@@ -26,19 +26,12 @@
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <boost/lockfree/queue.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <string_view>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -76,10 +69,11 @@ private:
|
||||
operator=(Sink const&) = delete;
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override;
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
override;
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override;
|
||||
};
|
||||
|
||||
@@ -137,16 +131,22 @@ private:
|
||||
Does nothing if there is no associated system file.
|
||||
*/
|
||||
void
|
||||
write(std::string const& str);
|
||||
write(std::string_view text);
|
||||
|
||||
/** write to the log file and append an end of line marker.
|
||||
Does nothing if there is no associated system file.
|
||||
*/
|
||||
void
|
||||
writeln(std::string_view text);
|
||||
|
||||
/** @} */
|
||||
|
||||
private:
|
||||
std::optional<std::ofstream> m_stream;
|
||||
std::unique_ptr<std::ofstream> m_stream;
|
||||
boost::filesystem::path m_path;
|
||||
};
|
||||
|
||||
std::mutex mutable sinkSetMutex_;
|
||||
std::mutex mutable mutex_;
|
||||
std::map<
|
||||
std::string,
|
||||
std::unique_ptr<beast::Journal::Sink>,
|
||||
@@ -156,24 +156,6 @@ private:
|
||||
File file_;
|
||||
bool silent_ = false;
|
||||
|
||||
// Batching members
|
||||
mutable std::mutex batchMutex_;
|
||||
boost::lockfree::queue<beast::Journal::StringBuffer, boost::lockfree::capacity<100>> messages_;
|
||||
static constexpr size_t BATCH_BUFFER_SIZE = 64 * 1024; // 64KB buffer
|
||||
std::array<char, BATCH_BUFFER_SIZE> batchBuffer_{};
|
||||
std::span<char> writeBuffer_; // Points to available write space
|
||||
std::span<char> readBuffer_; // Points to data ready to flush
|
||||
|
||||
// Log thread members
|
||||
std::thread logThread_;
|
||||
std::atomic<bool> stopLogThread_;
|
||||
std::mutex logMutex_;
|
||||
std::condition_variable logCondition_;
|
||||
|
||||
private:
|
||||
std::chrono::steady_clock::time_point lastFlush_ =
|
||||
std::chrono::steady_clock::now();
|
||||
|
||||
public:
|
||||
Logs(beast::severities::Severity level);
|
||||
|
||||
@@ -181,7 +163,7 @@ public:
|
||||
Logs&
|
||||
operator=(Logs const&) = delete;
|
||||
|
||||
virtual ~Logs(); // Need to flush on destruction
|
||||
virtual ~Logs() = default;
|
||||
|
||||
bool
|
||||
open(boost::filesystem::path const& pathToLogFile);
|
||||
@@ -201,10 +183,7 @@ public:
|
||||
}
|
||||
|
||||
beast::Journal
|
||||
journal(std::string const& name)
|
||||
{
|
||||
return beast::Journal{get(name), name};
|
||||
}
|
||||
journal(std::string const& name);
|
||||
|
||||
beast::severities::Severity
|
||||
threshold() const;
|
||||
@@ -219,15 +198,12 @@ public:
|
||||
write(
|
||||
beast::severities::Severity level,
|
||||
std::string const& partition,
|
||||
beast::Journal::StringBuffer text,
|
||||
std::string const& text,
|
||||
bool console);
|
||||
|
||||
std::string
|
||||
rotate();
|
||||
|
||||
void
|
||||
flushBatch();
|
||||
|
||||
/**
|
||||
* Set flag to write logs to stderr (false) or not (true).
|
||||
*
|
||||
@@ -260,7 +236,7 @@ public:
|
||||
static void
|
||||
format(
|
||||
std::string& output,
|
||||
std::string_view message,
|
||||
std::string const& message,
|
||||
beast::severities::Severity severity,
|
||||
std::string const& partition);
|
||||
|
||||
@@ -270,12 +246,6 @@ private:
|
||||
// If the message exceeds this length it will be truncated with elipses.
|
||||
maximumMessageCharacters = 12 * 1024
|
||||
};
|
||||
|
||||
void
|
||||
flushBatchUnsafe();
|
||||
|
||||
void
|
||||
logThreadWorker();
|
||||
};
|
||||
|
||||
// Wraps a Journal::Stream to skip evaluation of
|
||||
|
||||
@@ -22,12 +22,10 @@
|
||||
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
|
||||
#include <thread>
|
||||
#include <deque>
|
||||
#include <atomic>
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <source_location>
|
||||
@@ -330,146 +328,21 @@ public:
|
||||
|
||||
class Sink;
|
||||
|
||||
class StringBufferPool {
|
||||
public:
|
||||
static constexpr std::uint32_t kEmptyIdx = std::numeric_limits<std::uint32_t>::max();
|
||||
|
||||
struct Head {
|
||||
std::uint32_t tag;
|
||||
std::uint32_t idx; // kEmptyIdx means empty
|
||||
};
|
||||
|
||||
struct Node {
|
||||
std::uint32_t next_idx{kEmptyIdx};
|
||||
std::uint32_t self_idx{kEmptyIdx};
|
||||
std::string buf{};
|
||||
};
|
||||
|
||||
class StringBuffer
|
||||
{
|
||||
public:
|
||||
StringBuffer() = default;
|
||||
|
||||
std::string&
|
||||
str() { return node_->buf; }
|
||||
|
||||
private:
|
||||
StringBuffer(StringBufferPool* owner, Node* node)
|
||||
: owner_(owner), node_(node) {}
|
||||
|
||||
StringBufferPool* owner_ = nullptr;
|
||||
Node* node_ = nullptr;
|
||||
|
||||
friend class StringBufferPool;
|
||||
};
|
||||
|
||||
explicit StringBufferPool(std::uint32_t grow_by = 20)
|
||||
: growBy_(grow_by), head_({0, kEmptyIdx}) {}
|
||||
|
||||
// Rent a buffer; grows on demand. Returns move-only RAII handle.
|
||||
StringBuffer rent() {
|
||||
for (;;) {
|
||||
auto old = head_.load(std::memory_order_acquire);
|
||||
if (old.idx == kEmptyIdx) { grow(); continue; } // rare slow path
|
||||
|
||||
Node& n = nodes_[old.idx];
|
||||
std::uint32_t next = n.next_idx;
|
||||
|
||||
Head neu{ old.tag + 1, next };
|
||||
if (head_.compare_exchange_weak(old, neu,
|
||||
std::memory_order_acq_rel,
|
||||
std::memory_order_acquire)) {
|
||||
return {this, &n};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only the pool/handle can call this
|
||||
void giveBack(StringBuffer&& h) noexcept {
|
||||
Node* node = h.node_;
|
||||
if (!node) return; // already invalid
|
||||
const std::uint32_t idx = node->self_idx;
|
||||
|
||||
for (;;) {
|
||||
auto old = head_.load(std::memory_order_acquire);
|
||||
|
||||
node->next_idx = old.idx;
|
||||
|
||||
Head neu{ std::uint32_t(old.tag + 1), idx };
|
||||
if (head_.compare_exchange_weak(old, neu,
|
||||
std::memory_order_acq_rel,
|
||||
std::memory_order_acquire)) {
|
||||
// Invalidate handle (prevents double return)
|
||||
h.owner_ = nullptr;
|
||||
h.node_ = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void grow() {
|
||||
if (head_.load(std::memory_order_acquire).idx != kEmptyIdx) return;
|
||||
std::scoped_lock lk(growMutex_);
|
||||
if (head_.load(std::memory_order_acquire).idx != kEmptyIdx) return;
|
||||
|
||||
auto base = static_cast<std::uint32_t>(nodes_.size());
|
||||
nodes_.resize(base + growBy_);
|
||||
|
||||
// Init nodes and local chain
|
||||
for (std::uint32_t i = 0; i < growBy_; ++i) {
|
||||
std::uint32_t idx = base + i;
|
||||
Node& n = nodes_[idx];
|
||||
n.self_idx = idx;
|
||||
n.next_idx = (i + 1 < growBy_) ? (idx + 1) : kEmptyIdx;
|
||||
}
|
||||
|
||||
// Splice chain onto global head: [base .. base+grow_by_-1]
|
||||
const std::uint32_t chain_head = base;
|
||||
const std::uint32_t chain_tail = base + growBy_ - 1;
|
||||
|
||||
for (;;) {
|
||||
auto old = head_.load(std::memory_order_acquire);
|
||||
|
||||
nodes_[chain_tail].next_idx = old.idx; // tail -> old head
|
||||
Head neu{ std::uint32_t(old.tag + 1), chain_head };
|
||||
|
||||
if (head_.compare_exchange_weak(old, neu,
|
||||
std::memory_order_acq_rel,
|
||||
std::memory_order_acquire)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::uint32_t growBy_;
|
||||
|
||||
// single 64-bit CAS
|
||||
std::atomic<Head> head_;
|
||||
|
||||
// only during growth
|
||||
std::mutex growMutex_;
|
||||
|
||||
// stable storage for nodes/strings
|
||||
std::deque<Node> nodes_;
|
||||
};
|
||||
using StringBuffer = StringBufferPool::StringBuffer;
|
||||
|
||||
class JsonLogContext
|
||||
{
|
||||
StringBuffer messageBuffer_;
|
||||
std::string messageBuffer_;
|
||||
detail::SimpleJsonWriter jsonWriter_;
|
||||
bool hasMessageParams_ = false;
|
||||
std::size_t messageOffset_ = 0;
|
||||
public:
|
||||
|
||||
JsonLogContext()
|
||||
: messageBuffer_(rentFromPool())
|
||||
, jsonWriter_(&messageBuffer_.str())
|
||||
{}
|
||||
: jsonWriter_(&messageBuffer_)
|
||||
{
|
||||
messageBuffer_.reserve(4 * 1024);
|
||||
}
|
||||
|
||||
StringBuffer
|
||||
std::string&
|
||||
messageBuffer() { return messageBuffer_; }
|
||||
|
||||
void
|
||||
@@ -522,7 +395,6 @@ private:
|
||||
static std::shared_mutex globalLogAttributesMutex_;
|
||||
static bool jsonLogsEnabled_;
|
||||
|
||||
static StringBufferPool messagePool_;
|
||||
static thread_local JsonLogContext currentJsonLogContext_;
|
||||
|
||||
// Invariant: m_sink always points to a valid Sink
|
||||
@@ -533,21 +405,12 @@ private:
|
||||
std::source_location location,
|
||||
severities::Severity severity) const;
|
||||
|
||||
static StringBuffer
|
||||
static std::string&
|
||||
formatLog(std::string const& message);
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
static StringBuffer
|
||||
rentFromPool()
|
||||
{
|
||||
return messagePool_.rent();
|
||||
}
|
||||
|
||||
static void
|
||||
returnStringBuffer(StringBuffer&& node) { messagePool_.giveBack(std::move(node)); }
|
||||
|
||||
static void
|
||||
enableStructuredJournal();
|
||||
|
||||
@@ -597,7 +460,7 @@ public:
|
||||
level is below the current threshold().
|
||||
*/
|
||||
virtual void
|
||||
write(Severity level, StringBuffer text) = 0;
|
||||
write(Severity level, std::string const& 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
|
||||
@@ -607,7 +470,7 @@ public:
|
||||
* @param text Text to write to sink.
|
||||
*/
|
||||
virtual void
|
||||
writeAlways(Severity level, StringBuffer text) = 0;
|
||||
writeAlways(Severity level, std::string const& text) = 0;
|
||||
|
||||
private:
|
||||
Severity thresh_;
|
||||
|
||||
@@ -88,19 +88,17 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, Journal::StringBuffer text) override
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
{
|
||||
using beast::Journal;
|
||||
text.str() = prefix_ + text.str();
|
||||
sink_.write(level, text);
|
||||
sink_.write(level, prefix_ + text);
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity level, Journal::StringBuffer text) override
|
||||
writeAlways(severities::Severity level, std::string const& text) override
|
||||
{
|
||||
using beast::Journal;
|
||||
text.str() = prefix_ + text.str();
|
||||
sink_.writeAlways(level, text);
|
||||
sink_.writeAlways(level, prefix_ + text);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -38,12 +38,6 @@
|
||||
|
||||
namespace ripple {
|
||||
|
||||
namespace {
|
||||
constexpr auto FLUSH_INTERVAL =
|
||||
std::chrono::milliseconds(10); // Max delay before flush
|
||||
}
|
||||
|
||||
|
||||
Logs::Sink::Sink(
|
||||
std::string const& partition,
|
||||
beast::severities::Severity thresh,
|
||||
@@ -53,7 +47,7 @@ Logs::Sink::Sink(
|
||||
}
|
||||
|
||||
void
|
||||
Logs::Sink::write(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
Logs::Sink::write(beast::severities::Severity level, std::string const& text)
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
@@ -62,7 +56,9 @@ Logs::Sink::write(beast::severities::Severity level, beast::Journal::StringBuffe
|
||||
}
|
||||
|
||||
void
|
||||
Logs::Sink::writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
Logs::Sink::writeAlways(
|
||||
beast::severities::Severity level,
|
||||
std::string const& text)
|
||||
{
|
||||
logs_.write(level, partition_, text, console());
|
||||
}
|
||||
@@ -76,7 +72,7 @@ Logs::File::File() : m_stream(nullptr)
|
||||
bool
|
||||
Logs::File::isOpen() const noexcept
|
||||
{
|
||||
return m_stream.has_value();
|
||||
return m_stream != nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -87,16 +83,14 @@ Logs::File::open(boost::filesystem::path const& path)
|
||||
bool wasOpened = false;
|
||||
|
||||
// VFALCO TODO Make this work with Unicode file paths
|
||||
std::ofstream stream(path.c_str(), std::fstream::app);
|
||||
std::unique_ptr<std::ofstream> stream(
|
||||
new std::ofstream(path.c_str(), std::fstream::app));
|
||||
|
||||
if (stream.good())
|
||||
if (stream->good())
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -115,39 +109,31 @@ Logs::File::closeAndReopen()
|
||||
void
|
||||
Logs::File::close()
|
||||
{
|
||||
m_stream.reset();
|
||||
m_stream = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Logs::File::write(std::string const& text)
|
||||
Logs::File::write(std::string_view text)
|
||||
{
|
||||
if (m_stream.has_value())
|
||||
m_stream->write(text.data(), text.size());
|
||||
if (m_stream != nullptr)
|
||||
(*m_stream) << text;
|
||||
}
|
||||
|
||||
void
|
||||
Logs::File::writeln(std::string_view text)
|
||||
{
|
||||
if (m_stream != nullptr)
|
||||
{
|
||||
(*m_stream) << text;
|
||||
(*m_stream) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
Logs::Logs(beast::severities::Severity thresh)
|
||||
: thresh_(thresh) // default severity
|
||||
, writeBuffer_(
|
||||
batchBuffer_) // Initially, entire buffer is available for writing
|
||||
, readBuffer_(batchBuffer_.data(), 0) // No data ready to flush initially
|
||||
, stopLogThread_(false)
|
||||
{
|
||||
logThread_ = std::thread(&Logs::logThreadWorker, this);
|
||||
}
|
||||
|
||||
Logs::~Logs()
|
||||
{
|
||||
// Signal log thread to stop and wait for it to finish
|
||||
{
|
||||
stopLogThread_ = true;
|
||||
}
|
||||
|
||||
if (logThread_.joinable())
|
||||
logThread_.join();
|
||||
|
||||
flushBatch(); // Ensure all logs are written on shutdown
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -159,7 +145,7 @@ Logs::open(boost::filesystem::path const& pathToLogFile)
|
||||
beast::Journal::Sink&
|
||||
Logs::get(std::string const& name)
|
||||
{
|
||||
std::lock_guard lock(sinkSetMutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
auto const result = sinks_.emplace(name, makeSink(name, thresh_));
|
||||
return *result.first->second;
|
||||
}
|
||||
@@ -170,6 +156,12 @@ Logs::operator[](std::string const& name)
|
||||
return get(name);
|
||||
}
|
||||
|
||||
beast::Journal
|
||||
Logs::journal(std::string const& name)
|
||||
{
|
||||
return beast::Journal(get(name));
|
||||
}
|
||||
|
||||
beast::severities::Severity
|
||||
Logs::threshold() const
|
||||
{
|
||||
@@ -179,7 +171,7 @@ Logs::threshold() const
|
||||
void
|
||||
Logs::threshold(beast::severities::Severity thresh)
|
||||
{
|
||||
std::lock_guard lock(sinkSetMutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
thresh_ = thresh;
|
||||
for (auto& sink : sinks_)
|
||||
sink.second->threshold(thresh);
|
||||
@@ -189,7 +181,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(sinkSetMutex_);
|
||||
std::lock_guard lock(mutex_);
|
||||
list.reserve(sinks_.size());
|
||||
for (auto const& [name, sink] : sinks_)
|
||||
list.emplace_back(name, toString(fromSeverity(sink->threshold())));
|
||||
@@ -200,118 +192,28 @@ void
|
||||
Logs::write(
|
||||
beast::severities::Severity level,
|
||||
std::string const& partition,
|
||||
beast::Journal::StringBuffer text,
|
||||
std::string const& text,
|
||||
bool console)
|
||||
{
|
||||
std::string s;
|
||||
std::string_view result = text.str();
|
||||
std::string_view result = text;
|
||||
if (!beast::Journal::isStructuredJournalEnabled())
|
||||
{
|
||||
format(s, text.str(), level, partition);
|
||||
text.str() = s;
|
||||
result = text.str();
|
||||
}
|
||||
|
||||
// if (!silent_)
|
||||
// std::cerr << result << '\n';
|
||||
|
||||
messages_.push(text);
|
||||
|
||||
// Signal log thread that new messages are available
|
||||
// logCondition_.notify_one();
|
||||
|
||||
// Add to batch buffer for file output
|
||||
if (0) {
|
||||
// std::lock_guard lock(batchMutex_);
|
||||
|
||||
// Console output still immediate for responsiveness
|
||||
// if (!silent_)
|
||||
// std::cerr << result << '\n';
|
||||
|
||||
size_t logSize = result.size() + 1; // +1 for newline
|
||||
|
||||
// If log won't fit in current write buffer, flush first
|
||||
if (logSize > writeBuffer_.size())
|
||||
{
|
||||
flushBatchUnsafe();
|
||||
}
|
||||
|
||||
// Copy log into write buffer
|
||||
std::copy(result.begin(), result.end(), writeBuffer_.begin());
|
||||
writeBuffer_[result.size()] = '\n';
|
||||
|
||||
return;
|
||||
|
||||
// Update spans: expand read buffer, shrink write buffer
|
||||
size_t totalUsed = readBuffer_.size() + logSize;
|
||||
readBuffer_ = std::span<char>(batchBuffer_.data(), totalUsed);
|
||||
writeBuffer_ = std::span<char>(
|
||||
batchBuffer_.data() + totalUsed, batchBuffer_.size() - totalUsed);
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
bool shouldFlush = (now - lastFlush_) >= FLUSH_INTERVAL;
|
||||
|
||||
if (shouldFlush)
|
||||
{
|
||||
flushBatchUnsafe();
|
||||
lastFlush_ = now;
|
||||
}
|
||||
format(s, text, level, partition);
|
||||
result = text;
|
||||
}
|
||||
|
||||
std::lock_guard lock(mutex_);
|
||||
file_.writeln(result);
|
||||
// VFALCO TODO Fix console output
|
||||
// if (console)
|
||||
// out_.write_console(s);
|
||||
}
|
||||
|
||||
void
|
||||
Logs::flushBatch()
|
||||
{
|
||||
std::lock_guard lock(batchMutex_);
|
||||
flushBatchUnsafe();
|
||||
}
|
||||
|
||||
void
|
||||
Logs::flushBatchUnsafe()
|
||||
{
|
||||
if (readBuffer_.empty())
|
||||
return;
|
||||
|
||||
// Write the read buffer contents to file in one system call
|
||||
// file_.write(std::string_view{readBuffer_.data(), readBuffer_.size()});
|
||||
|
||||
// Reset spans: entire buffer available for writing, nothing to read
|
||||
writeBuffer_ = std::span<char>(batchBuffer_);
|
||||
readBuffer_ = std::span<char>(batchBuffer_.data(), 0);
|
||||
}
|
||||
|
||||
void
|
||||
Logs::logThreadWorker()
|
||||
{
|
||||
while (!stopLogThread_)
|
||||
{
|
||||
std::this_thread::sleep_for(FLUSH_INTERVAL);
|
||||
|
||||
beast::Journal::StringBuffer buffer;
|
||||
// Process all available messages
|
||||
while (messages_.pop(buffer))
|
||||
{
|
||||
// Also write to console if not silent
|
||||
if (!silent_)
|
||||
std::cerr << buffer.str() << '\n';
|
||||
|
||||
// Write to file
|
||||
file_.write(buffer.str());
|
||||
|
||||
// Return node to pool for reuse
|
||||
beast::Journal::returnStringBuffer(std::move(buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
Logs::rotate()
|
||||
{
|
||||
flushBatch(); // Flush pending logs before rotating
|
||||
std::lock_guard lock(mutex_);
|
||||
bool const wasOpened = file_.closeAndReopen();
|
||||
if (wasOpened)
|
||||
return "The log file was closed and reopened.";
|
||||
@@ -428,7 +330,7 @@ Logs::fromString(std::string const& s)
|
||||
void
|
||||
Logs::format(
|
||||
std::string& output,
|
||||
std::string_view message,
|
||||
std::string const& message,
|
||||
beast::severities::Severity severity,
|
||||
std::string const& partition)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#include <xrpl/beast/utility/Journal.h>
|
||||
|
||||
#include <date/date.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <ios>
|
||||
#include <ostream>
|
||||
@@ -28,92 +30,9 @@
|
||||
|
||||
namespace beast {
|
||||
|
||||
namespace {
|
||||
|
||||
// Fast timestamp to ISO string conversion
|
||||
// Returns string like "2024-01-15T10:30:45.123Z"
|
||||
std::string_view
|
||||
fastTimestampToString(std::int64_t milliseconds_since_epoch)
|
||||
{
|
||||
thread_local char buffer[64]; // "2024-01-15T10:30:45.123Z"
|
||||
|
||||
// Precomputed lookup table for 2-digit numbers 00-99
|
||||
static constexpr char digits[200] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6',
|
||||
'0', '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3',
|
||||
'1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0',
|
||||
'2', '1', '2', '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7',
|
||||
'2', '8', '2', '9', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4',
|
||||
'3', '5', '3', '6', '3', '7', '3', '8', '3', '9', '4', '0', '4', '1',
|
||||
'4', '2', '4', '3', '4', '4', '4', '5', '4', '6', '4', '7', '4', '8',
|
||||
'4', '9', '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', '5', '5',
|
||||
'5', '6', '5', '7', '5', '8', '5', '9', '6', '0', '6', '1', '6', '2',
|
||||
'6', '3', '6', '4', '6', '5', '6', '6', '6', '7', '6', '8', '6', '9',
|
||||
'7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6',
|
||||
'7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', '2', '8', '3',
|
||||
'8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', '9', '0',
|
||||
'9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', '7',
|
||||
'9', '8', '9', '9'};
|
||||
|
||||
constexpr std::int64_t UNIX_EPOCH_DAYS =
|
||||
719468; // Days from year 0 to 1970-01-01
|
||||
|
||||
std::int64_t seconds = milliseconds_since_epoch / 1000;
|
||||
int ms = milliseconds_since_epoch % 1000;
|
||||
std::int64_t days = seconds / 86400 + UNIX_EPOCH_DAYS;
|
||||
int sec_of_day = seconds % 86400;
|
||||
|
||||
// Calculate year, month, day from days using Gregorian calendar algorithm
|
||||
int era = (days >= 0 ? days : days - 146096) / 146097;
|
||||
int doe = days - era * 146097;
|
||||
int yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
int year = yoe + era * 400;
|
||||
int doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
int mp = (5 * doy + 2) / 153;
|
||||
int day = doy - (153 * mp + 2) / 5 + 1;
|
||||
int month = mp + (mp < 10 ? 3 : -9);
|
||||
year += (month <= 2);
|
||||
|
||||
// Calculate hour, minute, second
|
||||
int hour = sec_of_day / 3600;
|
||||
int min = (sec_of_day % 3600) / 60;
|
||||
int sec = sec_of_day % 60;
|
||||
|
||||
// Format: "2024-01-15T10:30:45.123Z"
|
||||
buffer[0] = '0' + year / 1000;
|
||||
buffer[1] = '0' + (year / 100) % 10;
|
||||
buffer[2] = '0' + (year / 10) % 10;
|
||||
buffer[3] = '0' + year % 10;
|
||||
buffer[4] = '-';
|
||||
buffer[5] = digits[month * 2];
|
||||
buffer[6] = digits[month * 2 + 1];
|
||||
buffer[7] = '-';
|
||||
buffer[8] = digits[day * 2];
|
||||
buffer[9] = digits[day * 2 + 1];
|
||||
buffer[10] = 'T';
|
||||
buffer[11] = digits[hour * 2];
|
||||
buffer[12] = digits[hour * 2 + 1];
|
||||
buffer[13] = ':';
|
||||
buffer[14] = digits[min * 2];
|
||||
buffer[15] = digits[min * 2 + 1];
|
||||
buffer[16] = ':';
|
||||
buffer[17] = digits[sec * 2];
|
||||
buffer[18] = digits[sec * 2 + 1];
|
||||
buffer[19] = '.';
|
||||
buffer[20] = '0' + ms / 100;
|
||||
buffer[21] = '0' + (ms / 10) % 10;
|
||||
buffer[22] = '0' + ms % 10;
|
||||
buffer[23] = 'Z';
|
||||
|
||||
return {buffer, 24};
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
std::string Journal::globalLogAttributes_;
|
||||
std::shared_mutex Journal::globalLogAttributesMutex_;
|
||||
bool Journal::jsonLogsEnabled_ = false;
|
||||
Journal::StringBufferPool Journal::messagePool_{};
|
||||
thread_local Journal::JsonLogContext Journal::currentJsonLogContext_{};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -157,12 +76,12 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(severities::Severity, Journal::StringBuffer) override
|
||||
write(severities::Severity, std::string const&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity, Journal::StringBuffer) override
|
||||
writeAlways(severities::Severity, std::string const&) override
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -224,12 +143,12 @@ Journal::JsonLogContext::start(
|
||||
thread_local ThreadIdStringInitializer const threadId;
|
||||
|
||||
messageOffset_ = 0;
|
||||
messageBuffer_.str().clear();
|
||||
jsonWriter_ = detail::SimpleJsonWriter{&messageBuffer_.str()};
|
||||
messageBuffer_.clear();
|
||||
jsonWriter_ = detail::SimpleJsonWriter{&messageBuffer_};
|
||||
|
||||
if (!jsonLogsEnabled_)
|
||||
{
|
||||
messageBuffer_.str() = journalAttributes;
|
||||
messageBuffer_ = journalAttributes;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -277,10 +196,9 @@ Journal::JsonLogContext::start(
|
||||
writer().writeString(severityStr);
|
||||
|
||||
auto nowMs = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
writer().writeKey("Tm");
|
||||
writer().writeString(fastTimestampToString(nowMs));
|
||||
writer().writeString(date::format("%Y-%b-%d %T %Z", nowMs));
|
||||
|
||||
writer().endObject();
|
||||
|
||||
@@ -290,25 +208,22 @@ Journal::JsonLogContext::start(
|
||||
void
|
||||
Journal::JsonLogContext::reuseJson()
|
||||
{
|
||||
messageOffset_ = messageBuffer_.str().size();
|
||||
messageOffset_ = messageBuffer_.size();
|
||||
}
|
||||
|
||||
void
|
||||
Journal::JsonLogContext::finish()
|
||||
{
|
||||
if (messageOffset_ != 0)
|
||||
{
|
||||
auto buffer = rentFromPool();
|
||||
std::string_view json{messageBuffer_.str()};
|
||||
buffer.str() = json.substr(0, messageOffset_);
|
||||
messageBuffer_ = buffer;
|
||||
messageBuffer_.erase(messageOffset_);
|
||||
}
|
||||
else
|
||||
{
|
||||
messageBuffer_ = rentFromPool();
|
||||
messageBuffer_.clear();
|
||||
}
|
||||
|
||||
messageBuffer_.str().reserve(1024 * 5);
|
||||
jsonWriter_ = detail::SimpleJsonWriter{&messageBuffer_.str()};
|
||||
jsonWriter_ = detail::SimpleJsonWriter{&messageBuffer_};
|
||||
}
|
||||
|
||||
void
|
||||
@@ -319,7 +234,7 @@ Journal::initMessageContext(
|
||||
currentJsonLogContext_.start(location, severity, name_, attributes_);
|
||||
}
|
||||
|
||||
Journal::StringBuffer
|
||||
std::string&
|
||||
Journal::formatLog(std::string const& message)
|
||||
{
|
||||
if (!jsonLogsEnabled_)
|
||||
@@ -423,9 +338,8 @@ Journal::ScopedStream::~ScopedStream()
|
||||
if (s == "\n")
|
||||
s = "";
|
||||
|
||||
auto messageHandle = formatLog(s);
|
||||
m_sink.write(m_level, formatLog(s));
|
||||
currentJsonLogContext_.finish();
|
||||
m_sink.write(m_level, messageHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,14 +48,14 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(severities::Severity level, Journal::StringBuffer) override
|
||||
write(severities::Severity level, std::string const&) override
|
||||
{
|
||||
if (level >= threshold())
|
||||
++m_count;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(severities::Severity level, Journal::StringBuffer) override
|
||||
writeAlways(severities::Severity level, std::string const&) override
|
||||
{
|
||||
++m_count;
|
||||
}
|
||||
|
||||
@@ -49,19 +49,20 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
|
||||
std::cout << clock_.now().time_since_epoch().count() << " " << text.str()
|
||||
std::cout << clock_.now().time_since_epoch().count() << " " << text
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
std::cout << clock_.now().time_since_epoch().count() << " " << text.str()
|
||||
std::cout << clock_.now().time_since_epoch().count() << " " << text
|
||||
<< std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -57,18 +57,19 @@ class CaptureLogs : public Logs
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
{
|
||||
std::lock_guard lock(strmMutex_);
|
||||
strm_ << text.str();
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
std::lock_guard lock(strmMutex_);
|
||||
strm_ << text.str();
|
||||
strm_ << text;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
std::lock_guard lock(strmMutex_);
|
||||
strm_ << text;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,14 +45,15 @@ class CheckMessageLogs : public Logs
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
if (text.str().find(owner_.msg_) != std::string::npos)
|
||||
if (text.find(owner_.msg_) != std::string::npos)
|
||||
*owner_.pFound_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
write(level, text);
|
||||
|
||||
@@ -92,19 +92,20 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
write(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
|
||||
suite_.log << text.str() << std::endl;
|
||||
suite_.log << text << std::endl;
|
||||
}
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
suite_.log << text.str() << std::endl;
|
||||
suite_.log << text << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,14 +49,17 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override;
|
||||
write(beast::severities::Severity level, std::string const& text) override;
|
||||
|
||||
void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text) override;
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override;
|
||||
};
|
||||
|
||||
inline void
|
||||
SuiteJournalSink::write(beast::severities::Severity level, beast::Journal::StringBuffer text)
|
||||
SuiteJournalSink::write(
|
||||
beast::severities::Severity level,
|
||||
std::string const& text)
|
||||
{
|
||||
// Only write the string if the level at least equals the threshold.
|
||||
if (level >= threshold())
|
||||
@@ -66,7 +69,7 @@ SuiteJournalSink::write(beast::severities::Severity level, beast::Journal::Strin
|
||||
inline void
|
||||
SuiteJournalSink::writeAlways(
|
||||
beast::severities::Severity level,
|
||||
beast::Journal::StringBuffer text)
|
||||
std::string const& text)
|
||||
{
|
||||
using namespace beast::severities;
|
||||
|
||||
@@ -93,7 +96,7 @@ SuiteJournalSink::writeAlways(
|
||||
|
||||
static std::mutex log_mutex;
|
||||
std::lock_guard lock(log_mutex);
|
||||
suite_.log << s << partition_ << text.str() << std::endl;
|
||||
suite_.log << s << partition_ << text << std::endl;
|
||||
}
|
||||
|
||||
class SuiteJournal
|
||||
@@ -134,7 +137,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
write(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
write(beast::severities::Severity level, std::string const& text) override
|
||||
{
|
||||
if (level < threshold())
|
||||
return;
|
||||
@@ -142,9 +145,10 @@ public:
|
||||
}
|
||||
|
||||
inline void
|
||||
writeAlways(beast::severities::Severity level, beast::Journal::StringBuffer text) override
|
||||
writeAlways(beast::severities::Severity level, std::string const& text)
|
||||
override
|
||||
{
|
||||
strm_ << text.str() << std::endl;
|
||||
strm_ << text << std::endl;
|
||||
}
|
||||
|
||||
std::stringstream const&
|
||||
|
||||
@@ -14,5 +14,3 @@ xrpl_add_test(crypto)
|
||||
target_link_libraries(xrpl.test.crypto PRIVATE xrpl.imports.test)
|
||||
xrpl_add_test(net)
|
||||
target_link_libraries(xrpl.test.net PRIVATE xrpl.imports.test)
|
||||
xrpl_add_test(telemetry)
|
||||
target_link_libraries(xrpl.test.telemetry PRIVATE xrpl.imports.test)
|
||||
|
||||
@@ -1107,8 +1107,7 @@ RCLConsensus::startRound(
|
||||
RclConsensusLogger::RclConsensusLogger(
|
||||
char const* label,
|
||||
bool const validating,
|
||||
beast::Journal j,
|
||||
std::source_location location)
|
||||
beast::Journal j)
|
||||
: j_(j)
|
||||
{
|
||||
if (!validating && !j.info())
|
||||
@@ -1126,16 +1125,16 @@ RclConsensusLogger::~RclConsensusLogger()
|
||||
return;
|
||||
auto const duration = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now() - start_);
|
||||
|
||||
std::stringstream outSs;
|
||||
outSs << header_ << "duration " << (duration.count() / 1000) << '.'
|
||||
<< std::setw(3) << std::setfill('0') << (duration.count() % 1000)
|
||||
<< "s. " << ss_->str();
|
||||
|
||||
auto node = beast::Journal::rentFromPool();
|
||||
thread_local std::string buffer;
|
||||
if (beast::Journal::isStructuredJournalEnabled())
|
||||
{
|
||||
beast::detail::SimpleJsonWriter writer{&node.str()};
|
||||
buffer.resize(5 * 1024);
|
||||
beast::detail::SimpleJsonWriter writer{&buffer};
|
||||
writer.startObject();
|
||||
writer.writeKey("Msg");
|
||||
writer.writeString(outSs.str());
|
||||
@@ -1146,9 +1145,9 @@ RclConsensusLogger::~RclConsensusLogger()
|
||||
}
|
||||
else
|
||||
{
|
||||
node.str() = outSs.str();
|
||||
buffer = outSs.str();
|
||||
}
|
||||
j_.sink().writeAlways(beast::severities::kInfo, node);
|
||||
j_.sink().writeAlways(beast::severities::kInfo, buffer);
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
@@ -553,14 +553,12 @@ class RclConsensusLogger
|
||||
beast::Journal j_;
|
||||
std::unique_ptr<std::stringstream> ss_;
|
||||
std::chrono::steady_clock::time_point start_;
|
||||
std::source_location location_;
|
||||
|
||||
public:
|
||||
explicit RclConsensusLogger(
|
||||
char const* label,
|
||||
bool validating,
|
||||
beast::Journal j,
|
||||
std::source_location location = std::source_location::current());
|
||||
beast::Journal j);
|
||||
~RclConsensusLogger();
|
||||
|
||||
std::unique_ptr<std::stringstream> const&
|
||||
|
||||
@@ -1644,7 +1644,6 @@ ApplicationImp::run()
|
||||
perfLog_->stop();
|
||||
|
||||
JLOG(m_journal.info()) << "Done.";
|
||||
logs_->flushBatch();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -113,17 +113,20 @@ flow(
|
||||
|
||||
if (auto stream = j.trace())
|
||||
{
|
||||
stream << "\nsrc: " << src << "\ndst: " << dst
|
||||
std::stringstream ss;
|
||||
ss << "\nsrc: " << src << "\ndst: " << dst
|
||||
<< "\nsrcIssue: " << srcIssue << "\ndstIssue: " << dstIssue;
|
||||
stream << "\nNumStrands: " << strands.size();
|
||||
ss << "\nNumStrands: " << strands.size();
|
||||
for (auto const& curStrand : strands)
|
||||
{
|
||||
stream << "NumSteps: " << curStrand.size();
|
||||
ss << "NumSteps: " << curStrand.size();
|
||||
for (auto const& step : curStrand)
|
||||
{
|
||||
stream << '\n' << *step << '\n';
|
||||
ss << '\n' << *step << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
std::move(stream) << ss.str();
|
||||
}
|
||||
|
||||
bool const srcIsXRP = isXRP(srcIssue.currency);
|
||||
|
||||
@@ -693,8 +693,6 @@ Config::loadFromString(std::string const& fileContents)
|
||||
if (getSingleSection(secConfig, SECTION_LOG_STYLE, strTemp, j_))
|
||||
LOG_STYLE = LogStyle::fromString(strTemp);
|
||||
|
||||
LOG_STYLE = LogStyle::Json;
|
||||
|
||||
if (getSingleSection(secConfig, SECTION_SWEEP_INTERVAL, strTemp, j_))
|
||||
{
|
||||
SWEEP_INTERVAL = beast::lexicalCastThrow<std::size_t>(strTemp);
|
||||
|
||||
@@ -822,14 +822,6 @@ PeerImp::cancelTimer() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
PeerImp::makePrefix(id_t id)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "[" << std::setfill('0') << std::setw(3) << id << "] ";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void
|
||||
PeerImp::doAccept()
|
||||
|
||||
@@ -831,14 +831,16 @@ PeerImp::PeerImp(
|
||||
app_.journal("Peer"),
|
||||
log::attributes(
|
||||
log::attr("NodeID", id),
|
||||
log::attr("RemoteAddress", to_string(slot->remote_endpoint()))
|
||||
log::attr("RemoteAddress", to_string(slot->remote_endpoint())),
|
||||
log::attr("PublicKey", toBase58(TokenType::NodePublic, publicKey))
|
||||
))
|
||||
, p_journal_(
|
||||
app_.journal("Protocol"),
|
||||
log::attributes(
|
||||
log::attr("NodeID", id),
|
||||
log::attr("RemoteAddress", to_string(slot->remote_endpoint())
|
||||
)))
|
||||
log::attr("RemoteAddress", to_string(slot->remote_endpoint())),
|
||||
log::attr("PublicKey", toBase58(TokenType::NodePublic, publicKey))
|
||||
))
|
||||
, stream_ptr_(std::move(stream_ptr))
|
||||
, socket_(stream_ptr_->next_layer().socket())
|
||||
, stream_(*stream_ptr_)
|
||||
|
||||
Reference in New Issue
Block a user