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
168 std::string const& partition,
169 std::string const& text,
170 bool console)
171{
172 std::string s;
173 format(s, text, level, partition);
175 file_.writeln(s);
176 if (!silent_)
177 std::cerr << s << '\n';
178 // VFALCO TODO Fix console output
179 // if (console)
180 // out_.write_console(s);
181}
182
185{
187 bool const wasOpened = file_.closeAndReopen();
188 if (wasOpened)
189 return "The log file was closed and reopened.";
190 return "The log file could not be closed and reopened.";
191}
192
195{
196 return std::make_unique<Sink>(name, threshold, *this);
197}
198
201{
202 using namespace beast::severities;
203 switch (level)
204 {
205 case kTrace:
206 return lsTRACE;
207 case kDebug:
208 return lsDEBUG;
209 case kInfo:
210 return lsINFO;
211 case kWarning:
212 return lsWARNING;
213 case kError:
214 return lsERROR;
215
216 // LCOV_EXCL_START
217 default:
218 UNREACHABLE("xrpl::Logs::fromSeverity : invalid severity");
219 [[fallthrough]];
220 // LCOV_EXCL_STOP
221 case kFatal:
222 break;
223 }
224
225 return lsFATAL;
226}
227
230{
231 using namespace beast::severities;
232 switch (level)
233 {
234 case lsTRACE:
235 return kTrace;
236 case lsDEBUG:
237 return kDebug;
238 case lsINFO:
239 return kInfo;
240 case lsWARNING:
241 return kWarning;
242 case lsERROR:
243 return kError;
244 // LCOV_EXCL_START
245 default:
246 UNREACHABLE("xrpl::Logs::toSeverity : invalid severity");
247 [[fallthrough]];
248 // LCOV_EXCL_STOP
249 case lsFATAL:
250 break;
251 }
252
253 return kFatal;
254}
255
258{
259 switch (s)
260 {
261 case lsTRACE:
262 return "Trace";
263 case lsDEBUG:
264 return "Debug";
265 case lsINFO:
266 return "Info";
267 case lsWARNING:
268 return "Warning";
269 case lsERROR:
270 return "Error";
271 case lsFATAL:
272 return "Fatal";
273 // LCOV_EXCL_START
274 default:
275 UNREACHABLE("xrpl::Logs::toString : invalid severity");
276 return "Unknown";
277 // LCOV_EXCL_STOP
278 }
279}
280
283{
284 if (boost::iequals(s, "trace"))
285 return lsTRACE;
286
287 if (boost::iequals(s, "debug"))
288 return lsDEBUG;
289
290 if (boost::iequals(s, "info") || boost::iequals(s, "information"))
291 return lsINFO;
292
293 if (boost::iequals(s, "warn") || boost::iequals(s, "warning") || boost::iequals(s, "warnings"))
294 return lsWARNING;
295
296 if (boost::iequals(s, "error") || boost::iequals(s, "errors"))
297 return lsERROR;
298
299 if (boost::iequals(s, "fatal") || boost::iequals(s, "fatals"))
300 return lsFATAL;
301
302 return lsINVALID;
303}
304
305void
307 std::string& output,
308 std::string const& message,
310 std::string const& partition)
311{
312 output.reserve(message.size() + partition.size() + 100);
313
315
316 output += " ";
317 if (!partition.empty())
318 output += partition + ":";
319
320 using namespace beast::severities;
321 switch (severity)
322 {
323 case kTrace:
324 output += "TRC ";
325 break;
326 case kDebug:
327 output += "DBG ";
328 break;
329 case kInfo:
330 output += "NFO ";
331 break;
332 case kWarning:
333 output += "WRN ";
334 break;
335 case kError:
336 output += "ERR ";
337 break;
338 // LCOV_EXCL_START
339 default:
340 UNREACHABLE("xrpl::Logs::format : invalid severity");
341 [[fallthrough]];
342 // LCOV_EXCL_STOP
343 case kFatal:
344 output += "FTL ";
345 break;
346 }
347
348 output += message;
349
350 // Limit the maximum length of the output
351 if (output.size() > maximumMessageCharacters)
352 {
354 output += "...";
355 }
356
357 // Attempt to prevent sensitive information from appearing in log files by
358 // redacting it with asterisks.
359 auto scrubber = [&output](char const* token) {
360 auto first = output.find(token);
361
362 // If we have found the specified token, then attempt to isolate the
363 // sensitive data (it's enclosed by double quotes) and mask it off:
364 if (first != std::string::npos)
365 {
366 first = output.find('\"', first + std::strlen(token));
367
368 if (first != std::string::npos)
369 {
370 auto last = output.find('\"', ++first);
371
372 if (last == std::string::npos)
373 last = output.size();
374
375 output.replace(first, last - first, last - first, '*');
376 }
377 }
378 };
379
380 scrubber("\"seed\"");
381 scrubber("\"seed_hex\"");
382 scrubber("\"secret\"");
383 scrubber("\"master_key\"");
384 scrubber("\"master_seed\"");
385 scrubber("\"master_seed_hex\"");
386 scrubber("\"passphrase\"");
387}
388
389//------------------------------------------------------------------------------
390
392{
393private:
397
398public:
399 DebugSink() : sink_(beast::Journal::getNullSink())
400 {
401 }
402
403 DebugSink(DebugSink const&) = delete;
404 DebugSink&
405 operator=(DebugSink const&) = delete;
406
407 DebugSink(DebugSink&&) = delete;
408 DebugSink&
409 operator=(DebugSink&&) = delete;
410
413 {
415
416 using std::swap;
417 swap(holder_, sink);
418
419 if (holder_)
420 sink_ = *holder_;
421 else
423
424 return sink;
425 }
426
429 {
431 return sink_.get();
432 }
433};
434
435static DebugSink&
437{
438 static DebugSink _;
439 return _;
440}
441
444{
445 return debugSink().set(std::move(sink));
446}
447
450{
451 return beast::Journal(debugSink().get());
452}
453
454} // namespace xrpl
Abstraction for the underlying message destination.
Definition Journal.h:56
A generic endpoint for log messages.
Definition Journal.h:40
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:412
DebugSink(DebugSink &&)=delete
beast::Journal::Sink & get()
Definition Log.cpp:428
DebugSink & operator=(DebugSink const &)=delete
DebugSink & operator=(DebugSink &&)=delete
std::mutex m_
Definition Log.cpp:396
std::reference_wrapper< beast::Journal::Sink > sink_
Definition Log.cpp:394
DebugSink(DebugSink const &)=delete
std::unique_ptr< beast::Journal::Sink > holder_
Definition Log.cpp:395
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:32
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:138
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:194
beast::Journal::Sink & get(std::string const &name)
Definition Log.cpp:120
static LogSeverity fromSeverity(beast::severities::Severity level)
Definition Log.cpp:200
bool silent_
Definition Log.h:140
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:282
@ maximumMessageCharacters
Definition Log.h:214
static void format(std::string &output, std::string const &message, beast::severities::Severity severity, std::string const &partition)
Definition Log.cpp:306
std::mutex mutex_
Definition Log.h:136
std::string rotate()
Definition Log.cpp:184
std::map< std::string, std::unique_ptr< beast::Journal::Sink >, boost::beast::iless > sinks_
Definition Log.h:137
static std::string toString(LogSeverity s)
Definition Log.cpp:257
File file_
Definition Log.h:139
static beast::severities::Severity toSeverity(LogSeverity level)
Definition Log.cpp:229
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:10
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:12
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:449
std::unique_ptr< beast::Journal::Sink > setDebugLogSink(std::unique_ptr< beast::Journal::Sink > sink)
Set the sink for the debug journal.
Definition Log.cpp:443
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:600
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:436
LogSeverity
Definition Log.h:18
@ lsERROR
Definition Log.h:26
@ lsWARNING
Definition Log.h:24
@ lsINVALID
Definition Log.h:19
@ lsDEBUG
Definition Log.h:22
@ lsFATAL
Definition Log.h:27
@ lsINFO
Definition Log.h:23
@ lsTRACE
Definition Log.h:20
@ 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)