Flow123d  JS_before_hm-1003-g4e68d2c
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 
24 #include <iomanip>
25 
26 
27 /// Helper function, use for shorten the code point path
28 std::string cmn_prefix( std::string a, std::string b ) {
29  if( a.size() > b.size() ) std::swap(a,b) ;
30  return std::string( a.begin(), std::mismatch( a.begin(), a.end(), b.begin() ).first ) ;
31 }
32 
33 
34 /*******************************************************************
35  * implementation of StreamMask
36  */
37 
41 
42 
44 {
45  return StreamMask(this->mask_ & other.mask_);
46 }
47 
49 {
50  return StreamMask(this->mask_ | other.mask_);
51 }
52 
54 {
55  return mask_;
56 }
57 
58 
59 /*******************************************************************
60  * implementation of Logger
61  */
62 
63 
65 : type_(type), every_process_(false), line_(0)
66 {
67  // set actual time
69 
70  // set MPI rank
72 }
73 
74 
76 {
77  // print output to streams
78  print_to_screen(std::cout, cout_stream_, StreamMask::cout);
79  print_to_screen(std::cerr, cerr_stream_, StreamMask::cerr);
80  if (LoggerOptions::get_instance().is_init())
82 }
83 
84 
85 const std::string Logger::msg_type_string(MsgType msg_type, bool full_format)
86 {
87  static std::vector<std::string> type_names = {"WARNING.", "MESSAGE.", "LOG.", "DEBUG.", "ERROR",
88  "Wrn", "Msg", "Log", "Dbg", "Err"};
89  int type_idx = msg_type;
90 
91  if (full_format) {
92  return type_names[type_idx];
93  } else {
94  return type_names[type_idx + 5];
95  }
96 }
97 
98 
99 Logger& Logger::set_context(const char* file_name, const char* function, const int line)
100 {
101  file_name_ = std::string(file_name);
102  function_ = std::string(function);
103  line_ = line;
104  this->set_mask();
105 
106  return *this;
107 }
108 
109 
111 {
112  every_process_ = true;
113  this->set_mask();
114 
115  return *this;
116 }
117 
119 {
120  if ( !every_process_ && (mpi_rank_ > 0) ) return;
121 
122  switch (type_) {
123  case MsgType::warning:
124  case MsgType::error:
125  if (LoggerOptions::get_instance().no_log_)
127  else
128  streams_mask_ = StreamMask::cerr | StreamMask::log;
129  break;
130  case MsgType::message:
131  if (LoggerOptions::get_instance().no_log_)
133  else
134  streams_mask_ = StreamMask::cout | StreamMask::log;
135  break;
136  case MsgType::log:
137  if (LoggerOptions::get_instance().no_log_)
139  else if (LoggerOptions::get_instance().is_init())
141  else
143  break;
144 #ifdef FLOW123D_DEBUG
145  case MsgType::debug: // for debug build
146  if (LoggerOptions::get_instance().no_log_)
148  else if (LoggerOptions::get_instance().is_init())
149  streams_mask_ = StreamMask::log | StreamMask::cout;
150  else
152  break;
153 #else
154  case MsgType::debug: // for release build
156  break;
157 
158 #endif
159  default:
160  ASSERT(false);
161  }
162 
164 
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  std::stringstream message_stream;
177  bool header_line = this->print_screen_header(message_stream);
178 
179  // print message
180  std::string segment;
181  std::istringstream istream(scr_stream.str());
182  while(std::getline(istream, segment)) {
183  if (header_line) {
184  header_line = false;
185  } else {
186  message_stream << std::setw(18) << "";
187  }
188  message_stream << segment << "\n";
189  }
190 
191  stream << message_stream.str();
192  stream << std::flush;
193  }
194 }
195 
196 
197 void Logger::print_to_file(std::ofstream& stream, std::stringstream& file_stream, StreamMask mask)
198 {
199  if ( full_streams_mask_() & mask() ) {
200  stream << setfill(' ');
201 
202  // print header
203  std::stringstream message_stream;
204  this->print_file_header(message_stream);
205 
206  // print message
207  std::string segment;
208  std::vector<std::string> segments;
209  std::istringstream istream(file_stream.str());
210  while(std::getline(istream, segment)) {
211  segments.push_back(segment);
212  }
213  if (segments.size() > 1) {
214  message_stream << " - |" << "\n";
215  for (auto seg : segments)
216  message_stream << std::setw(4) << "" << seg << "\n";
217  } else if (segments.size() == 1) {
218  message_stream << " - " << segments[0] << "\n";
219  }
220 
221  stream << message_stream.str();
222  stream << std::flush;
223  }
224 }
225 
226 
227 std::string Logger::compact_file_name(std::string file_name)
228 {
229  // if constant FLOW123D_SOURCE_DIR is defined, we try to erase it from beginning of each CodePoint's filepath
230  #ifdef FLOW123D_SOURCE_DIR
231  string common_path = cmn_prefix(string(FLOW123D_SOURCE_DIR), file_name);
232  file_name.erase (0, common_path.size());
233  #endif
234  return file_name;
235 }
236 
237 bool Logger::print_screen_header(std::stringstream& stream)
238 {
239  stream << date_time_ << " ";
240  if (every_process_) { // rank
241  stringstream rank;
242  rank << "[" << mpi_rank_ << "]";
243  stream << setiosflags(ios::left) << std::setw(5) << rank.str();
244  } else {
245  stream << std::setw(5) << "";
246  }
247 
248  stream << msg_type_string(type_);
249  if (type_ == MsgType::debug) {
250  stream << "(" << compact_file_name(file_name_) << ":" << line_ << ")";
251  }
252  return true;
253 }
254 
255 
256 void Logger::print_file_header(std::stringstream& stream)
257 {
258  stream << "- -" << std::setw(13) << "" << "[ ";
259  stream << msg_type_string(type_, false);
260  if (every_process_) { // add 'E' (only for every_proc) + print rank
261  stream << "E, ";
262  if (mpi_rank_ >= 0) stream << setiosflags(ios::right) << std::setw(4) << mpi_rank_;
263  else stream << "null";
264  } else {
265  stream << " , null";
266  }
267  stream << ", \"" << date_time_ << "\"";
268  stream << ", \"" << compact_file_name(file_name_) << "\", " << line_ << ", \"" << function_ << "\"";
269  stream << " ]\n";
270 }
271 
272 
273 
274 /**
275  * implementation of operators
276  */
277 
279 {
280  // set mask
281  log.streams_mask_ = mask;
283 
284  return log;
285 }
286 
287 
288 Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) )
289 {
290  if ( (log.streams_mask_ & StreamMask::cout)() ) pf(log.cout_stream_);
291  if ( (log.streams_mask_ & StreamMask::cerr)() ) pf(log.cerr_stream_);
292  if ( (log.streams_mask_ & StreamMask::log)() ) pf(log.file_stream_);
293  return log;
294 }
Class for storing logger messages.
Definition: logger.hh:135
static StreamMask cout
Predefined mask of std::cout output.
Definition: logger.hh:52
int operator()(void)
Definition: logger.cc:53
std::stringstream cout_stream_
Store messages printed to cout output stream.
Definition: logger.hh:196
~Logger()
Destructor.
Definition: logger.cc:75
StreamMask streams_mask_
Mask of logger, specifies streams in actual time into which to be written.
Definition: logger.hh:207
StreamMask()
Empty constructor.
Definition: logger.hh:44
friend Logger & operator<<(Logger &log, const T &x)
Definition: logger.hh:239
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
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:99
std::string cmn_prefix(std::string a, std::string b)
Helper function, use for shorten the code point path.
Definition: logger.cc:28
static std::string format_hh_mm_ss()
std::stringstream cerr_stream_
Store messages printed to cerr output stream.
Definition: logger.hh:197
std::string function_
Actual function.
Definition: logger.hh:203
StreamMask operator|(const StreamMask &other)
Definition: logger.cc:48
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:85
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:197
bool print_screen_header(std::stringstream &scr_stream)
Print header to screen stream, helper method called from print_to_screen.
Definition: logger.cc:237
static StreamMask log
Predefined mask of log file output.
Definition: logger.hh:58
StreamMask operator&(const StreamMask &other)
Definition: logger.cc:43
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:205
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:201
int get_mpi_rank()
Returns number of actual process, if MPI is not supported returns -1.
int line_
Actual line.
Definition: logger.hh:204
std::stringstream file_stream_
Store messages printed to file.
Definition: logger.hh:198
Logger & every_proc()
Set flag every_process_ to true.
Definition: logger.cc:110
static LoggerOptions & get_instance()
Getter of singleton instance object.
void print_file_header(std::stringstream &file_stream)
Print header to file stream, helper method called from print_to_file.
Definition: logger.cc:256
StreamMask full_streams_mask_
Mask of logger, specifies all streams into which to be written in logger message. ...
Definition: logger.hh:208
std::string file_name_
Actual file.
Definition: logger.hh:202
int mpi_rank_
Actual process (if MPI is supported)
Definition: logger.hh:206
std::string compact_file_name(std::string file_name)
Return compact (relative) path to the given source file.
Definition: logger.cc:227
MsgType type_
Type of message.
Definition: logger.hh:200
void set_mask()
Set streams_mask_ according to the type of message.
Definition: logger.cc:118
Logger(MsgType type)
Constructor.
Definition: logger.cc:64
MsgType
Enum of types of Logger messages.
Definition: logger.hh:138