Flow123d  release_2.2.0-914-gf1a3a4f
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 #include "system/file_path.hh"
23 #include "config.h"
24 
25 #include <iomanip>
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
79  print_to_screen(std::cout, cout_stream_, StreamMask::cout);
80  print_to_screen(std::cerr, cerr_stream_, StreamMask::cerr);
81  if (LoggerOptions::get_instance().is_init())
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  switch (type_) {
124  case MsgType::warning:
125  case MsgType::error:
126  if (LoggerOptions::get_instance().no_log_)
128  else
129  streams_mask_ = StreamMask::cerr | StreamMask::log;
130  break;
131  case MsgType::message:
132  if (LoggerOptions::get_instance().no_log_)
134  else
135  streams_mask_ = StreamMask::cout | StreamMask::log;
136  break;
137  case MsgType::log:
138  if (LoggerOptions::get_instance().no_log_)
140  else if (LoggerOptions::get_instance().is_init())
142  else
144  break;
145 #ifdef FLOW123D_DEBUG
146  case MsgType::debug: // for debug build
147  if (LoggerOptions::get_instance().no_log_)
149  else if (LoggerOptions::get_instance().is_init())
150  streams_mask_ = StreamMask::log | StreamMask::cout;
151  else
153  break;
154 #else
155  case MsgType::debug: // for release build
157  break;
158 
159 #endif
160  default:
161  ASSERT(false);
162  }
163 
165 
166 }
167 
168 
169 void Logger::print_to_screen(std::ostream& stream, std::stringstream& scr_stream, StreamMask mask)
170 {
171  if ( full_streams_mask_() & mask() ) {
172  stream << setfill(' ');
173 
174  // print header, if method returns true, message continues on the same line and first line of message
175  // doesn't need indentation in following while cycle
176  bool header_line = this->print_screen_header(stream, scr_stream);
177 
178  // print message
179  std::string segment;
180  std::istringstream istream(scr_stream.str());
181  while(std::getline(istream, segment)) {
182  if (header_line) {
183  header_line = false;
184  } else {
185  stream << std::setw(18) << "";
186  }
187  stream << segment << "\n";
188  }
189 
190  stream << std::flush;
191  }
192 }
193 
194 
195 void Logger::print_to_file(std::ofstream& stream, std::stringstream& file_stream, StreamMask mask)
196 {
197  if ( full_streams_mask_() & mask() ) {
198  stream << setfill(' ');
199 
200  // print header
201  this->print_file_header(stream, file_stream);
202 
203  // print message
204  std::string segment;
205  std::vector<std::string> segments;
206  std::istringstream istream(file_stream.str());
207  while(std::getline(istream, segment)) {
208  segments.push_back(segment);
209  }
210  if (segments.size() > 1) {
211  stream << " - |" << "\n";
212  for (auto seg : segments)
213  stream << std::setw(4) << "" << seg << "\n";
214  } else if (segments.size() == 1) {
215  stream << " - " << segments[0] << "\n";
216  }
217 
218  stream << std::flush;
219  }
220 }
221 
222 
223 std::string Logger::compact_file_name(std::string file_name)
224 {
225  // if constant FLOW123D_SOURCE_DIR is defined, we try to erase it from beginning of each CodePoint's filepath
226  #ifdef FLOW123D_SOURCE_DIR
227  string common_path = cmn_prefix(string(FLOW123D_SOURCE_DIR), file_name);
228  file_name.erase (0, common_path.size());
229  #endif
230  return file_name;
231 }
232 
233 bool Logger::print_screen_header(std::ostream& stream, std::stringstream& scr_stream)
234 {
235  stream << date_time_ << " ";
236  if (every_process_) { // rank
237  stringstream rank;
238  rank << "[" << mpi_rank_ << "]";
239  stream << setiosflags(ios::left) << std::setw(5) << rank.str();
240  } else {
241  stream << std::setw(5) << "";
242  }
243 
244  if (type_ != MsgType::message) { // type of message (besides Message)
245  stream << msg_type_string(type_);
246  if (type_ == MsgType::debug) {
247  stream << "(" << compact_file_name(file_name_) << ":" << line_ << ")";
248  }
249  stream << "\n";
250  return false; // logger message starts at new line
251  } else {
252  return true; // logger message continues on the same line as header
253  }
254 }
255 
256 
257 void Logger::print_file_header(std::ofstream& stream, std::stringstream& file_stream)
258 {
259  stream << "- -" << std::setw(13) << "" << "[ ";
260  stream << msg_type_string(type_, false);
261  if (every_process_) { // add 'E' (only for every_proc) + print rank
262  stream << "E, ";
263  if (mpi_rank_ >= 0) stream << setiosflags(ios::right) << std::setw(4) << mpi_rank_;
264  else stream << "null";
265  } else {
266  stream << " , null";
267  }
268  stream << ", \"" << date_time_ << "\"";
269  stream << ", \"" << compact_file_name(file_name_) << "\", " << line_ << ", \"" << function_ << "\"";
270  stream << " ]\n";
271 }
272 
273 
274 
275 /**
276  * implementation of operators
277  */
278 
280 {
281  // set mask
282  log.streams_mask_ = mask;
284 
285  return log;
286 }
287 
288 
289 Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) )
290 {
291  if ( (log.streams_mask_ & StreamMask::cout)() ) pf(log.cout_stream_);
292  if ( (log.streams_mask_ & StreamMask::cerr)() ) pf(log.cerr_stream_);
293  if ( (log.streams_mask_ & StreamMask::log)() ) pf(log.file_stream_);
294  return log;
295 }
Class for storing logger messages.
Definition: logger.hh:137
void print_file_header(std::ofstream &stream, std::stringstream &file_stream)
Print header to file stream, helper method called from print_to_file.
Definition: logger.cc:257
static StreamMask cout
Predefined mask of std::cout output.
Definition: logger.hh:52
int operator()(void)
Definition: logger.cc:54
std::stringstream cout_stream_
Store messages printed to cout output stream.
Definition: logger.hh:198
~Logger()
Destructor.
Definition: logger.cc:76
StreamMask streams_mask_
Mask of logger, specifies streams in actual time into which to be written.
Definition: logger.hh:209
StreamMask()
Empty constructor.
Definition: logger.hh:44
friend Logger & operator<<(Logger &log, const T &x)
Definition: logger.hh:226
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
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::string cmn_prefix(std::string a, std::string b)
Helper function, use for shorten the code point path.
Definition: logger.cc:29
static std::string format_hh_mm_ss()
std::stringstream cerr_stream_
Store messages printed to cerr output stream.
Definition: logger.hh:199
std::string function_
Actual function.
Definition: logger.hh:205
StreamMask operator|(const StreamMask &other)
Definition: logger.cc:49
Global macros to enhance readability and debugging, general constants.
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
static StreamMask cerr
Predefined mask of std::cerr output.
Definition: logger.hh:55
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:195
static StreamMask log
Predefined mask of log file output.
Definition: logger.hh:58
StreamMask operator&(const StreamMask &other)
Definition: logger.cc:44
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:169
Helper class, store mask specifying streams.
Definition: logger.hh:41
std::string date_time_
Actual date and time.
Definition: logger.hh:207
int mask_
Definition: logger.hh:70
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value andis_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:8688
bool every_process_
Flag marked if log message is printing for all processes or only for zero process.
Definition: logger.hh:203
int get_mpi_rank()
Returns number of actual process, if MPI is not supported returns -1.
int line_
Actual line.
Definition: logger.hh:206
std::stringstream file_stream_
Store messages printed to file.
Definition: logger.hh:200
Logger & every_proc()
Set flag every_process_ to true.
Definition: logger.cc:111
static LoggerOptions & get_instance()
Getter of singleton instance object.
StreamMask full_streams_mask_
Mask of logger, specifies all streams into which to be written in logger message. ...
Definition: logger.hh:210
bool print_screen_header(std::ostream &stream, std::stringstream &scr_stream)
Print header to screen stream, helper method called from print_to_screen.
Definition: logger.cc:233
std::string file_name_
Actual file.
Definition: logger.hh:204
int mpi_rank_
Actual process (if MPI is supported)
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:223
MsgType type_
Type of message.
Definition: logger.hh:202
void set_mask()
Set streams_mask_ according to the type of message.
Definition: logger.cc:119
Logger(MsgType type)
Constructor.
Definition: logger.cc:65
MsgType
Enum of types of Logger messages.
Definition: logger.hh:140