Flow123d  JB_release_tests-c4abd42
logger.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file logger.cc
15  * @brief
16  */
17 
18 
19 #include "system/logger.hh"
20 #include "system/logger_options.hh"
21 #include "system/global_defs.h"
22 
23 #include <iomanip>
24 
25 using namespace std;
26 
27 
28 /// Helper function, use for shorten the code point path
29 std::string cmn_prefix( std::string a, std::string b ) {
30  if( a.size() > b.size() ) std::swap(a,b) ;
31  return std::string( a.begin(), std::mismatch( a.begin(), a.end(), b.begin() ).first ) ;
32 }
33 
34 
35 /*******************************************************************
36  * implementation of StreamMask
37  */
38 
42 
43 
45 {
46  return StreamMask(this->mask_ & other.mask_);
47 }
48 
50 {
51  return StreamMask(this->mask_ | other.mask_);
52 }
53 
55 {
56  return mask_;
57 }
58 
59 
60 /*******************************************************************
61  * implementation of Logger
62  */
63 
64 
66 : type_(type), every_process_(false), line_(0)
67 {
68  // set actual time
70 
71  // set MPI rank
73 }
74 
75 
77 {
78  // print output to streams
81  if (LoggerOptions::get_instance().init_flag() == LoggerOptions::InitFlag::initialize)
83 }
84 
85 
86 const std::string Logger::msg_type_string(MsgType msg_type, bool full_format)
87 {
88  static std::vector<std::string> type_names = {"WARNING.", "MESSAGE.", "LOG.", "DEBUG.", "ERROR.",
89  "Wrn", "Msg", "Log", "Dbg", "Err"};
90  int type_idx = msg_type;
91 
92  if (full_format) {
93  return type_names[type_idx];
94  } else {
95  return type_names[type_idx + 5];
96  }
97 }
98 
99 
100 Logger& Logger::set_context(const char* file_name, const char* function, const int line)
101 {
102  file_name_ = std::string(file_name);
103  function_ = std::string(function);
104  line_ = line;
105  this->set_mask();
106 
107  return *this;
108 }
109 
110 
112 {
113  every_process_ = true;
114  this->set_mask();
115 
116  return *this;
117 }
118 
120 {
121  if ( !every_process_ && (mpi_rank_ > 0) ) return;
122 
123  bool no_log = LoggerOptions::get_instance().init_flag() == LoggerOptions::InitFlag::no_log;
124  bool log_ready = LoggerOptions::get_instance().init_flag() == LoggerOptions::InitFlag::initialize;
125 
126  switch (type_) {
127  case MsgType::warning:
128  case MsgType::error:
129  if (no_log)
131  else
133  break;
134  case MsgType::message:
135  if (no_log)
137  else
139  break;
140  case MsgType::log:
141  if (no_log)
143  else if (log_ready)
145  else
147  break;
148 #ifdef FLOW123D_DEBUG_ASSERTS
149  case MsgType::debug: // for debug build
150  if (no_log)
152  else if (log_ready)
154  else
156  break;
157 #else
158  case MsgType::debug: // for release build
160  break;
161 
162 #endif
163  default:
164  ASSERT_PERMANENT(false);
165  }
166 
168 
169 }
170 
171 
172 
173 void Logger::print_to_screen(std::ostream& stream, std::stringstream& scr_stream, StreamMask mask)
174 {
175  if ( full_streams_mask_() & mask() ) {
176  stream << setfill(' ');
177 
178  // print header, if method returns true, message continues on the same line and first line of message
179  // doesn't need indentation in following while cycle
180  std::stringstream message_stream;
181  bool header_line = this->print_screen_header(message_stream);
182 
183  // print message
184  std::string segment;
185  std::istringstream istream(scr_stream.str());
186  while(std::getline(istream, segment)) {
187  if (header_line) {
188  header_line = false;
189  } else {
190  message_stream << std::setw(18) << "";
191  }
192  message_stream << segment << "\n";
193  }
194 
195  stream << message_stream.str();
196  stream << std::flush;
197  }
198 }
199 
200 
201 void Logger::print_to_file(std::ofstream& stream, std::stringstream& file_stream, StreamMask mask)
202 {
203  if ( full_streams_mask_() & mask() ) {
204  stream << setfill(' ');
205 
206  // print header
207  std::stringstream message_stream;
208  this->print_file_header(message_stream);
209 
210  // print message
211  std::string segment;
212  std::vector<std::string> segments;
213  std::istringstream istream(file_stream.str());
214  while(std::getline(istream, segment)) {
215  segments.push_back(segment);
216  }
217  if (segments.size() > 1) {
218  message_stream << " - |" << "\n";
219  for (auto seg : segments)
220  message_stream << std::setw(4) << "" << seg << "\n";
221  } else if (segments.size() == 1) {
222  message_stream << " - " << segments[0] << "\n";
223  }
224 
225  stream << message_stream.str();
226  stream << std::flush;
227  }
228 }
229 
230 
231 std::string Logger::compact_file_name(std::string file_name)
232 {
233  // if constant FLOW123D_SOURCE_DIR is defined, we try to erase it from beginning of each CodePoint's filepath
234  #ifdef FLOW123D_SOURCE_DIR
235  string common_path = cmn_prefix(string(FLOW123D_SOURCE_DIR), file_name);
236  file_name.erase (0, common_path.size());
237  #endif
238  return file_name;
239 }
240 
241 bool Logger::print_screen_header(std::stringstream& stream)
242 {
243  stream << date_time_ << " ";
244  if (every_process_) { // rank
245  stringstream rank;
246  rank << "[" << mpi_rank_ << "]";
247  stream << setiosflags(ios::left) << std::setw(5) << rank.str();
248  } else {
249  stream << std::setw(5) << "";
250  }
251 
252  stream << msg_type_string(type_);
253  if (type_ == MsgType::debug) {
254  stream << "(" << compact_file_name(file_name_) << ":" << line_ << ")";
255  }
256  return true;
257 }
258 
259 
260 void Logger::print_file_header(std::stringstream& stream)
261 {
262  stream << "- -" << std::setw(13) << "" << "[ ";
263  stream << msg_type_string(type_, false);
264  if (every_process_) { // add 'E' (only for every_proc) + print rank
265  stream << "E, ";
266  if (mpi_rank_ >= 0) stream << setiosflags(ios::right) << std::setw(4) << mpi_rank_;
267  else stream << "null";
268  } else {
269  stream << " , null";
270  }
271  stream << ", \"" << date_time_ << "\"";
272  stream << ", \"" << compact_file_name(file_name_) << "\", " << line_ << ", \"" << function_ << "\"";
273  stream << " ]\n";
274 }
275 
276 
277 
278 /**
279  * implementation of operators
280  */
281 
283 {
284  // set mask
285  log.streams_mask_ = mask;
287 
288  return log;
289 }
290 
291 
292 Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) )
293 {
294  if ( (log.streams_mask_ & StreamMask::cout)() ) pf(log.cout_stream_);
295  if ( (log.streams_mask_ & StreamMask::cerr)() ) pf(log.cerr_stream_);
296  if ( (log.streams_mask_ & StreamMask::log)() ) pf(log.file_stream_);
297  return log;
298 }
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
LoggerOptions::InitFlag init_flag()
Check if singleton instance object is initialize.
static LoggerOptions & get_instance()
Getter of singleton instance object.
static std::string format_hh_mm_ss()
int get_mpi_rank() const
Returns number of actual process, if MPI is not supported returns -1.
Class for storing logger messages.
Definition: logger.hh:135
static const std::string msg_type_string(MsgType msg_type, bool full_format=true)
Return string value of given MsgType in full or shorter format (e.g. "WARNING" of "Wrn")
Definition: logger.cc:86
Logger & set_context(const char *file_name, const char *function, const int line)
Stores values for printing out line number, function, etc.
Definition: logger.cc:100
std::stringstream cerr_stream_
Store messages printed to cerr output stream.
Definition: logger.hh:209
Logger & every_proc()
Set flag every_process_ to true.
Definition: logger.cc:111
StreamMask streams_mask_
Mask of logger, specifies streams in actual time into which to be written.
Definition: logger.hh:219
void set_mask()
Set streams_mask_ according to the type of message.
Definition: logger.cc:119
MsgType
Enum of types of Logger messages.
Definition: logger.hh:150
std::string file_name_
Actual file.
Definition: logger.hh:214
Logger(MsgType type)
Constructor.
Definition: logger.cc:65
MsgType type_
Type of message.
Definition: logger.hh:212
bool every_process_
Flag marked if log message is printing for all processes or only for zero process.
Definition: logger.hh:213
void print_file_header(std::stringstream &file_stream)
Print header to file stream, helper method called from print_to_file.
Definition: logger.cc:260
int line_
Actual line.
Definition: logger.hh:216
std::string function_
Actual function.
Definition: logger.hh:215
void print_to_screen(std::ostream &stream, std::stringstream &scr_stream, StreamMask mask)
Print formated message to given screen stream if mask corresponds with streams_mask_.
Definition: logger.cc:173
std::stringstream cout_stream_
Store messages printed to cout output stream.
Definition: logger.hh:208
std::string compact_file_name(std::string file_name)
Return compact (relative) path to the given source file.
Definition: logger.cc:231
int mpi_rank_
Actual process (if MPI is supported)
Definition: logger.hh:218
~Logger()
Destructor.
Definition: logger.cc:76
std::string date_time_
Actual date and time.
Definition: logger.hh:217
StreamMask full_streams_mask_
Mask of logger, specifies all streams into which to be written in logger message.
Definition: logger.hh:220
bool print_screen_header(std::stringstream &scr_stream)
Print header to screen stream, helper method called from print_to_screen.
Definition: logger.cc:241
std::stringstream file_stream_
Store messages printed to file.
Definition: logger.hh:210
void print_to_file(std::ofstream &stream, std::stringstream &file_stream, StreamMask mask)
Print formated message to given file stream if mask corresponds with streams_mask_.
Definition: logger.cc:201
Helper class, store mask specifying streams.
Definition: logger.hh:41
static StreamMask cerr
Predefined mask of std::cerr output.
Definition: logger.hh:55
int operator()(void)
Definition: logger.cc:54
static StreamMask log
Predefined mask of log file output.
Definition: logger.hh:58
StreamMask operator|(const StreamMask &other)
Definition: logger.cc:49
StreamMask operator&(const StreamMask &other)
Definition: logger.cc:44
int mask_
Definition: logger.hh:70
static StreamMask cout
Predefined mask of std::cout output.
Definition: logger.hh:52
Global macros to enhance readability and debugging, general constants.
std::string cmn_prefix(std::string a, std::string b)
Helper function, use for shorten the code point path.
Definition: logger.cc:29
Logger & operator<<(Logger &log, StreamMask mask)
Definition: logger.cc:282
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value and is_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:8688