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