xrpld
Loading...
Searching...
No Matches
Log.cpp
1#include <xrpl/basics/Log.h>
2
3#include <xrpl/basics/chrono.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/beast/utility/instrumentation.h>
6
7#include <boost/algorithm/string/predicate.hpp>
8#include <boost/filesystem/path.hpp>
9
10#include <chrono>
11#include <cstring>
12#include <fstream>
13#include <functional>
14#include <iostream>
15#include <memory>
16#include <mutex>
17#include <optional>
18#include <string>
19#include <utility>
20#include <vector>
21
22namespace xrpl {
23
25 : beast::Journal::Sink(thresh, false), logs_(logs), partition_(std::move(partition))
26{
27}
28
29void
31{
32 if (level < threshold())
33 return;
34
35 logs_.write(level, partition_, text, console());
36}
37
38void
40{
41 logs_.write(level, partition_, text, console());
42}
43
44//------------------------------------------------------------------------------
45
47{
48}
49
50bool
51Logs::File::isOpen() const noexcept
52{
53 return stream_ != nullptr;
54}
55
56bool
57Logs::File::open(boost::filesystem::path const& path)
58{
59 close();
60
61 bool wasOpened = false;
62
63 // VFALCO TODO Make this work with Unicode file paths
65 std::make_unique<std::ofstream>(path.c_str(), std::fstream::app);
66
67 if (stream->good())
68 {
69 path_ = path;
70
71 stream_ = std::move(stream);
72
73 wasOpened = true;
74 }
75
76 return wasOpened;
77}
78
79bool
81{
82 close();
83
84 return open(path_);
85}
86
87void
89{
90 stream_ = nullptr;
91}
92
93void
94Logs::File::write(char const* text)
95{
96 if (stream_ != nullptr)
97 (*stream_) << text;
98}
99
100void
101Logs::File::writeln(char const* text)
102{
103 if (stream_ != nullptr)
104 {
105 (*stream_) << text;
106 (*stream_) << std::endl;
107 }
108}
109
110//------------------------------------------------------------------------------
111
112Logs::Logs(beast::Severity thresh) : thresh_(thresh) // default severity
113{
114}
115
116bool
117Logs::open(boost::filesystem::path const& pathToLogFile)
118{
119 return file_.open(pathToLogFile);
120}
121
124{
125 std::scoped_lock const lock(mutex_);
126 auto const result = sinks_.emplace(name, makeSink(name, thresh_));
127 return *result.first->second;
128}
129
132{
133 return get(name);
134}
135
138{
139 return beast::Journal(get(name));
140}
141
144{
145 return thresh_;
146}
147
148void
150{
151 std::scoped_lock const lock(mutex_);
152 thresh_ = thresh;
153 for (auto& sink : sinks_)
154 sink.second->threshold(thresh);
155}
156
159{
161 std::scoped_lock const lock(mutex_);
162 list.reserve(sinks_.size());
163 for (auto const& [name, sink] : sinks_)
164 list.emplace_back(name, toString(sink->threshold()));
165 return list;
166}
167
168void
170 beast::Severity level,
171 std::string const& partition,
172 std::string const& text,
173 bool console)
174{
175 std::string s;
176 format(s, text, level, partition);
177 std::scoped_lock const lock(mutex_);
178 file_.writeln(s);
179 if (!silent_)
180 std::cerr << s << '\n';
181 // VFALCO TODO Fix console output
182 // if (console)
183 // out_.write_console(s);
184}
185
188{
189 std::scoped_lock const lock(mutex_);
190 bool const wasOpened = file_.closeAndReopen();
191 if (wasOpened)
192 return "The log file was closed and reopened.";
193 return "The log file could not be closed and reopened.";
194}
195
198{
199 return std::make_unique<Sink>(name, threshold, *this);
200}
201
204{
205 switch (s)
206 {
208 return "Trace";
210 return "Debug";
212 return "Info";
214 return "Warning";
216 return "Error";
218 return "Fatal";
219 // LCOV_EXCL_START
220 default:
221 UNREACHABLE("xrpl::Logs::toString : invalid severity");
222 return "Unknown";
223 // LCOV_EXCL_STOP
224 }
225}
226
229{
230 if (boost::iequals(s, "trace"))
232
233 if (boost::iequals(s, "debug"))
235
236 if (boost::iequals(s, "info") || boost::iequals(s, "information"))
238
239 if (boost::iequals(s, "warn") || boost::iequals(s, "warning") || boost::iequals(s, "warnings"))
241
242 if (boost::iequals(s, "error") || boost::iequals(s, "errors"))
244
245 if (boost::iequals(s, "fatal") || boost::iequals(s, "fatals"))
247
248 return std::nullopt;
249}
250
251void
253 std::string& output,
254 std::string const& message,
255 beast::Severity severity,
256 std::string const& partition)
257{
258 output.reserve(message.size() + partition.size() + 100);
259
261
262 output += " ";
263 if (!partition.empty())
264 output += partition + ":";
265
266 using beast::Severity;
267 switch (severity)
268 {
269 case Severity::Trace:
270 output += "TRC ";
271 break;
272 case Severity::Debug:
273 output += "DBG ";
274 break;
275 case Severity::Info:
276 output += "NFO ";
277 break;
278 case Severity::Warning:
279 output += "WRN ";
280 break;
281 case Severity::Error:
282 output += "ERR ";
283 break;
284 // LCOV_EXCL_START
285 default:
286 UNREACHABLE("xrpl::Logs::format : invalid severity");
287 [[fallthrough]];
288 // LCOV_EXCL_STOP
289 case Severity::Fatal:
290 output += "FTL ";
291 break;
292 }
293
294 output += message;
295
296 // Limit the maximum length of the output
297 if (output.size() > kMaximumMessageCharacters)
298 {
300 output += "...";
301 }
302
303 // Attempt to prevent sensitive information from appearing in log files by
304 // redacting it with asterisks.
305 auto scrubber = [&output](char const* token) {
306 auto first = output.find(token);
307
308 // If we have found the specified token, then attempt to isolate the
309 // sensitive data (it's enclosed by double quotes) and mask it off:
310 if (first != std::string::npos)
311 {
312 first = output.find('\"', first + std::strlen(token));
313
314 if (first != std::string::npos)
315 {
316 auto last = output.find('\"', ++first);
317
318 if (last == std::string::npos)
319 last = output.size();
320
321 output.replace(first, last - first, last - first, '*');
322 }
323 }
324 };
325
326 scrubber("\"seed\"");
327 scrubber("\"seed_hex\"");
328 scrubber("\"secret\"");
329 scrubber("\"master_key\"");
330 scrubber("\"master_seed\"");
331 scrubber("\"master_seed_hex\"");
332 scrubber("\"passphrase\"");
333}
334
335//------------------------------------------------------------------------------
336
338{
339private:
343
344public:
345 DebugSink() : sink_(beast::Journal::getNullSink())
346 {
347 }
348
349 DebugSink(DebugSink const&) = delete;
350 DebugSink&
351 operator=(DebugSink const&) = delete;
352
353 DebugSink(DebugSink&&) = delete;
354 DebugSink&
355 operator=(DebugSink&&) = delete;
356
359 {
360 std::scoped_lock const _(mtx_);
361
362 using std::swap;
363 swap(holder_, sink);
364
365 if (holder_)
366 {
367 sink_ = *holder_;
368 }
369 else
370 {
372 }
373
374 return sink;
375 }
376
379 {
380 std::scoped_lock const _(mtx_);
381 return sink_.get();
382 }
383};
384
385static DebugSink&
387{
388 static DebugSink kInst;
389 return kInst;
390}
391
394{
395 return debugSink().set(std::move(sink));
396}
397
400{
401 return beast::Journal(debugSink().get());
402}
403
404} // namespace xrpl
Abstraction for the underlying message destination.
Definition Journal.h:51
virtual bool console() const
Returns true if a message is also written to the Output Window (MSVC).
A generic endpoint for log messages.
Definition Journal.h:38
static Sink & getNullSink()
Returns a Sink which does nothing.
std::unique_ptr< beast::Journal::Sink > set(std::unique_ptr< beast::Journal::Sink > sink)
Definition Log.cpp:358
DebugSink(DebugSink &&)=delete
beast::Journal::Sink & get()
Definition Log.cpp:378
DebugSink & operator=(DebugSink const &)=delete
DebugSink & operator=(DebugSink &&)=delete
std::reference_wrapper< beast::Journal::Sink > sink_
Definition Log.cpp:340
std::mutex mtx_
Definition Log.cpp:342
DebugSink(DebugSink const &)=delete
std::unique_ptr< beast::Journal::Sink > holder_
Definition Log.cpp:341
void writeln(char const *text)
write to the log file and append an end of line marker.
Definition Log.cpp:101
bool open(boost::filesystem::path const &path)
Associate a system file with the log.
Definition Log.cpp:57
bool closeAndReopen()
Close and re-open the system file associated with the log This assists in interoperating with externa...
Definition Log.cpp:80
boost::filesystem::path path_
Definition Log.h:121
void write(char const *text)
write to the log file.
Definition Log.cpp:94
bool isOpen() const noexcept
Determine if a system file is associated with the log.
Definition Log.cpp:51
void close()
Close the system file if it is open.
Definition Log.cpp:88
std::unique_ptr< std::ofstream > stream_
Definition Log.h:120
File()
Construct with no associated system file.
Definition Log.cpp:46
void writeAlways(beast::Severity level, std::string const &text) override
Bypass filter and write text to the sink at the specified severity.
Definition Log.cpp:39
void write(beast::Severity level, std::string const &text) override
Write text to the sink at the specified severity.
Definition Log.cpp:30
Sink(std::string partition, beast::Severity thresh, Logs &logs)
Definition Log.cpp:24
std::string partition_
Definition Log.h:26
Logs & logs_
Definition Log.h:25
std::vector< std::pair< std::string, std::string > > partitionSeverities() const
Definition Log.cpp:158
bool open(boost::filesystem::path const &pathToLogFile)
Definition Log.cpp:117
beast::Journal journal(std::string const &name)
Definition Log.cpp:137
static std::string toString(beast::Severity s)
Definition Log.cpp:203
beast::Journal::Sink & get(std::string const &name)
Definition Log.cpp:123
beast::Severity thresh_
Definition Log.h:126
bool silent_
Definition Log.h:128
beast::Severity threshold() const
Definition Log.cpp:143
void write(beast::Severity level, std::string const &partition, std::string const &text, bool console)
Definition Log.cpp:169
static void format(std::string &output, std::string const &message, beast::Severity severity, std::string const &partition)
Definition Log.cpp:252
std::mutex mutex_
Definition Log.h:124
static std::optional< beast::Severity > fromString(std::string const &s)
Definition Log.cpp:228
std::string rotate()
Definition Log.cpp:187
std::map< std::string, std::unique_ptr< beast::Journal::Sink >, boost::beast::iless > sinks_
Definition Log.h:125
static constexpr auto kMaximumMessageCharacters
Definition Log.h:194
Logs(beast::Severity level)
Definition Log.cpp:112
File file_
Definition Log.h:127
virtual std::unique_ptr< beast::Journal::Sink > makeSink(std::string const &partition, beast::Severity startingLevel)
Definition Log.cpp:197
beast::Journal::Sink & operator[](std::string const &name)
Definition Log.cpp:131
T emplace_back(T... args)
T endl(T... args)
T find(T... args)
T make_unique(T... args)
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:11
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:399
std::unique_ptr< beast::Journal::Sink > setDebugLogSink(std::unique_ptr< beast::Journal::Sink > sink)
Set the sink for the debug journal.
Definition Log.cpp:393
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
static DebugSink & debugSink()
Definition Log.cpp:386
std::string to_string(BaseUInt< Bits, Tag > const &a)
Definition base_uint.h:633
T replace(T... args)
T reserve(T... args)
T resize(T... args)
T size(T... args)
T strlen(T... args)
T swap(T... args)