128 if (!std::filesystem::exists(filename)) {
132 namespace po = boost::program_options;
133 po::options_description desc;
134 std::ifstream ifs(filename);
136 std::map<std::string, BackendConfiguration> configs;
138 po::parsed_options parsed = parse_config_file(ifs, desc,
true);
139 for (
auto const &opt : parsed.options) {
140 std::string section = opt.string_key.substr(0, opt.string_key.find(
'.'));
141 std::string key = opt.string_key.substr(opt.string_key.find(
'.') + 1);
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)
158 retVal.push_back(c.second);
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: ]"]
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>;
252 static std::vector<sink_ptr> activeSinks;
253 for (
auto &sink : activeSinks) {
254 boost::log::core::get()->remove_sink(sink);
264 if (
auto noconfigs = std::none_of(configs.begin(), configs.end(), [](
const auto &
config) { return config.enabled; });
265 !enabled && noconfigs) {
266 auto sink = boost::make_shared<NullSink>();
267 boost::log::core::get()->add_sink(sink);
268 activeSinks.emplace_back(std::move(sink));
273 if (configs.empty()) {
274 configs.emplace_back();
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);
317 activeSinks.emplace_back(std::move(sink));