12#include <boost/core/null_deleter.hpp>
13#include <boost/log/attributes/mutable_constant.hpp>
14#include <boost/log/core.hpp>
15#include <boost/log/expressions.hpp>
16#include <boost/log/sinks/sink.hpp>
17#include <boost/log/sinks/sync_frontend.hpp>
18#include <boost/log/sinks/text_ostream_backend.hpp>
19#include <boost/log/support/date_time.hpp>
20#include <boost/log/trivial.hpp>
21#include <boost/log/utility/setup/filter_parser.hpp>
22#include <boost/log/utility/setup/formatter_parser.hpp>
23#include <boost/program_options.hpp>
30 formatter_type
create_formatter(boost::log::attribute_name
const &name, args_map
const &args)
override
32 namespace expr = boost::log::expressions;
33 args_map::const_iterator it = args.find(
"format");
35 return expr::stream << expr::format_date_time<boost::posix_time::ptime>(expr::attr<boost::posix_time::ptime>(name), it->second);
37 return expr::stream << expr::attr<boost::posix_time::ptime>(name);
44 formatter_type
create_formatter(boost::log::attribute_name
const &name, args_map
const &args)
override
46 namespace expr = boost::log::expressions;
47 auto severity = expr::attr<boost::log::trivial::severity_level>(
"Severity");
50 << expr::if_(severity == boost::log::trivial::severity_level::error)
51 [expr::stream <<
"\033[31m"
53 << expr::if_(severity == boost::log::trivial::severity_level::warning)
54 [expr::stream <<
"\033[36m"
63 formatter_type
create_formatter(boost::log::attribute_name
const &name, args_map
const &args)
override
65 namespace expr = boost::log::expressions;
66 auto severity = expr::attr<boost::log::trivial::severity_level>(
"Severity");
69 << expr::if_(severity == boost::log::trivial::severity_level::error)
72 << expr::if_(severity == boost::log::trivial::severity_level::warning)
79class NullSink final :
public boost::log::sinks::sink {
82 :
boost::log::sinks::sink(false) {}
84 bool will_consume(boost::log::attribute_value_set
const &)
override
89 void consume(boost::log::record_view
const &)
override {}
118 void consume(boost::log::record_view
const &rec, string_type
const &formatted_record)
120 *
_ostream << formatted_record <<
'\n'
132 namespace po = boost::program_options;
133 po::options_description desc;
138 po::parsed_options parsed = parse_config_file(ifs, desc,
true);
139 for (
auto const &opt : parsed.options) {
144 configs[section].setOption(key, opt.value[0]);
146 std::cerr <<
"WARNING: section [" << section <<
"] in configuration file \"" << filename <<
"\" contains invalid key \"" << key <<
"\"\n";
149 }
catch (po::error &e) {
150 std::cout <<
"ERROR reading logging configuration: " << e.what() <<
"\n\n";
156 for (
auto const &c : configs)
157 if (c.second.enabled)
171 namespace expr = boost::log::expressions;
172 namespace trivial = boost::log::trivial;
173 auto severity = expr::attr<trivial::severity_level>(
"Severity");
176 << expr::attr<int>(
"Rank")
178 << expr::format_date_time<boost::posix_time::ptime>(
"TimeStamp",
"%H:%M:%S")
180 << expr::attr<std::string>(
"Module")
182 << expr::attr<int>(
"Line")
184 << expr::attr<std::string>(
"Function")
186 << expr::if_(severity == trivial::error)[expr::stream <<
"\033[31mERROR: "]
187 << expr::if_(severity == trivial::warning)[expr::stream <<
"\033[36mWARNING: ]"]
194 namespace expr = boost::log::expressions;
195 namespace trivial = boost::log::trivial;
196 auto severity = trivial::severity;
197 auto rank = expr::attr<int>(
"Rank");
198 return expr::has_attr(
"preCICE") && expr::attr<bool>(
"preCICE") && (severity > trivial::debug) && !((severity == trivial::info) && (rank != 0));
203 boost::algorithm::to_lower(key);
205 boost::algorithm::to_lower(value);
218 boost::algorithm::to_lower(key);
219 return key ==
"output" || key ==
"filter" || key ==
"format" || key ==
"type";
232 namespace bl = boost::log;
233 bl::register_formatter_factory(
"TimeStamp", boost::make_shared<timestamp_formatter_factory>());
234 bl::register_formatter_factory(
"ColorizedSeverity", boost::make_shared<colorized_severity_formatter_factory>());
235 bl::register_formatter_factory(
"Severity", boost::make_shared<severity_formatter_factory>());
236 bl::register_simple_filter_factory<bl::trivial::severity_level, char>(
"Severity");
240 bl::expressions::stream
241 <<
"(" << bl::expressions::attr<int>(
"Rank") <<
") "
242 << bl::expressions::format_date_time<boost::posix_time::ptime>(
"TimeStamp",
"%H:%M:%S") <<
" "
243 << bl::expressions::attr<std::string>(
"File") <<
":"
244 << bl::expressions::attr<int>(
"Line")
245 <<
" [" << bl::expressions::attr<std::string>(
"Module") <<
"] in "
246 << bl::expressions::attr<std::string>(
"Function") <<
": "
247 << bl::expressions::message;
250 using sink_ptr =
typename boost::shared_ptr<boost::log::sinks::sink>;
253 for (
auto &sink : activeSinks) {
254 boost::log::core::get()->remove_sink(sink);
265 !enabled && noconfigs) {
266 auto sink = boost::make_shared<NullSink>();
267 boost::log::core::get()->add_sink(sink);
273 if (configs.
empty()) {
278 for (
const auto &
config : configs) {
284 boost::shared_ptr<StreamBackend> backend;
285 if (
config.type ==
"file")
286 backend = boost::make_shared<StreamBackend>(boost::shared_ptr<std::ostream>(
new std::ofstream(
config.output)));
287 if (
config.type ==
"stream") {
288 if (
config.output ==
"stdout")
289 backend = boost::make_shared<StreamBackend>(boost::shared_ptr<std::ostream>(&
std::cout, boost::null_deleter()));
290 if (
config.output ==
"stderr")
291 backend = boost::make_shared<StreamBackend>(boost::shared_ptr<std::ostream>(&
std::cerr, boost::null_deleter()));
293 PRECICE_ASSERT(backend !=
nullptr,
"The logging backend was not initialized properly. Check your log config.");
294 backend->auto_flush(
true);
297 auto sink = boost::make_shared<boost::log::sinks::synchronous_sink<StreamBackend>>(backend);
303 sink->set_formatter(boost::log::parse_formatter(
config.format));
307 if (
config.filter.empty()) {
308 sink->set_filter(boost::log::expressions::attr<bool>(
"preCICE") ==
true);
313 sink->set_filter(boost::log::parse_filter(
"%preCICE% & ( " +
config.filter +
" )"));
316 boost::log::core::get()->add_sink(sink);
#define PRECICE_ASSERT(...)
void consume(boost::log::record_view const &) override
bool is_cross_thread() const noexcept
bool will_consume(boost::log::attribute_value_set const &) override
bool try_consume(boost::log::record_view const &) override
boost::shared_ptr< std::ostream > _ostream
StreamBackend(boost::shared_ptr< std::ostream > ostream)
void consume(boost::log::record_view const &rec, string_type const &formatted_record)
T emplace_back(T... args)
contains the logging framework.
void setupLogging(LoggingConfiguration configs, bool enabled)
Configures the logging from a LoggingConfiguration.
void setMPIRank(int const rank)
void setParticipant(std::string const &participant)
static boost::log::filter createDefaultFilter()
LoggingConfiguration readLogConfFile(std::string const &filename)
Reads a log file, returns a logging configuration.
std::vector< BackendConfiguration > LoggingConfiguration
Holds the configuration of the logging system.
GlobalLoggingConfig & getGlobalLoggingConfig()
Returns the global logging configuration.
static boost::log::formatter createDefaultFormatter()
void setEnabled(bool enabled)
Sets weather the sink is enabled or disabled.
static const std::string default_filter
void setOption(std::string key, std::string value)
Sets on option, overwrites default values.
static const std::string default_type
static const std::string default_output
static bool isValidOption(std::string key)
Checks if an option is usable.
static const std::string default_formatter
Holds global logging data in a central place.