Belle II Software development
LogMessage.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <framework/logging/LogMessage.h>
10
11#include <framework/utilities/Utils.h>
12#include <framework/gearbox/Unit.h>
13#include <framework/pcore/ProcHandler.h>
14#include <framework/datastore/StoreObjPtr.h>
15#include <framework/dataobjects/EventMetaData.h>
16#include <framework/core/ProcessStatistics.h>
17
18#include <boost/property_tree/json_parser.hpp>
19#include <ostream>
20#include <utility>
21
22using namespace std;
23using namespace Belle2;
24
25LogMessage::LogMessage(LogConfig::ELogLevel logLevel, const std::string& message, const char* package,
26 std::string function, std::string file, unsigned int line, int debugLevel) :
27 m_logLevel(logLevel),
28 m_message(message),
29 m_module(""),
30 m_package(package ? package : ""),
31 m_function(std::move(function)),
32 m_file(std::move(file)),
33 m_line(line),
34 m_debugLevel(debugLevel),
35 m_logInfo(0),
36 m_count(0)
37{
38}
39
40LogMessage::LogMessage(LogConfig::ELogLevel logLevel, LogVariableStream&& messageStream, const char* package,
41 std::string function, std::string file, unsigned int line, int debugLevel) :
42 m_logLevel(logLevel),
43 m_message(std::move(messageStream)),
44 m_module(""),
45 m_package(package ? package : ""),
46 m_function(std::move(function)),
47 m_file(std::move(file)),
48 m_line(line),
49 m_debugLevel(debugLevel),
50 m_logInfo(0),
51 m_count(0)
52{
54}
55
56
57bool LogMessage::operator==(const LogMessage& message) const
58{
59 return ((m_logLevel == message.m_logLevel) &&
60 (m_line == message.m_line) &&
61 (m_message == message.m_message) &&
62 (m_module == message.m_module) &&
63 (m_package == message.m_package) &&
64 (m_function == message.m_function) &&
65 (m_file == message.m_file));
66}
67
68std::string LogMessage::toJSON(bool complete) const
69{
70 using namespace boost::property_tree::json_parser;
71 std::stringstream buffer;
72 static const double startClock = Utils::getClock();
73 double time = (Utils::getClock() - startClock) / Unit::s;
74 int logInfo = (m_logInfo and not complete) ? m_logInfo :
77 // in JSON we always output level, independent of what the log info says, otherwise it is hard to parse
78 buffer << R"({"level":")" << LogConfig::logLevelToString(m_logLevel) << '"';
79 if (logInfo & LogConfig::c_Message) {
80 buffer << R"(,"message":")" << create_escapes(m_message.getMessage()) << '"';
81 const auto& vars = m_message.getVariables();
82 if ((vars.size() > 0 or complete) and !(logInfo & LogConfig::c_NoVariables)) {
83 buffer << ",\"variables\":{";
84 bool first{true};
85 for (const auto& v : vars) {
86 if (!first) buffer << ",";
87 buffer << '"' << create_escapes(v.getName()) << "\":\"" << create_escapes(v.getValue()) << '"';
88 first = false;
89 }
90 buffer << '}';
91 }
92 }
93 if (logInfo & LogConfig::c_Module)
94 buffer << R"(,"module":")" << create_escapes(m_module) << '"';
95 if (logInfo & LogConfig::c_Package)
96 buffer << R"(,"package":")" << create_escapes(m_package) << '"';
97 if (logInfo & LogConfig::c_Function)
98 buffer << R"(,"function":")" << create_escapes(m_function) << '"';
99 if (logInfo & LogConfig::c_File)
100 buffer << R"(,"file":")" << create_escapes(m_file) << '"';
101 if (logInfo & LogConfig::c_Line)
102 buffer << ",\"line\":" << m_line;
103 if (logInfo & LogConfig::c_Timestamp)
104 buffer << ",\"timestamp\":" << std::fixed << std::setprecision(3) << time;
105 if (ProcHandler::EvtProcID() != -1 or complete)
106 buffer << ",\"proc\":" << ProcHandler::EvtProcID();
107 if (complete) {
108 buffer << ",\"count\":" << m_count;
109 StoreObjPtr<EventMetaData> eventMetaData;
110 if (eventMetaData.isValid()) {
111 buffer << ",\"experiment\":" << eventMetaData->getExperiment();
112 buffer << ",\"run\":" << eventMetaData->getRun();
113 buffer << ",\"subrun\":" << eventMetaData->getSubrun();
114 buffer << ",\"event\":" << eventMetaData->getEvent();
115 }
117 if (processStatistics.isValid()) {
118 const auto& stats = processStatistics->getGlobal();
119 buffer << ",\"nruns\":" << int(stats.getCalls(ModuleStatistics::EStatisticCounters::c_BeginRun));
120 buffer << ",\"nevents\":" << int(stats.getCalls());
121 }
122 buffer << ",\"initialize\":" << ((DataStore::Instance().getInitializeActive()) ? "true" : "false");
123 }
124 buffer << "}\n";
125 return buffer.str();
126}
127
128std::ostream& LogMessage::print(std::ostream& out) const
129{
130 int logInfo = m_logInfo ? m_logInfo :
133 if (logInfo & LogConfig::c_Timestamp) {
134 static const double startClock = Utils::getClock();
135 const auto flags = out.flags();
136 const int oldprecision = out.precision(3);
137 out << std::fixed << (Utils::getClock() - startClock) / Unit::s << ": ";
138 out.precision(oldprecision);
139 out.flags(flags);
140 }
141 if (logInfo & LogConfig::c_Level) {
142 const std::string debugLevel = (m_logLevel == LogConfig::c_Debug) ? (":" + std::to_string(m_debugLevel)) : "";
143 out << "[" << LogConfig::logLevelToString(m_logLevel) << debugLevel << "] ";
144 }
145 if (ProcHandler::EvtProcID() != -1) {
146 //which process is this?
147 out << "(" << ProcHandler::EvtProcID() << ") ";
148 }
149 if (logInfo & LogConfig::c_Message) {
150 out << m_message.str(!(logInfo & LogConfig::c_NoVariables));
151 }
152 // if there is no module or package or similar there's no need to print them
153 if (m_module.empty()) logInfo &= ~LogConfig::c_Module;
154 if (m_package.empty()) logInfo &= ~LogConfig::c_Package;
155 if (m_function.empty()) logInfo &= ~LogConfig::c_Function;
156 // line number without filename is useless as well so disable both in one go
157 if (m_file.empty()) logInfo &= ~(LogConfig::c_File | LogConfig::c_Line);
158 // is there any location string left to print?
159 bool printLocation = logInfo & (LogConfig::c_Module | LogConfig::c_Package | LogConfig::c_Function |
161 if (printLocation) {
162 out << " {";
163 }
164 if (logInfo & LogConfig::c_Module) {
165 out << " module: " << m_module;
166 }
167 if (logInfo & LogConfig::c_Package) {
168 out << " package: " << m_package;
169 }
170 if (logInfo & LogConfig::c_Function) {
171 out << " function: " << m_function;
172 }
173 if (logInfo & LogConfig::c_File) {
174 out << " @" << m_file;
175 }
176 if (logInfo & LogConfig::c_Line) {
177 out << ":" << m_line;
178 }
179 if (printLocation) {
180 out << " }";
181 }
182 out << endl;
183 return out;
184}
185
186
187ostream& operator<< (ostream& out, const LogMessage& logMessage)
188{
189 return logMessage.print(out);
190}
bool getInitializeActive() const
Are we currently initializing modules?
Definition: DataStore.h:502
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:60
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:54
The LogConfig class.
Definition: LogConfig.h:22
ELogLevel
Definition of the supported log levels.
Definition: LogConfig.h:26
@ c_Debug
Debug: for code development.
Definition: LogConfig.h:26
@ c_Module
Module in which the message was emitted.
Definition: LogConfig.h:38
@ c_File
Source file in which the message was emitted.
Definition: LogConfig.h:41
@ c_Function
Function in which the message was emitted.
Definition: LogConfig.h:40
@ c_Line
Line in source file in which the message was emitted.
Definition: LogConfig.h:42
@ c_Level
Log level of the message.
Definition: LogConfig.h:36
@ c_Package
Package in which the message was emitted.
Definition: LogConfig.h:39
@ c_Message
Log message text.
Definition: LogConfig.h:37
@ c_NoVariables
If set don't output any variables that are part of the message.
Definition: LogConfig.h:44
@ c_Timestamp
Time at which the message was emitted.
Definition: LogConfig.h:43
static const char * logLevelToString(ELogLevel logLevelType)
Converts a log level type to a string.
Definition: LogConfig.cc:42
The LogMessage class.
Definition: LogMessage.h:29
LogMessage(LogConfig::ELogLevel logLevel, const std::string &message, const char *package, std::string function, std::string file, unsigned int line, int debugLevel=0)
The LogMessage constructor.
Definition: LogMessage.cc:25
std::string toJSON(bool complete) const
Return a json string for the log message.
Definition: LogMessage.cc:68
int m_debugLevel
The debug level for messages with level=c_Debug.
Definition: LogMessage.h:165
unsigned int m_logInfo
kind of information to show (ORed combination of LogConfig::ELogInfo flags).
Definition: LogMessage.h:167
LogVariableStream m_message
The message stream which should be sent.
Definition: LogMessage.h:159
unsigned int m_line
The line number in the source code where the message was sent from.
Definition: LogMessage.h:164
std::string m_file
The file name where the message was sent from.
Definition: LogMessage.h:163
bool operator==(const LogMessage &message) const
Compares two messages.
Definition: LogMessage.cc:57
std::string m_module
The module name where the message was sent from.
Definition: LogMessage.h:160
std::ostream & print(std::ostream &out) const
Generate output stream.
Definition: LogMessage.cc:128
std::string m_function
The function name where the message was sent from.
Definition: LogMessage.h:162
LogConfig::ELogLevel m_logLevel
The log level of the message.
Definition: LogMessage.h:158
std::string m_package
The package name where the message was sent from.
Definition: LogMessage.h:161
int m_count
Number of occurrences of the same message.
Definition: LogMessage.h:168
@ c_BeginRun
Counting time/calls in beginRun()
static int EvtProcID()
Return ID of the current process.
Definition: ProcHandler.cc:248
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:111
static const double s
[second]
Definition: Unit.h:95
Specialized implementation of an ostream-like class where the << operator can be used to insert value...
const std::vector< LogVar > & getVariables() const
Return the list of all defined variables.
std::string getMessage() const
Return the constant message part without the variables.
void adjustLogLevel(Belle2::LogConfig::ELogLevel &logLevel) const
Adjust the log level in case of a realm dependent modification.
std::string str(bool showVariables=true) const
Return the content of the stream as string.
std::ostream & operator<<(std::ostream &output, const IntervalOfValidity &iov)
double getClock()
Return current value of the real-time clock.
Definition: Utils.cc:66
Abstract base class for different kinds of events.
STL namespace.