Belle II Software  release-08-01-10
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 
22 using namespace std;
23 using namespace Belle2;
24 
25 LogMessage::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 
40 LogMessage::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 
57 bool 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 
68 std::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 
128 std::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 
187 ostream& 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
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...
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.
const std::vector< LogVar > & getVariables() const
Return the list of all defined variables.
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.