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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
#include "Logger.hpp"
#include <boost/algorithm/string/predicate.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/core.hpp>
#include <boost/log/common.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/expressions/keyword.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/attributes/clock.hpp>
#include <boost/log/attributes/counter.hpp>
#include <boost/log/attributes/current_process_id.hpp>
#include <boost/log/attributes/current_thread_id.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/filter_parser.hpp>
#include <boost/log/utility/setup/from_stream.hpp>
#include <boost/log/utility/setup/settings.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/filesystem/fstream.hpp>
#include <string>
namespace fs = boost::filesystem;
namespace logging = boost::log;
namespace srcs = logging::sources;
namespace sinks = logging::sinks;
namespace keywords = logging::keywords;
namespace expr = logging::expressions;
namespace attrs = logging::attributes;
namespace ptime = boost::posix_time;
BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS (sys,
srcs::severity_channel_logger_mt<logging::trivial::severity_level>,
(keywords::channel = "SYSLOG"));
BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS (data,
srcs::severity_channel_logger_mt<logging::trivial::severity_level>,
(keywords::channel = "DATALOG"));
namespace Logger
{
namespace
{
// Custom formatter factory to add TimeStamp format support in config ini file.
// Allows %TimeStamp(format=\"%Y.%m.%d %H:%M:%S.%f\")% to be used in ini config file for property Format.
class TimeStampFormatterFactory
: public logging::basic_formatter_factory<char, ptime::ptime>
{
public:
formatter_type create_formatter (logging::attribute_name const& name, args_map const& args)
{
args_map::const_iterator it = args.find ("format");
if (it != args.end ())
{
return expr::stream
<< expr::format_date_time<ptime::ptime>
(
expr::attr<ptime::ptime> (name), it->second
);
}
else
{
return expr::stream
<< expr::attr<ptime::ptime> (name);
}
}
};
// Custom formatter factory to add Uptime format support in config ini file.
// Allows %Uptime(format=\"%O:%M:%S.%f\")% to be used in ini config file for property Format.
// attrs::timer value type is ptime::time_duration
class UptimeFormatterFactory
: public logging::basic_formatter_factory<char, ptime::time_duration>
{
public:
formatter_type create_formatter (logging::attribute_name const& name, args_map const& args)
{
args_map::const_iterator it = args.find ("format");
if (it != args.end ())
{
return expr::stream
<< expr::format_date_time<ptime::time_duration>
(
expr::attr<ptime::time_duration> (name), it->second
);
}
else
{
return expr::stream
<< expr::attr<ptime::time_duration> (name);
}
}
};
class CommonInitialization
{
public:
CommonInitialization ()
{
// Add attributes: LineID, TimeStamp, ProcessID, ThreadID, and Uptime
auto core = logging::core::get ();
core->add_global_attribute ("LineID", attrs::counter<unsigned int> (1));
core->add_global_attribute ("TimeStamp", attrs::utc_clock ());
core->add_global_attribute ("ProcessID", attrs::current_process_id ());
core->add_global_attribute ("ThreadID", attrs::current_thread_id ());
core->add_global_attribute ("Uptime", attrs::timer ());
// Allows %Severity% to be used in ini config file for property Filter.
logging::register_simple_filter_factory<logging::trivial::severity_level, char> ("Severity");
// Allows %Severity% to be used in ini config file for property Format.
logging::register_simple_formatter_factory<logging::trivial::severity_level, char> ("Severity");
// Allows %TimeStamp(format=\"%Y.%m.%d %H:%M:%S.%f\")% to be used in ini config file for property Format.
logging::register_formatter_factory ("TimeStamp", boost::make_shared<TimeStampFormatterFactory> ());
// Allows %Uptime(format=\"%O:%M:%S.%f\")% to be used in ini config file for property Format.
logging::register_formatter_factory ("Uptime", boost::make_shared<UptimeFormatterFactory> ());
}
~CommonInitialization ()
{
}
};
}
void init ()
{
CommonInitialization ci;
}
void init_from_config (std::wistream& stream)
{
CommonInitialization ci;
try
{
// Still can throw even with the exception suppressor above.
logging::init_from_stream (stream);
}
catch (std::exception& e)
{
std::string err = "Caught exception initializing boost logging: ";
err += e.what ();
// Since we cannot be sure of boost log state, output to cerr and cout.
std::cerr << "ERROR: " << err << std::endl;
LOG_ERROR (err);
throw;
}
}
void disable ()
{
logging::core::get ()->set_logging_enabled (false);
}
void add_datafile_log (std::wstring const& log_file_name)
{
// Create a text file sink
boost::shared_ptr<sinks::wtext_ostream_backend> backend
(
new sinks::wtext_ostream_backend()
);
backend->add_stream (boost::shared_ptr<std::wostream> (new fs::wofstream (log_file_name)));
// Flush after each log record
backend->auto_flush (true);
// Create a sink for the backend
typedef sinks::synchronous_sink<sinks::wtext_ostream_backend> sink_t;
boost::shared_ptr<sink_t> sink (new sink_t (backend));
// The log output formatter
sink->set_formatter (expr::format (L"[%1%][%2%] %3%")
% expr::attr<ptime::ptime> ("TimeStamp")
% logging::trivial::severity
% expr::message
);
// Filter by severity and by DATALOG channel
sink->set_filter (logging::trivial::severity >= logging::trivial::info &&
expr::attr<std::string> ("Channel") == "DATALOG");
// Add it to the core
logging::core::get ()->add_sink (sink);
}
}
|