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