Ethereum  PoC-8
The C++ Implementation of Ethereum
Log.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include "Log.h"
23 
24 #ifdef __APPLE__
25 #include <pthread.h>
26 #endif
27 
28 #include <boost/core/null_deleter.hpp>
29 #include <boost/log/attributes/clock.hpp>
30 #include <boost/log/attributes/function.hpp>
31 #include <boost/log/expressions.hpp>
32 #include <boost/log/sinks/text_ostream_backend.hpp>
33 #include <boost/log/sources/global_logger_storage.hpp>
34 #include <boost/log/sources/severity_channel_logger.hpp>
35 #include <boost/log/support/date_time.hpp>
36 #include <boost/log/utility/exception_handler.hpp>
37 
38 #if defined(NDEBUG)
39 #include <boost/log/sinks/async_frontend.hpp>
40 template <class T>
41 using log_sink = boost::log::sinks::asynchronous_sink<T>;
42 #else
43 #include <boost/log/sinks/sync_frontend.hpp>
44 template <class T>
45 using log_sink = boost::log::sinks::synchronous_sink<T>;
46 #endif
47 
48 namespace dev
49 {
50 BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
51 BOOST_LOG_ATTRIBUTE_KEYWORD(context, "Context", std::string)
52 BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)
53 BOOST_LOG_ATTRIBUTE_KEYWORD(threadName, "ThreadName", std::string)
54 BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
55 
56 namespace
57 {
59 struct ThreadLocalLogName
60 {
61  ThreadLocalLogName(std::string const& _name) { m_name.reset(new std::string(_name)); }
62  boost::thread_specific_ptr<std::string> m_name;
63 };
64 
65 ThreadLocalLogName g_logThreadName("main");
66 
67 auto const g_timestampFormatter =
68  (boost::log::expressions::stream
69  << EthViolet << boost::log::expressions::format_date_time(timestamp, "%m-%d %H:%M:%S")
70  << EthReset " ");
71 
72 std::string verbosityToString(int _verbosity)
73 {
74  switch (_verbosity)
75  {
76  case VerbosityError:
77  return "ERROR";
78  case VerbosityWarning:
79  return "WARN";
80  case VerbosityInfo:
81  return "INFO";
82  case VerbosityDebug:
83  return "DEBUG";
84  case VerbosityTrace:
85  return "TRACE";
86  }
87  return {};
88 }
89 
90 void formatter(boost::log::record_view const& _rec, boost::log::formatting_ostream& _strm)
91 {
92  _strm << std::setw(5) << std::left << verbosityToString(_rec.attribute_values()[severity].get())
93  << " ";
94 
95  g_timestampFormatter(_rec, _strm);
96 
97  _strm << EthNavy << std::setw(4) << std::left << _rec[threadName] << EthReset " ";
98  _strm << std::setw(6) << std::left << _rec[channel] << " ";
99  if (boost::log::expressions::has_attr(context)(_rec))
100  _strm << EthNavy << _rec[context] << EthReset " ";
101 
102  _strm << _rec[boost::log::expressions::smessage];
103 }
104 
105 } // namespace
106 
107 std::string getThreadName()
108 {
109 #if defined(__GLIBC__) || defined(__APPLE__)
110  char buffer[128];
111  pthread_getname_np(pthread_self(), buffer, 127);
112  buffer[127] = 0;
113  return buffer;
114 #else
115  return g_logThreadName.m_name.get() ? *g_logThreadName.m_name.get() : "<unknown>";
116 #endif
117 }
118 
119 void setThreadName(std::string const& _n)
120 {
121 #if defined(__GLIBC__)
122  pthread_setname_np(pthread_self(), _n.c_str());
123 #elif defined(__APPLE__)
124  pthread_setname_np(_n.c_str());
125 #else
126  g_logThreadName.m_name.reset(new std::string(_n));
127 #endif
128 }
129 
130 void setupLogging(LoggingOptions const& _options)
131 {
132  auto sink = boost::make_shared<log_sink<boost::log::sinks::text_ostream_backend>>();
133 
134  boost::shared_ptr<std::ostream> stream{&std::cout, boost::null_deleter{}};
135  sink->locked_backend()->add_stream(stream);
136  sink->set_filter([_options](boost::log::attribute_value_set const& _set) {
137  if (_set[severity] > _options.verbosity)
138  return false;
139 
140  auto const messageChannel = _set[channel];
141  return (_options.includeChannels.empty() ||
142  contains(_options.includeChannels, messageChannel)) &&
143  !contains(_options.excludeChannels, messageChannel);
144  });
145 
146  sink->set_formatter(&formatter);
147 
148  boost::log::core::get()->add_sink(sink);
149 
150  boost::log::core::get()->add_global_attribute(
151  "ThreadName", boost::log::attributes::make_function(&getThreadName));
152  boost::log::core::get()->add_global_attribute(
153  "TimeStamp", boost::log::attributes::local_clock());
154 
155  boost::log::core::get()->set_exception_handler(
156  boost::log::make_exception_handler<std::exception>([](std::exception const& _ex) {
157  std::cerr << "Exception from the logging library: " << _ex.what() << '\n';
158  }));
159 }
160 
161 } // namespace dev
log_sink
boost::log::sinks::synchronous_sink< T > log_sink
Definition: Log.cpp:45
EthReset
#define EthReset
Definition: Terminal.h:79
dev::VerbosityWarning
@ VerbosityWarning
Definition: Log.h:69
dev::VerbosityInfo
@ VerbosityInfo
Definition: Log.h:70
EthNavy
#define EthNavy
Definition: Terminal.h:92
dev::VerbosityError
@ VerbosityError
Definition: Log.h:68
dev::setupLogging
void setupLogging(LoggingOptions const &_options)
Definition: Log.cpp:130
m_name
boost::thread_specific_ptr< std::string > m_name
Definition: Log.cpp:62
dev::VerbosityDebug
@ VerbosityDebug
Definition: Log.h:71
EthViolet
#define EthViolet
Definition: Terminal.h:94
dev::contains
bool contains(T const &_t, V const &_v)
Definition: CommonData.h:324
dev
Definition: Address.cpp:21
dev::VerbosityTrace
@ VerbosityTrace
Definition: Log.h:72
dev::setThreadName
void setThreadName(std::string const &_n)
Definition: Log.cpp:119
Log.h
dev::getThreadName
std::string getThreadName()
Set the current thread's log name.
Definition: Log.cpp:107