rippled
Loading...
Searching...
No Matches
Log.cpp
1#include <xrpl/basics/Log.h>
2#include <xrpl/basics/chrono.h>
3#include <xrpl/beast/utility/Journal.h>
4#include <xrpl/beast/utility/instrumentation.h>
5
6#include <boost/algorithm/string/predicate.hpp>
7#include <boost/filesystem/path.hpp>
8
9#include <chrono>
10#include <cstring>
11#include <fstream>
12#include <functional>
13#include <iostream>
14#include <memory>
15#include <mutex>
16#include <string>
17#include <utility>
18#include <vector>
19
20namespace ripple {
21
23 std::string const& partition,
25 Logs& logs)
26 : beast::Journal::Sink(thresh, false), logs_(logs), partition_(partition)
27{
28}
29
30void
32{
33 if (level < threshold())
34 return;
35
36 logs_.write(level, partition_, text, console());
37}
38
39void
42 std::string const& text)
43{
44 logs_.write(level, partition_, text, console());
45}
46
47//------------------------------------------------------------------------------
48
49Logs::File::File() : m_stream(nullptr)
50{
51}
52
53bool
54Logs::File::isOpen() const noexcept
55{
56 return m_stream != nullptr;
57}
58
59bool
60Logs::File::open(boost::filesystem::path const& path)
61{
62 close();
63
64 bool wasOpened = false;
65
66 // VFALCO TODO Make this work with Unicode file paths
68 new std::ofstream(path.c_str(), std::fstream::app));
69
70 if (stream->good())
71 {
72 m_path = path;
73
74 m_stream = std::move(stream);
75
76 wasOpened = true;
77 }
78
79 return wasOpened;
80}
81
82bool
84{
85 close();
86
87 return open(m_path);
88}
89
90void
92{
93 m_stream = nullptr;
94}
95
96void
97Logs::File::write(char const* text)
98{
99 if (m_stream != nullptr)
100 (*m_stream) << text;
101}
102
103void
104Logs::File::writeln(char const* text)
105{
106 if (m_stream != nullptr)
107 {
108 (*m_stream) << text;
109 (*m_stream) << std::endl;
110 }
111}
112
113//------------------------------------------------------------------------------
114
116 : thresh_(thresh) // default severity
117{
118}
119
120bool
121Logs::open(boost::filesystem::path const& pathToLogFile)
122{
123 return file_.open(pathToLogFile);
124}
125
128{
130 auto const result = sinks_.emplace(name, makeSink(name, thresh_));
131 return *result.first->second;
132}
133
136{
137 return get(name);
138}
139
142{
143 return beast::Journal(get(name));
144}
145
148{
149 return thresh_;
150}
151
152void
154{
156 thresh_ = thresh;
157 for (auto& sink : sinks_)
158 sink.second->threshold(thresh);
159}
160
163{
166 list.reserve(sinks_.size());
167 for (auto const& [name, sink] : sinks_)
168 list.emplace_back(name, toString(fromSeverity(sink->threshold())));
169 return list;
170}
171
172void
175 std::string const& partition,
176 std::string const& text,
177 bool console)
178{
179 std::string s;
180 format(s, text, level, partition);
182 file_.writeln(s);
183 if (!silent_)
184 std::cerr << s << '\n';
185 // VFALCO TODO Fix console output
186 // if (console)
187 // out_.write_console(s);
188}
189
192{
194 bool const wasOpened = file_.closeAndReopen();
195 if (wasOpened)
196 return "The log file was closed and reopened.";
197 return "The log file could not be closed and reopened.";
198}
199
202{
203 return std::make_unique<Sink>(name, threshold, *this);
204}
205
208{
209 using namespace beast::severities;
210 switch (level)
211 {
212 case kTrace:
213 return lsTRACE;
214 case kDebug:
215 return lsDEBUG;
216 case kInfo:
217 return lsINFO;
218 case kWarning:
219 return lsWARNING;
220 case kError:
221 return lsERROR;
222
223 // LCOV_EXCL_START
224 default:
225 UNREACHABLE("ripple::Logs::fromSeverity : invalid severity");
226 [[fallthrough]];
227 // LCOV_EXCL_STOP
228 case kFatal:
229 break;
230 }
231
232 return lsFATAL;
233}
234
237{
238 using namespace beast::severities;
239 switch (level)
240 {
241 case lsTRACE:
242 return kTrace;
243 case lsDEBUG:
244 return kDebug;
245 case lsINFO:
246 return kInfo;
247 case lsWARNING:
248 return kWarning;
249 case lsERROR:
250 return kError;
251 // LCOV_EXCL_START
252 default:
253 UNREACHABLE("ripple::Logs::toSeverity : invalid severity");
254 [[fallthrough]];
255 // LCOV_EXCL_STOP
256 case lsFATAL:
257 break;
258 }
259
260 return kFatal;
261}
262
265{
266 switch (s)
267 {
268 case lsTRACE:
269 return "Trace";
270 case lsDEBUG:
271 return "Debug";
272 case lsINFO:
273 return "Info";
274 case lsWARNING:
275 return "Warning";
276 case lsERROR:
277 return "Error";
278 case lsFATAL:
279 return "Fatal";
280 // LCOV_EXCL_START
281 default:
282 UNREACHABLE("ripple::Logs::toString : invalid severity");
283 return "Unknown";
284 // LCOV_EXCL_STOP
285 }
286}
287
290{
291 if (boost::iequals(s, "trace"))
292 return lsTRACE;
293
294 if (boost::iequals(s, "debug"))
295 return lsDEBUG;
296
297 if (boost::iequals(s, "info") || boost::iequals(s, "information"))
298 return lsINFO;
299
300 if (boost::iequals(s, "warn") || boost::iequals(s, "warning") ||
301 boost::iequals(s, "warnings"))
302 return lsWARNING;
303
304 if (boost::iequals(s, "error") || boost::iequals(s, "errors"))
305 return lsERROR;
306
307 if (boost::iequals(s, "fatal") || boost::iequals(s, "fatals"))
308 return lsFATAL;
309
310 return lsINVALID;
311}
312
313void
315 std::string& output,
316 std::string const& message,
318 std::string const& partition)
319{
320 output.reserve(message.size() + partition.size() + 100);
321
323
324 output += " ";
325 if (!partition.empty())
326 output += partition + ":";
327
328 using namespace beast::severities;
329 switch (severity)
330 {
331 case kTrace:
332 output += "TRC ";
333 break;
334 case kDebug:
335 output += "DBG ";
336 break;
337 case kInfo:
338 output += "NFO ";
339 break;
340 case kWarning:
341 output += "WRN ";
342 break;
343 case kError:
344 output += "ERR ";
345 break;
346 // LCOV_EXCL_START
347 default:
348 UNREACHABLE("ripple::Logs::format : invalid severity");
349 [[fallthrough]];
350 // LCOV_EXCL_STOP
351 case kFatal:
352 output += "FTL ";
353 break;
354 }
355
356 output += message;
357
358 // Limit the maximum length of the output
359 if (output.size() > maximumMessageCharacters)
360 {
362 output += "...";
363 }
364
365 // Attempt to prevent sensitive information from appearing in log files by
366 // redacting it with asterisks.
367 auto scrubber = [&output](char const* token) {
368 auto first = output.find(token);
369
370 // If we have found the specified token, then attempt to isolate the
371 // sensitive data (it's enclosed by double quotes) and mask it off:
372 if (first != std::string::npos)
373 {
374 first = output.find('\"', first + std::strlen(token));
375
376 if (first != std::string::npos)
377 {
378 auto last = output.find('\"', ++first);
379
380 if (last == std::string::npos)
381 last = output.size();
382
383 output.replace(first, last - first, last - first, '*');
384 }
385 }
386 };
387
388 scrubber("\"seed\"");
389 scrubber("\"seed_hex\"");
390 scrubber("\"secret\"");
391 scrubber("\"master_key\"");
392 scrubber("\"master_seed\"");
393 scrubber("\"master_seed_hex\"");
394 scrubber("\"passphrase\"");
395}
396
397//------------------------------------------------------------------------------
398
400{
401private:
405
406public:
407 DebugSink() : sink_(beast::Journal::getNullSink())
408 {
409 }
410
411 DebugSink(DebugSink const&) = delete;
412 DebugSink&
413 operator=(DebugSink const&) = delete;
414
415 DebugSink(DebugSink&&) = delete;
416 DebugSink&
417 operator=(DebugSink&&) = delete;
418
421 {
423
424 using std::swap;
425 swap(holder_, sink);
426
427 if (holder_)
428 sink_ = *holder_;
429 else
431
432 return sink;
433 }
434
437 {
439 return sink_.get();
440 }
441};
442
443static DebugSink&
445{
446 static DebugSink _;
447 return _;
448}
449
452{
453 return debugSink().set(std::move(sink));
454}
455
458{
459 return beast::Journal(debugSink().get());
460}
461
462} // namespace ripple
Abstraction for the underlying message destination.
Definition Journal.h:57
A generic endpoint for log messages.
Definition Journal.h:41
static Sink & getNullSink()
Returns a Sink which does nothing.
beast::Journal::Sink & get()
Definition Log.cpp:436
DebugSink(DebugSink &&)=delete
DebugSink(DebugSink const &)=delete
std::unique_ptr< beast::Journal::Sink > holder_
Definition Log.cpp:403
std::reference_wrapper< beast::Journal::Sink > sink_
Definition Log.cpp:402
DebugSink & operator=(DebugSink &&)=delete
std::mutex m_
Definition Log.cpp:404
DebugSink & operator=(DebugSink const &)=delete
std::unique_ptr< beast::Journal::Sink > set(std::unique_ptr< beast::Journal::Sink > sink)
Definition Log.cpp:420
bool isOpen() const noexcept
Determine if a system file is associated with the log.
Definition Log.cpp:54
bool closeAndReopen()
Close and re-open the system file associated with the log This assists in interoperating with externa...
Definition Log.cpp:83
void close()
Close the system file if it is open.
Definition Log.cpp:91
void write(char const *text)
write to the log file.
Definition Log.cpp:97
void writeln(char const *text)
write to the log file and append an end of line marker.
Definition Log.cpp:104
File()
Construct with no associated system file.
Definition Log.cpp:49
bool open(boost::filesystem::path const &path)
Associate a system file with the log.
Definition Log.cpp:60
void write(beast::severities::Severity level, std::string const &text) override
Write text to the sink at the specified severity.
Definition Log.cpp:31
void writeAlways(beast::severities::Severity level, std::string const &text) override
Bypass filter and write text to the sink at the specified severity.
Definition Log.cpp:40
Manages partitions for logging.
Definition Log.h:33
beast::Journal::Sink & get(std::string const &name)
Definition Log.cpp:127
beast::severities::Severity thresh_
Definition Log.h:148
static LogSeverity fromString(std::string const &s)
Definition Log.cpp:289
void write(beast::severities::Severity level, std::string const &partition, std::string const &text, bool console)
Definition Log.cpp:173
std::map< std::string, std::unique_ptr< beast::Journal::Sink >, boost::beast::iless > sinks_
Definition Log.h:147
File file_
Definition Log.h:149
beast::severities::Severity threshold() const
Definition Log.cpp:147
std::mutex mutex_
Definition Log.h:142
static std::string toString(LogSeverity s)
Definition Log.cpp:264
beast::Journal journal(std::string const &name)
Definition Log.cpp:141
virtual std::unique_ptr< beast::Journal::Sink > makeSink(std::string const &partition, beast::severities::Severity startingLevel)
Definition Log.cpp:201
std::string rotate()
Definition Log.cpp:191
static beast::severities::Severity toSeverity(LogSeverity level)
Definition Log.cpp:236
static void format(std::string &output, std::string const &message, beast::severities::Severity severity, std::string const &partition)
Definition Log.cpp:314
bool open(boost::filesystem::path const &pathToLogFile)
Definition Log.cpp:121
std::vector< std::pair< std::string, std::string > > partition_severities() const
Definition Log.cpp:162
bool silent_
Definition Log.h:150
beast::Journal::Sink & operator[](std::string const &name)
Definition Log.cpp:135
Logs(beast::severities::Severity level)
Definition Log.cpp:115
@ maximumMessageCharacters
Definition Log.h:225
static LogSeverity fromSeverity(beast::severities::Severity level)
Definition Log.cpp:207
T emplace_back(T... args)
T emplace(T... args)
T endl(T... args)
T find(T... args)
T is_same_v
A namespace for easy access to logging severity values.
Definition Journal.h:11
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:13
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
@ open
We haven't closed our ledger yet, but others might have.
beast::Journal debugLog()
Returns a debug journal.
Definition Log.cpp:457
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::unique_ptr< beast::Journal::Sink > setDebugLogSink(std::unique_ptr< beast::Journal::Sink > sink)
Set the sink for the debug journal.
Definition Log.cpp:451
static DebugSink & debugSink()
Definition Log.cpp:444
LogSeverity
Definition Log.h:19
@ lsDEBUG
Definition Log.h:23
@ lsINFO
Definition Log.h:24
@ lsERROR
Definition Log.h:27
@ lsWARNING
Definition Log.h:25
@ lsTRACE
Definition Log.h:21
@ lsINVALID
Definition Log.h:20
@ lsFATAL
Definition Log.h:28
T replace(T... args)
T reserve(T... args)
T resize(T... args)
T size(T... args)
T strlen(T... args)
T swap(T... args)