41#include <boost/algorithm/string.hpp>
42#include <boost/log/attributes/mutable_constant.hpp>
43#include <boost/log/utility/manipulators/add_value.hpp>
44#include <boost/log/attributes.hpp>
45#include <boost/log/expressions.hpp>
46#include <boost/log/expressions/formatters/date_time.hpp>
47#include <boost/log/sinks.hpp>
48#include <boost/log/sources/global_logger_storage.hpp>
49#include <boost/log/sources/record_ostream.hpp>
50#include <boost/log/sources/severity_logger.hpp>
51#include <boost/filesystem.hpp>
52#include <ql/shared_ptr.hpp>
54#include <ql/qldefines.hpp>
63#include <ql/patterns/singleton.hpp>
66#include <boost/any.hpp>
67#include <boost/thread/shared_mutex.hpp>
68#include <boost/thread/lock_types.hpp>
83template <
typename CharT,
typename TraitsT>
84inline std::basic_ostream<CharT, TraitsT>&
operator<<(std::basic_ostream<CharT, TraitsT>& strm,
oreSeverity lvl) {
120typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>
file_sink;
121typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend>
text_sink;
141 virtual void log(
unsigned level,
const std::string& s) = 0;
177 virtual void log(
unsigned l,
const std::string& s)
override {
179 std::cerr << s << std::endl;
207 virtual void log(
unsigned,
const std::string&)
override;
237 virtual void log(
unsigned,
const std::string&)
override;
304 void setFileLog(
const std::string& filepath,
const boost::filesystem::path& dir, QuantLib::Size rotationSize = 0);
325 void setFileLog(
const std::string& filepath,
const boost::filesystem::path& dir, QuantLib::Size rotationSize = 0);
345 void setFormatter(
const std::function<
void(
const boost::log::record_view&, boost::log::formatting_ostream&)>&);
389class Log :
public QuantLib::Singleton<Log, std::integral_constant<bool, true>> {
391 friend class QuantLib::Singleton<
Log, std::integral_constant<bool, true>>;
400 void
registerLogger(const QuantLib::ext::shared_ptr<Logger>& logger);
415 QuantLib::ext::shared_ptr<Logger>&
logger(const std::string& name);
416 QuantLib::ext::shared_ptr<IndependentLogger>&
independentLogger(const std::string& name);
432 void
addExcludeFilter(const std::string&, const std::function<bool(const std::string&)>);
439 void
header(unsigned m, const char* filename, int lineNo);
443 void log(
unsigned m);
450 boost::shared_lock<boost::shared_mutex> lock(
mutex());
454 boost::shared_lock<boost::shared_mutex> lock(
mutex());
458 boost::unique_lock<boost::shared_mutex> lock(
mutex());
462 boost::shared_lock<boost::shared_mutex> lock(
mutex());
466 boost::unique_lock<boost::shared_mutex> lock(
mutex());
470 boost::shared_lock<boost::shared_mutex> lock(
mutex());
474 boost::unique_lock<boost::shared_mutex> lock(
mutex());
479 boost::shared_lock<boost::shared_mutex> lock(
mutex());
483 boost::unique_lock<boost::shared_mutex> lock(
mutex());
487 boost::unique_lock<boost::shared_mutex> lock(
mutex());
492 boost::shared_lock<boost::shared_mutex> lock(
mutex());
503 std::string
source(
const char* filename,
int lineNo)
const;
505 std::map<std::string, QuantLib::ext::shared_ptr<Logger>>
loggers_;
529#define MLOG(mask, text) \
531 if (ore::data::Log::instance().enabled() && ore::data::Log::instance().filter(mask)) { \
532 std::ostringstream __ore_mlog_tmp_stringstream__; \
533 __ore_mlog_tmp_stringstream__ << text; \
534 if (!ore::data::Log::instance().checkExcludeFilters(__ore_mlog_tmp_stringstream__.str())) { \
535 boost::unique_lock<boost::shared_mutex> lock(ore::data::Log::instance().mutex()); \
536 ore::data::Log::instance().header(mask, __FILE__, __LINE__); \
537 ore::data::Log::instance().logStream() << __ore_mlog_tmp_stringstream__.str(); \
538 ore::data::Log::instance().log(mask); \
544#define ALOG(text) MLOG(oreSeverity::alert, text);
546#define CLOG(text) MLOG(oreSeverity::critical, text)
548#define ELOG(text) MLOG(oreSeverity::error, text)
550#define WLOG(text) MLOG(oreSeverity::warning, text)
552#define LOG(text) MLOG(oreSeverity::notice, text)
554#define DLOG(text) MLOG(oreSeverity::debug, text)
556#define TLOG(text) MLOG(oreSeverity::data, text)
559#define MEM_LOG MEM_LOG_USING_LEVEL(oreSeverity::memory)
561#define MEM_LOG_USING_LEVEL(LEVEL) \
563 if (ore::data::Log::instance().enabled() && ore::data::Log::instance().filter(LEVEL)) { \
564 boost::unique_lock<boost::shared_mutex> lock(ore::data::Log::instance().mutex()); \
565 ore::data::Log::instance().header(LEVEL, __FILE__, __LINE__); \
566 ore::data::Log::instance().logStream() << std::to_string(ore::data::os::getPeakMemoryUsageBytes()) << "|"; \
567 ore::data::Log::instance().logStream() << std::to_string(ore::data::os::getMemoryUsageBytes()); \
568 ore::data::Log::instance().log(LEVEL); \
607 LoggerStream(
unsigned mask,
const char* filename,
unsigned lineNo);
613 operator std::ostream &() {
return ss_; }
622#define CHECKED_LOGGERSTREAM(LEVEL, text) \
623 if (ore::data::Log::instance().enabled() && ore::data::Log::instance().filter(LEVEL)) { \
624 (std::ostream&)ore::data::LoggerStream(LEVEL, __FILE__, __LINE__) << text; \
627#define ALOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_ALERT, text)
628#define CLOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_CRITICAL, text)
629#define ELOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_ERROR, text)
630#define WLOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_WARNING, text)
631#define LOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_NOTICE, text)
632#define DLOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_DEBUG, text)
633#define TLOGGERSTREAM(text) CHECKED_LOGGERSTREAM(ORE_DATA, text)
639 virtual std::string
msg()
const = 0;
649 static std::string
jsonify(
const boost::any&);
651 std::map<std::string, boost::any>
data_;
684 const std::map<std::string, std::string>& subFields = std::map<std::string, std::string>());
687 const std::pair<std::string, std::string>& subField = std::pair<std::string, std::string>())
688 :
StructuredMessage(category, group, message, std::map<std::string, std::string>({subField})) {}
692 static constexpr const char*
name =
"StructuredMessage";
695 std::string
msg()
const {
return std::string(
name) + std::string(
" ") +
json(); }
700 void addSubFields(
const std::map<std::string, std::string>&);
711 std::pair<std::string, std::string>({
"exceptionType", exceptionType})){};
716 EventMessage(
const std::string&
msg,
const std::string& msgKey,
const std::map<std::string, boost::any> data = {}) {
721 static constexpr const char*
name =
"EventMessage";
724 std::string
msg()
const {
return std::string(
name) + std::string(
" ") +
json(); }
734 ProgressMessage(
const std::string&,
const QuantLib::Size,
const QuantLib::Size,
const std::string& detail =
"");
736 static constexpr const char*
name =
"ProgressMessage";
739 std::string
msg()
const {
return std::string(
name) + std::string(
" ") +
json(); }
746class ConsoleLog :
public QuantLib::Singleton<ConsoleLog, std::integral_constant<bool, true>> {
747 friend class QuantLib::Singleton<
ConsoleLog, std::integral_constant<bool, true>>;
759 boost::shared_lock<boost::shared_mutex> lock(
mutex());
763 boost::shared_lock<boost::shared_mutex> lock(
mutex_);
767 boost::shared_lock<boost::shared_mutex> lock(
mutex_);
771 boost::unique_lock<boost::shared_mutex> lock(
mutex_);
775 boost::unique_lock<boost::shared_mutex> lock(
mutex_);
779 boost::unique_lock<boost::shared_mutex> lock(
mutex_);
783 boost::unique_lock<boost::shared_mutex> lock(
mutex_);
790#define CONSOLEW(text) \
792 if (ore::data::ConsoleLog::instance().enabled()) { \
793 Size w = ore::data::ConsoleLog::instance().width(); \
794 std::ostringstream oss; \
796 Size len = oss.str().length(); \
797 Size wsLen = w > len ? w - len : 1; \
798 oss << std::string(wsLen, ' '); \
799 boost::unique_lock<boost::shared_mutex> lock(ore::data::ConsoleLog::instance().mutex()); \
800 std::cout << oss.str(); \
801 std::cout << std::flush; \
805#define CONSOLE(text) \
807 if (ore::data::ConsoleLog::instance().enabled()) { \
808 std::ostringstream oss; \
810 boost::unique_lock<boost::shared_mutex> lock(ore::data::ConsoleLog::instance().mutex()); \
811 std::cout << oss.str() << "\n"; \
812 std::cout << std::flush; \
static const std::string name
the name "BufferLogger"
std::queue< std::string > buffer_
BufferLogger(unsigned minLevel=64)
Constructor.
virtual void log(unsigned, const std::string &) override
The log callback.
bool hasNext()
Checks if Logger has new messages.
virtual ~BufferLogger()
Destructor.
std::string next()
Retrieve new messages.
Singleton to control console logging.
void setWidth(QuantLib::Size w)
boost::shared_mutex & mutex()
mutex to acquire locks
QuantLib::Size progressBarWidth_
QuantLib::Size progressBarWidth()
boost::shared_mutex mutex_
void setProgressBarWidth(QuantLib::Size w)
static const std::string name
the name "EventLogger"
virtual void removeSinks() override
Destructor.
QuantLib::ext::shared_ptr< file_sink > fileSink_
void setFileLog(const std::string &filepath)
const QuantLib::ext::shared_ptr< file_sink > & fileSink()
void setFormatter(const std::function< void(const boost::log::record_view &, boost::log::formatting_ostream &)> &)
EventMessage(const std::string &msg, const std::string &msgKey, const std::map< std::string, boost::any > data={})
void emitLog() const
generate Boost log record to pass to corresponding sinks
std::string msg() const
return a std::string for the log file
static constexpr const char * name
virtual ~FileLogger()
Destructor.
static const std::string name
the name "FileLogger"
virtual void log(unsigned, const std::string &) override
The log callback.
Base Log handler class that utilises Boost logging to create log sinks.
const std::string & name() const
Returns the Logger name.
IndependentLogger(const std::string &name)
Constructor.
std::vector< std::string > & messages()
virtual void removeSinks()=0
std::vector< std::string > messages_
virtual ~IndependentLogger()
Destructor.
const std::string json() const
create JSON-like output from the data
static std::string jsonify(const boost::any &)
void set(const std::string &key, const boost::any &value)
virtual std::string msg() const =0
return a std::string for the log file
std::map< std::string, boost::any > data_
void log() const
generate Boost log record to pass to corresponding sinks
virtual void emitLog() const =0
generate Boost log record - this method is called by log()
void removeLogger(const std::string &name)
Remove a Logger.
std::map< std::string, QuantLib::ext::shared_ptr< Logger > > loggers_
boost::shared_mutex & mutex()
mutex to acquire locks
QuantLib::ext::shared_ptr< Logger > & logger(const std::string &name)
Retrieve a Logger.
std::ostream & logStream()
macro utility function - do not use directly, not thread safe
const boost::filesystem::path & rootPath()
bool filter(unsigned mask)
void setMask(unsigned mask)
std::map< std::string, std::function< bool(const std::string &)> > excludeFilters_
const bool hasIndependentLogger(const std::string &name) const
std::size_t sameSourceLocationCutoff_
void setPid(const int pid)
if a PID is set for the logger, messages are tagged with [1234] if pid = 1234
std::size_t sameSourceLocationSince_
boost::filesystem::path rootPath_
bool writeSuppressedMessagesHint()
const bool hasLogger(const std::string &name) const
Check if logger exists.
void header(unsigned m, const char *filename, int lineNo)
macro utility function - do not use directly, not thread safe
std::string source(const char *filename, int lineNo) const
void removeIndependentLogger(const std::string &name)
void registerIndependentLogger(const QuantLib::ext::shared_ptr< IndependentLogger > &logger)
boost::shared_mutex mutex_
std::map< std::string, QuantLib::ext::shared_ptr< IndependentLogger > > independentLoggers_
void removeAllLoggers()
Remove all loggers.
bool checkExcludeFilters(const std::string &)
QuantLib::ext::shared_ptr< IndependentLogger > & independentLogger(const std::string &name)
void addExcludeFilter(const std::string &, const std::function< bool(const std::string &)>)
std::string lastFileName_
void removeExcludeFilter(const std::string &)
void registerLogger(const QuantLib::ext::shared_ptr< Logger > &logger)
Add a new Logger.
void clearAllIndependentLoggers()
bool writeSuppressedMessagesHint_
void setMaxLen(const int n)
void log(unsigned m)
macro utility function - do not use directly, not thread safe
void setRootPath(const boost::filesystem::path &pth)
The Base Custom Log Handler class.
const std::string & name()
Returns the Logger name.
virtual void log(unsigned level, const std::string &s)=0
The Log call back function.
virtual ~Logger()
Destructor.
Logger(const std::string &name)
Constructor.
LoggerStream class that is a std::ostream replacement that will log each line.
~LoggerStream()
destructor - this is when the logging takes place.
static const std::string name
the name "ProgressLogger"
virtual void removeSinks() override
Destructor.
ProgressLogger()
Constructors.
QuantLib::ext::shared_ptr< text_sink > coutSink_
QuantLib::ext::shared_ptr< file_sink > fileSink_
const QuantLib::ext::shared_ptr< text_sink > & cacheSink()
ProgressLogger(const bool coutLog)
const QuantLib::ext::shared_ptr< file_sink > & fileSink()
const QuantLib::ext::shared_ptr< text_sink > & coutSink()
void setCoutLog(bool flag)
void setFileLog(const std::string &filepath, const boost::filesystem::path &dir, QuantLib::Size rotationSize=0)
QuantLib::ext::shared_ptr< text_sink > cacheSink_
void emitLog() const
generate Boost log record to pass to corresponding sinks
std::string msg() const
return a std::string for the log file
static constexpr const char * name
static const std::string name
the name "StderrLogger"
StderrLogger(bool alertOnly=false)
Constructor.
virtual ~StderrLogger()
Destructor.
virtual void log(unsigned l, const std::string &s) override
The log callback that writes to stderr.
static const std::string name
the name "StructuredLogger"
virtual void removeSinks() override
Destructor.
QuantLib::ext::shared_ptr< file_sink > fileSink_
const QuantLib::ext::shared_ptr< text_sink > & cacheSink()
const QuantLib::ext::shared_ptr< file_sink > & fileSink()
StructuredLogger()
Constructors.
void setFileLog(const std::string &filepath, const boost::filesystem::path &dir, QuantLib::Size rotationSize=0)
QuantLib::ext::shared_ptr< text_sink > cacheSink_
StructuredLoggingErrorMessage(const std::string &exceptionType, const std::string &exceptionWhat="")
StructuredMessage(const Category &category, const Group &group, const std::string &message, const std::pair< std::string, std::string > &subField=std::pair< std::string, std::string >())
void addSubFields(const std::map< std::string, std::string > &)
void emitLog() const
generate Boost log record to pass to corresponding sinks
std::string msg() const
return a std::string for the log file
virtual ~StructuredMessage()
static constexpr const char * name
SafeStack< ValueType > value
std::basic_ostream< CharT, TraitsT > & operator<<(std::basic_ostream< CharT, TraitsT > &strm, oreSeverity lvl)
Outputs stringized representation of the severity level to the stream.
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > text_sink
boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > file_sink
Serializable Credit Default Swap.
Various OS specific utilities.