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