Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
log.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file ored/data/log.cpp
20 \brief Classes and functions for log message handling.
21 \ingroup
22*/
23
24#include <boost/core/null_deleter.hpp>
25#include <boost/date_time/posix_time/posix_time.hpp>
26#include <boost/filesystem.hpp>
27#include <boost/log/expressions.hpp>
28#include <boost/log/expressions/formatters/date_time.hpp>
29#include <boost/log/utility/setup/file.hpp>
30#include <boost/log/utility/setup/common_attributes.hpp>
31#include <boost/log/support/date_time.hpp>
32#include <boost/log/sources/severity_feature.hpp>
33#include <boost/phoenix/bind/bind_function.hpp>
34#include <iomanip>
37#include <ql/errors.hpp>
38
39using namespace boost::filesystem;
40using namespace boost::posix_time;
41using namespace std;
42
43namespace logging = boost::log;
44namespace lexpr = boost::log::expressions;
45namespace lsinks = boost::log::sinks;
46namespace lsrc = boost::log::sources;
47namespace lkeywords = boost::log::keywords;
48namespace lattr = boost::log::attributes;
49
51BOOST_LOG_ATTRIBUTE_KEYWORD(fileSource, "FileSource", std::string);
52BOOST_LOG_ATTRIBUTE_KEYWORD(messageType, "MessageType", std::string);
53
54namespace ore {
55namespace data {
56
57using namespace QuantLib;
58
59const string StderrLogger::name = "StderrLogger";
60const string BufferLogger::name = "BufferLogger";
61const string FileLogger::name = "FileLogger";
62const string StructuredLogger::name = "StructuredLogger";
63const string ProgressLogger::name = "ProgressLogger";
64const string EventLogger::name = "EventLogger";
65
66// -- Buffer Logger
67
68void BufferLogger::log(unsigned level, const string& s) {
69 if (level <= minLevel_)
70 buffer_.push(s);
71}
72
73bool BufferLogger::hasNext() { return !buffer_.empty(); }
74
76 QL_REQUIRE(!buffer_.empty(), "Log Buffer is empty");
77 string s = buffer_.front();
78 buffer_.pop();
79 return s;
80}
81
82// -- File Logger
83
84FileLogger::FileLogger(const string& filename) : Logger(name), filename_(filename) {
85 fout_.open(filename.c_str(), ios_base::out);
86 QL_REQUIRE(fout_.is_open(), "Error opening file " << filename);
87 fout_.setf(ios::fixed, ios::floatfield);
88 fout_.setf(ios::showpoint);
89}
90
92 if (fout_.is_open())
93 fout_.close();
94}
95
96void FileLogger::log(unsigned, const string& msg) {
97 if (fout_.is_open())
98 fout_ << msg << endl;
99}
100
102
104 // Create backend and initialize it with a stream
105 QuantLib::ext::shared_ptr<lsinks::text_ostream_backend> backend = QuantLib::ext::make_shared<lsinks::text_ostream_backend>();
106
107 // Wrap it into the frontend and register in the core
108 QuantLib::ext::shared_ptr<text_sink> sink(new text_sink(backend));
109
110 // This logger should only receive/process logs that were emitted by a ProgressMessage
111 sink->set_filter(messageType == ProgressMessage::name);
112
113 // Use formatter to intercept and store the message.
114 auto formatter = [this](const logging::record_view& rec, logging::formatting_ostream& strm) {
115 this->messages().push_back(rec[lexpr::smessage]->c_str());
116
117 // If a file sink exists, then send the log record to it.
118 if (this->fileSink()) {
119 // Send to progress log file
120 lsrc::severity_logger_mt<oreSeverity> lg;
121 lg.add_attribute(messageType.get_name(), lattr::constant<string>(name));
122 BOOST_LOG_SEV(lg, oreSeverity::notice) << rec[lexpr::smessage];
123 }
124
125 // Also send to full log file
126 LOG(ProgressMessage::name << " " << rec[lexpr::smessage]);
127 };
128 sink->set_formatter(formatter);
129 logging::core::get()->add_sink(sink);
130 cacheSink_ = sink;
131}
132
134 if (fileSink_) {
135 logging::core::get()->remove_sink(fileSink_);
136 fileSink_ = nullptr;
137 }
138 if (coutSink_) {
139 logging::core::get()->remove_sink(coutSink_);
140 coutSink_ = nullptr;
141 }
142}
143
144void ProgressLogger::setFileLog(const string& filepath, const path& dir, Size rotationSize) {
145 if (rotationSize == 0) {
146 fileSink_ = logging::add_file_log(
147 lkeywords::target = dir,
148 lkeywords::file_name = filepath,
149 lkeywords::filter = messageType == ProgressLogger::name,
150 lkeywords::auto_flush = true
151 );
152 } else {
153 fileSink_ = logging::add_file_log(
154 lkeywords::target = dir,
155 lkeywords::file_name = filepath,
156 lkeywords::filter = messageType == ProgressLogger::name,
157 lkeywords::scan_method = lsinks::file::scan_matching,
158 lkeywords::rotation_size = rotationSize,
159 lkeywords::auto_flush = true
160 );
161 }
162}
163
164void ProgressLogger::setCoutLog(const bool flag) {
165 if (flag) {
166 if (!coutSink_) {
167 // Create backend and initialize it with a stream
168 QuantLib::ext::shared_ptr<lsinks::text_ostream_backend> backend = QuantLib::ext::make_shared<lsinks::text_ostream_backend>();
169 backend->add_stream(QuantLib::ext::shared_ptr<std::ostream>(&std::clog, boost::null_deleter()));
170
171 // Wrap it into the frontend and register in the core
172 QuantLib::ext::shared_ptr<text_sink> sink(new text_sink(backend));
173 sink->set_filter(messageType == ProgressMessage::name);
174 logging::core::get()->add_sink(sink);
175
176 // Store the sink for removal/retrieval later
177 coutSink_ = sink;
178 }
179 } else if (coutSink_) {
180 logging::core::get()->remove_sink(coutSink_);
181 coutSink_ = nullptr;
182 }
183}
184
186 // Create backend and initialize it with a stream
187 QuantLib::ext::shared_ptr<lsinks::text_ostream_backend> backend = QuantLib::ext::make_shared<lsinks::text_ostream_backend>();
188
189 // Wrap it into the frontend and register in the core
190 QuantLib::ext::shared_ptr<text_sink> sink(new text_sink(backend));
191 sink->set_filter(messageType == StructuredMessage::name);
192
193 // Use formatter to intercept and store the message.
194 auto formatter = [this](const logging::record_view& rec, logging::formatting_ostream& strm) {
195 const string& msg = rec[lexpr::smessage]->c_str();
196
197 // Emit log record if it has not been logged before
198 if (this->messages().empty() ||
199 std::find(this->messages().begin(), this->messages().end(), msg) == this->messages().end()) {
200 // Store the message
201 this->messages().push_back(msg);
202
203 oreSeverity logSeverity = boost::log::extract<oreSeverity>(severity.get_name(), rec).get();
204 // If a file sink has been defined, then send the log record to it.
205 if (this->fileSink()) {
206 // Send to structured log file
207 lsrc::severity_logger_mt<oreSeverity> lg;
208 lg.add_attribute(messageType.get_name(), lattr::constant<string>(name));
209 BOOST_LOG_SEV(lg, logSeverity) << rec[lexpr::smessage];
210 }
211
212 // Also send to full log file
213 MLOG(logSeverity, StructuredMessage::name << " " << rec[lexpr::smessage]);
214 }
215 };
216 sink->set_formatter(formatter);
217 logging::core::get()->add_sink(sink);
218 cacheSink_ = sink;
219}
220
222 if (fileSink_) {
223 logging::core::get()->remove_sink(fileSink_);
224 fileSink_ = nullptr;
225 }
226}
227
228void StructuredLogger::setFileLog(const string& filepath, const path& dir, Size rotationSize) {
229 if (rotationSize == 0) {
230 fileSink_ = logging::add_file_log(
231 lkeywords::target = dir,
232 lkeywords::file_name = filepath,
233 lkeywords::filter = messageType == StructuredLogger::name,
234 lkeywords::auto_flush = true
235 );
236 } else {
237 fileSink_ = logging::add_file_log(
238 lkeywords::target = dir,
239 lkeywords::file_name = filepath,
240 lkeywords::filter = messageType == StructuredLogger::name,
241 lkeywords::scan_method = lsinks::file::scan_matching,
242 lkeywords::rotation_size = rotationSize,
243 lkeywords::auto_flush = true
244 );
245 }
246}
247
249 if (fileSink_) {
250 logging::core::get()->remove_sink(fileSink_);
251 fileSink_ = nullptr;
252 }
253}
254
255void EventLogger::setFileLog(const std::string& filepath) {
256 fileSink_ = logging::add_file_log(
257 lkeywords::file_name = filepath + "%Y-%m-%d" + ".json",
258 lkeywords::time_based_rotation = lsinks::file::rotation_at_time_point(0, 0, 0), /*< at midnight >*/
259 lkeywords::filter = messageType == EventMessage::name,
260 lkeywords::scan_method = lsinks::file::scan_matching,
261 lkeywords::auto_flush = true
262 );
263}
264
266 const std::function<void(const boost::log::record_view&, boost::log::formatting_ostream&)>& formatter) {
267 if (fileSink_)
268 fileSink_->set_formatter(formatter);
269}
270
271// The Log itself
272Log::Log() : loggers_(), enabled_(false), mask_(255), ls_() {
273
274 ls_.setf(ios::fixed, ios::floatfield);
275 ls_.setf(ios::showpoint);
276}
277
278void Log::registerLogger(const QuantLib::ext::shared_ptr<Logger>& logger) {
279 boost::unique_lock<boost::shared_mutex> lock(mutex_);
280 QL_REQUIRE(loggers_.find(logger->name()) == loggers_.end(),
281 "Logger with name " << logger->name() << " already registered");
282 loggers_[logger->name()] = logger;
283}
284
285void Log::registerIndependentLogger(const QuantLib::ext::shared_ptr<IndependentLogger>& logger) {
286 boost::unique_lock<boost::shared_mutex> lock(mutex_);
287 QL_REQUIRE(independentLoggers_.find(logger->name()) == independentLoggers_.end(),
288 "Logger with name " << logger->name() << " already registered as independent logger");
290}
291
293 boost::unique_lock<boost::shared_mutex> lock(mutex_);
294 for (auto& [_, l] : independentLoggers_)
295 l->clear();
296}
297
298const bool Log::hasLogger(const string& name) const {
299 boost::shared_lock<boost::shared_mutex> lock(mutex_);
300 return loggers_.find(name) != loggers_.end();
301}
302
303QuantLib::ext::shared_ptr<Logger>& Log::logger(const string& name) {
304 boost::shared_lock<boost::shared_mutex> lock(mutex_);
305 QL_REQUIRE(hasLogger(name), "No logger found with name " << name);
306 return loggers_[name];
307}
308
309const bool Log::hasIndependentLogger(const string& name) const {
310 boost::shared_lock<boost::shared_mutex> lock(mutex_);
311 return independentLoggers_.find(name) != independentLoggers_.end();
312}
313
314QuantLib::ext::shared_ptr<IndependentLogger>& Log::independentLogger(const string& name) {
315 boost::shared_lock<boost::shared_mutex> lock(mutex_);
316 QL_REQUIRE(hasIndependentLogger(name), "No independent logger found with name " << name);
318}
319
320void Log::removeLogger(const string& name) {
321 boost::unique_lock<boost::shared_mutex> lock(mutex_);
322 map<string, QuantLib::ext::shared_ptr<Logger>>::iterator it = loggers_.find(name);
323 if (it != loggers_.end()) {
324 loggers_.erase(it);
325 } else {
326 QL_FAIL("No logger found with name " << name);
327 }
328}
329
331 boost::unique_lock<boost::shared_mutex> lock(mutex_);
332 map<string, QuantLib::ext::shared_ptr<IndependentLogger>>::iterator it = independentLoggers_.find(name);
333 if (it != independentLoggers_.end()) {
334 it->second->removeSinks();
335 independentLoggers_.erase(it);
336 } else {
337 QL_FAIL("No independdent logger found with name " << name);
338 }
339}
340
342 boost::unique_lock<boost::shared_mutex> lock(mutex_);
343 loggers_.clear();
344 logging::core::get()->remove_all_sinks();
345 independentLoggers_.clear();
346}
347
348string Log::source(const char* filename, int lineNo) const {
349 string filepath;
350 if (rootPath_.empty()) {
351 filepath = filename;
352 } else {
353 filepath = relative(path(filename), rootPath_).string();
354 }
355 int lineNoLen = (int)log10((double)lineNo) + 1; // Length of the int as a string
356 int len = 2 + filepath.length() + 1 + lineNoLen + 1; // " (" + file + ':' + line + ')'
357
358 if (maxLen_ == 0) {
359 return "(" + filepath + ':' + to_string(lineNo) + ')';
360 } else {
361 if (len <= maxLen_) {
362 // pad out spaces
363 return string(maxLen_ - len, ' ') + "(" + filepath + ':' + to_string(lineNo) + ')';
364 } else {
365 // need to trim the filename to fit into maxLen chars
366 // need to remove (len - maxLen_) chars + 3 for the "..."
367 return "(..." + filepath.substr(3 + len - maxLen_) + ':' + to_string(lineNo) + ')';
368 }
369 }
370}
371
372void Log::addExcludeFilter(const string& key, const std::function<bool(const std::string&)> func) {
373 boost::unique_lock<boost::shared_mutex> lock(mutex_);
374 excludeFilters_[key] = func;
375}
376
377void Log::removeExcludeFilter(const string& key) {
378 boost::unique_lock<boost::shared_mutex> lock(mutex_);
379 excludeFilters_.erase(key);
380}
381
382bool Log::checkExcludeFilters(const std::string& msg) {
383 boost::shared_lock<boost::shared_mutex> lock(mutex_);
384 for (const auto& f : excludeFilters_) {
385 if (f.second(msg))
386 return true;
387 }
388 return false;
389}
390
391void Log::header(unsigned m, const char* filename, int lineNo) {
392 // 1. Reset stringstream
393 ls_.str(string());
394 ls_.clear();
395
396 // Write the header to the stream
397 // TYPE [Time Stamp] (file:line)
398 switch (m) {
399 case ORE_ALERT:
400 ls_ << "ALERT ";
401 break;
402 case ORE_CRITICAL:
403 ls_ << "CRITICAL ";
404 break;
405 case ORE_ERROR:
406 ls_ << "ERROR ";
407 break;
408 case ORE_WARNING:
409 ls_ << "WARNING ";
410 break;
411 case ORE_NOTICE:
412 ls_ << "NOTICE ";
413 break;
414 case ORE_DEBUG:
415 ls_ << "DEBUG ";
416 break;
417 case ORE_DATA:
418 ls_ << "DATA ";
419 break;
420 case ORE_MEMORY:
421 ls_ << "MEMORY ";
422 break;
423 }
424
425 // Timestamp
426 // Use boost::posix_time microsecond clock to get better precision (when available).
427 // format is "2014-Apr-04 11:10:16.179347"
428 ls_ << '[' << to_simple_string(microsec_clock::local_time()) << ']';
429
430 // Filename & line no
431 // format is " (file:line)"
432 ls_ << " " << source(filename, lineNo) << " : ";
433
434 // log pid if given
435 if (pid_ > 0)
436 ls_ << " [" << pid_ << "] ";
437
438 // update statistics
439 if (lastLineNo_ == lineNo && lastFileName_ == filename) {
441 } else {
442 lastFileName_ = filename;
443 lastLineNo_ = lineNo;
446 }
447}
448
449void Log::log(unsigned m) {
450 string msg = ls_.str();
451 map<string, QuantLib::ext::shared_ptr<Logger>>::iterator it;
453 for (auto& l : loggers_) {
454 l.second->log(m, msg);
455 }
456 } else if (writeSuppressedMessagesHint_) {
457 std::string suffix;
458 if (msg.find(StructuredMessage::name) == string::npos) {
459 suffix = " ... suppressing more messages from same source code location (cutoff = " +
460 std::to_string(sameSourceLocationCutoff_) + " lines)";
461 }
462 for (auto& l : loggers_) {
463 l.second->log(m, msg + suffix);
464 }
466 }
467}
468
469// --------
470
471LoggerStream::LoggerStream(unsigned mask, const char* filename, unsigned lineNo)
472 : mask_(mask), filename_(filename), lineNo_(lineNo), ss_() {
473 QL_REQUIRE(mask == ORE_ALERT || mask == ORE_CRITICAL || mask == ORE_ERROR || mask == ORE_WARNING ||
474 mask == ORE_NOTICE || mask == ORE_DEBUG || mask == ORE_DATA,
475 "Invalid log mask " << mask);
476}
477
479 string text;
480 while (getline(ss_, text)) {
481 // we expand the MLOG macro here so we can overwrite __FILE__ and __LINE__
482 if (ore::data::Log::instance().enabled() && ore::data::Log::instance().filter(mask_)) {
483 boost::unique_lock<boost::shared_mutex> lock(ore::data::Log::instance().mutex());
484 ore::data::Log::instance().header(mask_, filename_, lineNo_);
485 ore::data::Log::instance().logStream() << text;
486 ore::data::Log::instance().log(mask_);
487 }
488 }
489}
490
491void JSONMessage::log() const {
492 if (!ore::data::Log::instance().checkExcludeFilters(msg()))
493 emitLog();
494}
495
496string JSONMessage::jsonify(const boost::any& obj) {
497 if (obj.type() == typeid(map<string, boost::any>)) {
498 string jsonStr = "{ ";
499 Size i = 0;
500 for (const auto& kv : boost::any_cast<map<string, boost::any>>(obj)) {
501 if (i > 0)
502 jsonStr += ", ";
503 jsonStr += '\"' + kv.first + "\": " + jsonify(kv.second);
504 i++;
505 }
506 jsonStr += " }";
507 return jsonStr;
508 } else if (obj.type() == typeid(vector<boost::any>)) {
509 string arrayStr = "[ ";
510 Size i = 0;
511 for (const auto& v : boost::any_cast<vector<boost::any>>(obj)) {
512 if (i > 0)
513 arrayStr += ", ";
514 arrayStr += jsonify(v);
515 i++;
516 }
517 arrayStr += " ]";
518 return arrayStr;
519 } else if (obj.type() == typeid(string)) {
520 string str = boost::any_cast<string>(obj);
521 boost::replace_all(str, "\\", "\\\\"); // do this before the below otherwise we get \\"
522 boost::replace_all(str, "\"", "\\\"");
523 boost::replace_all(str, "\r", "\\r");
524 boost::replace_all(str, "\n", "\\n");
525 return '\"' + str + '\"';
526 } else if (obj.type() == typeid(StructuredMessage::Category)) {
527 return to_string(boost::any_cast<StructuredMessage::Category>(obj));
528 } else if (obj.type() == typeid(StructuredMessage::Group)) {
529 return to_string(boost::any_cast<StructuredMessage::Group>(obj));
530 } else if (obj.type() == typeid(int)) {
531 return to_string(boost::any_cast<int>(obj));
532 } else if (obj.type() == typeid(bool)) {
533 return to_string(boost::any_cast<bool>(obj));
534 } else if (obj.type() == typeid(QuantLib::Size)) {
535 return to_string(boost::any_cast<QuantLib::Size>(obj));
536 } else if (obj.type() == typeid(QuantLib::Real)) {
537 return to_string(boost::any_cast<QuantLib::Real>(obj));
538 } else if (obj.type() == typeid(unsigned int)) {
539 return to_string(boost::any_cast<unsigned int>(obj));
540 } else if (obj.type() == typeid(unsigned short)) {
541 return to_string(boost::any_cast<unsigned short>(obj));
542 } else if (obj.type() == typeid(float)) {
543 return to_string(boost::any_cast<float>(obj));
544 } else {
545 try {
546 // It is possible that this line is the one causing the unknown value error.
547 StructuredLoggingErrorMessage("JSON Message Logging", "JSONMessage::jsonify() : Unrecognised value type")
548 .log();
549 } catch (...) {
550 }
551 return string();
552 }
553}
554
555StructuredMessage::StructuredMessage(const Category& category, const Group& group, const string& message,
556 const map<string, string>& subFields) {
557 data_["category"] = to_string(category);
558 data_["group"] = to_string(group);
559 data_["message"] = message;
560
561 if (!subFields.empty()) {
562 vector<boost::any> subFieldsVector;
563 bool addedSubField = false;
564 for (const auto& sf : subFields) {
565 if (!sf.second.empty()) {
566 map<string, boost::any> subField({{"name", sf.first}, {"value", sf.second}});
567 subFieldsVector.push_back(subField);
568 addedSubField = true;
569 }
570 }
571 if (addedSubField)
572 data_["sub_fields"] = subFieldsVector;
573 }
574}
575
577 lsrc::severity_logger_mt<oreSeverity> lg;
578 lg.add_attribute(messageType.get_name(), lattr::constant<string>(name));
579
580 auto it = data_.find("category");
581 QL_REQUIRE(it != data_.end(), "StructuredMessage must have a 'category' key specified.");
582 QL_REQUIRE(it->second.type() == typeid(string), "StructuredMessage category must be a string.");
583
584 string category = boost::any_cast<string>(it->second);
586 BOOST_LOG_SEV(lg, oreSeverity::warning) << json();
587 } else if (category == to_string(StructuredMessage::Category::Error)) {
588 BOOST_LOG_SEV(lg, oreSeverity::alert) << json();
589 } else {
590 QL_FAIL("StructuredMessage::log() invalid category '" << category << "'");
591 }
592}
593
594void StructuredMessage::addSubFields(const map<string, string>& subFields) {
595 if (!subFields.empty()) {
596
597 // First check that there is at least one non-empty subfield
598 bool hasNonEmptySubField = false;
599 for (const auto& sf : subFields) {
600 if (!sf.second.empty()) {
601 hasNonEmptySubField = true;
602 break;
603 }
604 }
605 if (!hasNonEmptySubField)
606 return;
607
608 if (data_.find("sub_fields") == data_.end()) {
609 data_["sub_fields"] = vector<boost::any>();
610 }
611
612 for (const auto& sf : subFields) {
613 if (!sf.second.empty()) {
614 map<string, boost::any> subField({{"name", sf.first}, {"value", sf.second}});
615 boost::any_cast<vector<boost::any>&>(data_.at("sub_fields")).push_back(subField);
616 }
617 }
618
619 }
620}
621
623 lsrc::severity_logger_mt<oreSeverity> lg;
624 lg.add_attribute(messageType.get_name(), lattr::constant<string>(name));
625 BOOST_LOG_SEV(lg, oreSeverity::alert) << json();
626 MLOG(oreSeverity::alert, msg());
627}
628
629ProgressMessage::ProgressMessage(const string& key, const Size progressCurrent, const Size progressTotal, const string& detail) {
630 data_["key"] = key;
631 if (!detail.empty())
632 data_["detail"] = detail;
633 data_["progress"] = progressCurrent;
634 data_["total"] = progressTotal;
635 data_["@timestamp"] =
636 boost::posix_time::to_iso_extended_string(boost::posix_time::microsec_clock::universal_time());
637}
638
640 lsrc::severity_logger_mt<oreSeverity> lg;
641 lg.add_attribute(messageType.get_name(), lattr::constant<string>(name));
642 BOOST_LOG_SEV(lg, oreSeverity::notice) << json();
643}
644
645std::ostream& operator<<(std::ostream& out, const StructuredMessage::Category& category) {
647 out << "Error";
648 else if (category == StructuredMessage::Category::Warning)
649 out << "Warning";
650 else if (category == StructuredMessage::Category::Unknown)
651 out << "UnknownType";
652 else
653 QL_FAIL("operator<<: Unsupported enum value for StructuredMessage::Category");
654
655 return out;
656}
657
658std::ostream& operator<<(std::ostream& out, const StructuredMessage::Group& group) {
660 out << "Analytics";
662 out << "Configuration";
663 else if (group == StructuredMessage::Group::Model)
664 out << "Model";
665 else if (group == StructuredMessage::Group::Curve)
666 out << "Curve";
667 else if (group == StructuredMessage::Group::Trade)
668 out << "Trade";
669 else if (group == StructuredMessage::Group::Fixing)
670 out << "Fixing";
671 else if (group == StructuredMessage::Group::Logging)
672 out << "Logging";
674 out << "Reference Data";
675 else if (group == StructuredMessage::Group::Unknown)
676 out << "UnknownType";
677 else
678 QL_FAIL("operator<<: Unsupported enum value for StructuredMessage::Group");
679
680 return out;
681}
682
683} // namespace data
684} // namespace ore
static const std::string name
the name "BufferLogger"
Definition: log.hpp:231
std::queue< std::string > buffer_
Definition: log.hpp:253
virtual void log(unsigned, const std::string &) override
The log callback.
Definition: log.cpp:68
bool hasNext()
Checks if Logger has new messages.
Definition: log.cpp:73
unsigned minLevel_
Definition: log.hpp:254
std::string next()
Retrieve new messages.
Definition: log.cpp:75
static const std::string name
the name "EventLogger"
Definition: log.hpp:339
virtual void removeSinks() override
Destructor.
Definition: log.cpp:248
QuantLib::ext::shared_ptr< file_sink > fileSink_
Definition: log.hpp:352
void setFileLog(const std::string &filepath)
Definition: log.cpp:255
void setFormatter(const std::function< void(const boost::log::record_view &, boost::log::formatting_ostream &)> &)
Definition: log.cpp:265
void emitLog() const
generate Boost log record to pass to corresponding sinks
Definition: log.cpp:622
std::string msg() const
return a std::string for the log file
Definition: log.hpp:724
static constexpr const char * name
Definition: log.hpp:721
virtual ~FileLogger()
Destructor.
Definition: log.cpp:91
static const std::string name
the name "FileLogger"
Definition: log.hpp:196
std::fstream fout_
Definition: log.hpp:211
virtual void log(unsigned, const std::string &) override
The log callback.
Definition: log.cpp:96
FileLogger(const std::string &filename)
Constructor.
Definition: log.cpp:84
Base Log handler class that utilises Boost logging to create log sinks.
Definition: log.hpp:264
std::vector< std::string > & messages()
Definition: log.hpp:269
std::vector< std::string > messages_
Definition: log.hpp:282
const std::string json() const
create JSON-like output from the data
Definition: log.hpp:643
static std::string jsonify(const boost::any &)
Definition: log.cpp:496
virtual std::string msg() const =0
return a std::string for the log file
std::map< std::string, boost::any > data_
Definition: log.hpp:651
void log() const
generate Boost log record to pass to corresponding sinks
Definition: log.cpp:491
virtual void emitLog() const =0
generate Boost log record - this method is called by log()
std::ostringstream ls_
Definition: log.hpp:510
void removeLogger(const std::string &name)
Remove a Logger.
Definition: log.cpp:320
std::map< std::string, QuantLib::ext::shared_ptr< Logger > > loggers_
Definition: log.hpp:505
int lastLineNo_
Definition: log.hpp:517
int maxLen_
Definition: log.hpp:512
QuantLib::ext::shared_ptr< Logger > & logger(const std::string &name)
Retrieve a Logger.
Definition: log.cpp:303
std::map< std::string, std::function< bool(const std::string &)> > excludeFilters_
Definition: log.hpp:523
const bool hasIndependentLogger(const std::string &name) const
Definition: log.cpp:309
std::size_t sameSourceLocationCutoff_
Definition: log.hpp:515
std::size_t sameSourceLocationSince_
Definition: log.hpp:513
boost::filesystem::path rootPath_
Definition: log.hpp:509
const bool hasLogger(const std::string &name) const
Check if logger exists.
Definition: log.cpp:298
void header(unsigned m, const char *filename, int lineNo)
macro utility function - do not use directly, not thread safe
Definition: log.cpp:391
std::string source(const char *filename, int lineNo) const
Definition: log.cpp:348
void removeIndependentLogger(const std::string &name)
Definition: log.cpp:330
void registerIndependentLogger(const QuantLib::ext::shared_ptr< IndependentLogger > &logger)
Definition: log.cpp:285
boost::shared_mutex mutex_
Definition: log.hpp:521
std::map< std::string, QuantLib::ext::shared_ptr< IndependentLogger > > independentLoggers_
Definition: log.hpp:506
void removeAllLoggers()
Remove all loggers.
Definition: log.cpp:341
bool checkExcludeFilters(const std::string &)
Definition: log.cpp:382
QuantLib::ext::shared_ptr< IndependentLogger > & independentLogger(const std::string &name)
Definition: log.cpp:314
void addExcludeFilter(const std::string &, const std::function< bool(const std::string &)>)
Definition: log.cpp:372
std::string lastFileName_
Definition: log.hpp:516
void removeExcludeFilter(const std::string &)
Definition: log.cpp:377
void registerLogger(const QuantLib::ext::shared_ptr< Logger > &logger)
Add a new Logger.
Definition: log.cpp:278
void clearAllIndependentLoggers()
Definition: log.cpp:292
bool writeSuppressedMessagesHint_
Definition: log.hpp:514
void log(unsigned m)
macro utility function - do not use directly, not thread safe
Definition: log.cpp:449
The Base Custom Log Handler class.
Definition: log.hpp:130
std::stringstream ss_
Definition: log.hpp:619
LoggerStream(unsigned mask, const char *filename, unsigned lineNo)
Definition: log.cpp:471
~LoggerStream()
destructor - this is when the logging takes place.
Definition: log.cpp:478
const char * filename_
Definition: log.hpp:617
static const std::string name
the name "ProgressLogger"
Definition: log.hpp:294
virtual void removeSinks() override
Destructor.
Definition: log.cpp:133
ProgressLogger()
Constructors.
Definition: log.cpp:103
QuantLib::ext::shared_ptr< text_sink > coutSink_
Definition: log.hpp:308
QuantLib::ext::shared_ptr< file_sink > fileSink_
Definition: log.hpp:307
const QuantLib::ext::shared_ptr< file_sink > & fileSink()
Definition: log.hpp:298
void setCoutLog(bool flag)
Definition: log.cpp:164
void setFileLog(const std::string &filepath, const boost::filesystem::path &dir, QuantLib::Size rotationSize=0)
Definition: log.cpp:144
QuantLib::ext::shared_ptr< text_sink > cacheSink_
Definition: log.hpp:309
ProgressMessage(const std::string &, const QuantLib::Size, const QuantLib::Size, const std::string &detail="")
Definition: log.cpp:629
void emitLog() const
generate Boost log record to pass to corresponding sinks
Definition: log.cpp:639
static constexpr const char * name
Definition: log.hpp:736
static const std::string name
the name "StderrLogger"
Definition: log.hpp:167
static const std::string name
the name "StructuredLogger"
Definition: log.hpp:318
virtual void removeSinks() override
Destructor.
Definition: log.cpp:221
QuantLib::ext::shared_ptr< file_sink > fileSink_
Definition: log.hpp:328
const QuantLib::ext::shared_ptr< file_sink > & fileSink()
Definition: log.hpp:321
StructuredLogger()
Constructors.
Definition: log.cpp:185
void setFileLog(const std::string &filepath, const boost::filesystem::path &dir, QuantLib::Size rotationSize=0)
Definition: log.cpp:228
QuantLib::ext::shared_ptr< text_sink > cacheSink_
Definition: log.hpp:329
void addSubFields(const std::map< std::string, std::string > &)
Definition: log.cpp:594
void emitLog() const
generate Boost log record to pass to corresponding sinks
Definition: log.cpp:576
static constexpr const char * name
Definition: log.hpp:692
StructuredMessage(const Category &category, const Group &group, const std::string &message, const std::map< std::string, std::string > &subFields=std::map< std::string, std::string >())
Definition: log.cpp:555
SafeStack< Filter > filter
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", oreSeverity)
Classes and functions for log message handling.
oreSeverity
Definition: log.hpp:70
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define ORE_DEBUG
Definition: log.hpp:32
#define ORE_CRITICAL
Definition: log.hpp:28
#define ORE_MEMORY
Definition: log.hpp:34
#define ORE_DATA
Definition: log.hpp:33
#define MLOG(mask, text)
Definition: log.hpp:529
#define ORE_NOTICE
Definition: log.hpp:31
#define ORE_ERROR
Definition: log.hpp:29
#define ORE_WARNING
Definition: log.hpp:30
#define ORE_ALERT
Definition: log.hpp:27
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > text_sink
Definition: log.hpp:121
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Serializable Credit Default Swap.
Definition: namespaces.docs:23
string conversion utilities
string name
MarketObject obj