-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathLog.cpp
158 lines (131 loc) · 4.79 KB
/
Log.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Aleth: Ethereum C++ client, tools and libraries.
// Copyright 2013-2019 Aleth Authors.
// Licensed under the GNU General Public License, Version 3.
#include "Log.h"
#ifdef __APPLE__
#include <pthread.h>
#endif
#include <boost/core/null_deleter.hpp>
#include <boost/log/attributes/clock.hpp>
#include <boost/log/attributes/function.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/severity_channel_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/exception_handler.hpp>
#if defined(NDEBUG)
#include <boost/log/sinks/async_frontend.hpp>
template <class T>
using log_sink = boost::log::sinks::asynchronous_sink<T>;
#else
#include <boost/log/sinks/sync_frontend.hpp>
template <class T>
using log_sink = boost::log::sinks::synchronous_sink<T>;
#endif
namespace dev
{
BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(prefix, "Prefix", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(suffix, "Suffix", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)
BOOST_LOG_ATTRIBUTE_KEYWORD(threadName, "ThreadName", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
namespace
{
/// Associate a name with each thread for nice logging.
struct ThreadLocalLogName
{
ThreadLocalLogName(std::string const& _name) { m_name.reset(new std::string(_name)); }
boost::thread_specific_ptr<std::string> m_name;
};
ThreadLocalLogName g_logThreadName("main");
auto const g_timestampFormatter =
(boost::log::expressions::stream
<< EthViolet << boost::log::expressions::format_date_time(timestamp, "%m-%d %H:%M:%S")
<< EthReset " ");
std::string verbosityToString(int _verbosity)
{
switch (_verbosity)
{
case VerbosityError:
return "ERROR";
case VerbosityWarning:
return "WARN";
case VerbosityInfo:
return "INFO";
case VerbosityDebug:
return "DEBUG";
case VerbosityTrace:
return "TRACE";
}
return {};
}
void formatter(boost::log::record_view const& _rec, boost::log::formatting_ostream& _strm)
{
_strm << std::setw(5) << std::left << verbosityToString(_rec.attribute_values()[severity].get())
<< " ";
g_timestampFormatter(_rec, _strm);
_strm << EthNavy << std::setw(4) << std::left << _rec[threadName] << EthReset " ";
_strm << std::setw(6) << std::left << _rec[channel] << " ";
if (boost::log::expressions::has_attr(prefix)(_rec))
_strm << EthNavy << _rec[prefix] << EthReset " ";
_strm << _rec[boost::log::expressions::smessage];
if (boost::log::expressions::has_attr(suffix)(_rec))
_strm << " " EthNavy << _rec[suffix] << EthReset;
}
std::atomic<bool> g_vmTraceEnabled{false};
} // namespace
std::string getThreadName()
{
#if defined(__GLIBC__) || defined(__APPLE__)
char buffer[128];
pthread_getname_np(pthread_self(), buffer, 127);
buffer[127] = 0;
return buffer;
#else
return g_logThreadName.m_name.get() ? *g_logThreadName.m_name.get() : "<unknown>";
#endif
}
void setThreadName(std::string const& _n)
{
#if defined(__GLIBC__)
pthread_setname_np(pthread_self(), _n.c_str());
#elif defined(__APPLE__)
pthread_setname_np(_n.c_str());
#else
g_logThreadName.m_name.reset(new std::string(_n));
#endif
}
void setupLogging(LoggingOptions const& _options)
{
auto sink = boost::make_shared<log_sink<boost::log::sinks::text_ostream_backend>>();
boost::shared_ptr<std::ostream> stream{&std::cout, boost::null_deleter{}};
sink->locked_backend()->add_stream(stream);
// Enable auto-flushing after each log record written
sink->locked_backend()->auto_flush(true);
sink->set_filter([_options](boost::log::attribute_value_set const& _set) {
if (_set[severity] > _options.verbosity)
return false;
auto const messageChannel = _set[channel];
return (_options.includeChannels.empty() ||
contains(_options.includeChannels, messageChannel)) &&
!contains(_options.excludeChannels, messageChannel);
});
sink->set_formatter(&formatter);
boost::log::core::get()->add_sink(sink);
boost::log::core::get()->add_global_attribute(
"ThreadName", boost::log::attributes::make_function(&getThreadName));
boost::log::core::get()->add_global_attribute(
"TimeStamp", boost::log::attributes::local_clock());
boost::log::core::get()->set_exception_handler(
boost::log::make_exception_handler<std::exception>([](std::exception const& _ex) {
std::cerr << "Exception from the logging library: " << _ex.what() << '\n';
}));
g_vmTraceEnabled = _options.vmTrace;
}
bool isVmTraceEnabled()
{
return g_vmTraceEnabled;
}
} // namespace dev