Flow123d  master-49d9643
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
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  bool no_log = LoggerOptions::get_instance().no_log_;
123  bool log_ready = LoggerOptions::get_instance().is_init();
124 
125  switch (type_) {
126  case MsgType::warning:
127  case MsgType::error:
128  if (no_log)
130  else
132  break;
133  case MsgType::message:
134  if (no_log)
136  else
138  break;
139  case MsgType::log:
140  if (no_log)
142  else if (log_ready)
144  else
146  break;
147 #ifdef FLOW123D_DEBUG_ASSERTS
148  case MsgType::debug: // for debug build
149  if (no_log)
151  else if (log_ready)
153  else
155  break;
156 #else
157  case MsgType::debug: // for release build
159  break;
160 
161 #endif
162  default:
163  ASSERT_PERMANENT(false);
164  }
165 
167 
168 }
169 
170 
171 
172 void Logger::print_to_screen(std::ostream& stream, std::stringstream& scr_stream, StreamMask mask)
173 {
174  if ( full_streams_mask_() & mask() ) {
175  stream << setfill(' ');
176 
177  // print header, if method returns true, message continues on the same line and first line of message
178  // doesn't need indentation in following while cycle
179  std::stringstream message_stream;
180  bool header_line = this->print_screen_header(message_stream);
181 
182  // print message
183  std::string segment;
184  std::istringstream istream(scr_stream.str());
185  while(std::getline(istream, segment)) {
186  if (header_line) {
187  header_line = false;
188  } else {
189  message_stream << std::setw(18) << "";
190  }
191  message_stream << segment << "\n";
192  }
193 
194  stream << message_stream.str();
195  stream << std::flush;
196  }
197 }
198 
199 
200 void Logger::print_to_file(std::ofstream& stream, std::stringstream& file_stream, StreamMask mask)
201 {
202  if ( full_streams_mask_() & mask() ) {
203  stream << setfill(' ');
204 
205  // print header
206  std::stringstream message_stream;
207  this->print_file_header(message_stream);
208 
209  // print message
210  std::string segment;
211  std::vector<std::string> segments;
212  std::istringstream istream(file_stream.str());
213  while(std::getline(istream, segment)) {
214  segments.push_back(segment);
215  }
216  if (segments.size() > 1) {
217  message_stream << " - |" << "\n";
218  for (auto seg : segments)
219  message_stream << std::setw(4) << "" << seg << "\n";
220  } else if (segments.size() == 1) {
221  message_stream << " - " << segments[0] << "\n";
222  }
223 
224  stream << message_stream.str();
225  stream << std::flush;
226  }
227 }
228 
229 
230 std::string Logger::compact_file_name(std::string file_name)
231 {
232  // if constant FLOW123D_SOURCE_DIR is defined, we try to erase it from beginning of each CodePoint's filepath
233  #ifdef FLOW123D_SOURCE_DIR
234  string common_path = cmn_prefix(string(FLOW123D_SOURCE_DIR), file_name);
235  file_name.erase (0, common_path.size());
236  #endif
237  return file_name;
238 }
239 
240 bool Logger::print_screen_header(std::stringstream& stream)
241 {
242  stream << date_time_ << " ";
243  if (every_process_) { // rank
244  stringstream rank;
245  rank << "[" << mpi_rank_ << "]";
246  stream << setiosflags(ios::left) << std::setw(5) << rank.str();
247  } else {
248  stream << std::setw(5) << "";
249  }
250 
251  stream << msg_type_string(type_);
252  if (type_ == MsgType::debug) {
253  stream << "(" << compact_file_name(file_name_) << ":" << line_ << ")";
254  }
255  return true;
256 }
257 
258 
259 void Logger::print_file_header(std::stringstream& stream)
260 {
261  stream << "- -" << std::setw(13) << "" << "[ ";
262  stream << msg_type_string(type_, false);
263  if (every_process_) { // add 'E' (only for every_proc) + print rank
264  stream << "E, ";
265  if (mpi_rank_ >= 0) stream << setiosflags(ios::right) << std::setw(4) << mpi_rank_;
266  else stream << "null";
267  } else {
268  stream << " , null";
269  }
270  stream << ", \"" << date_time_ << "\"";
271  stream << ", \"" << compact_file_name(file_name_) << "\", " << line_ << ", \"" << function_ << "\"";
272  stream << " ]\n";
273 }
274 
275 
276 
277 /**
278  * implementation of operators
279  */
280 
282 {
283  // set mask
284  log.streams_mask_ = mask;
286 
287  return log;
288 }
289 
290 
291 Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) )
292 {
293  if ( (log.streams_mask_ & StreamMask::cout)() ) pf(log.cout_stream_);
294  if ( (log.streams_mask_ & StreamMask::cerr)() ) pf(log.cerr_stream_);
295  if ( (log.streams_mask_ & StreamMask::log)() ) pf(log.file_stream_);
296  return log;
297 }
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
int get_mpi_rank()
Returns number of actual process, if MPI is not supported returns -1.
bool no_log_
Turn off logger file output.
static LoggerOptions & get_instance()
Getter of singleton instance object.
bool is_init()
Check if singleton instance object is initialize.
static std::string format_hh_mm_ss()
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:85
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::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:110
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:118
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:64
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:259
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:172
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:230
int mpi_rank_
Actual process (if MPI is supported)
Definition: logger.hh:218
~Logger()
Destructor.
Definition: logger.cc:75
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:240
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:200
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:53
static StreamMask log
Predefined mask of log file output.
Definition: logger.hh:58
StreamMask operator|(const StreamMask &other)
Definition: logger.cc:48
StreamMask operator&(const StreamMask &other)
Definition: logger.cc:43
StreamMask()
Empty constructor.
Definition: logger.hh: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:28
Logger & operator<<(Logger &log, StreamMask mask)
Definition: logger.cc:281
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