Flow123d  release_2.2.0-23-g01927c6
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 bool Logger::print_screen_header(std::ostream& stream, std::stringstream& scr_stream)
223 {
224  stream << date_time_ << " ";
225  if (every_process_) { // rank
226  stringstream rank;
227  rank << "[" << mpi_rank_ << "]";
228  stream << setiosflags(ios::left) << std::setw(5) << rank.str();
229  } else {
230  stream << std::setw(5) << "";
231  }
232 
233  if (type_ != MsgType::message) { // type of message (besides Message)
234  stream << msg_type_string(type_) << " ";
235  return true; // logger message starts at new line
236  } else {
237  return true; // logger message continues on the same line as header
238  }
239 }
240 
241 
242 void Logger::print_file_header(std::ofstream& stream, std::stringstream& file_stream)
243 {
244  stream << "- -" << std::setw(13) << "" << "[ ";
245  stream << msg_type_string(type_, false);
246  if (every_process_) { // add 'E' (only for every_proc) + print rank
247  stream << "E, ";
248  if (mpi_rank_ >= 0) stream << setiosflags(ios::right) << std::setw(4) << mpi_rank_;
249  else stream << "null";
250  } else {
251  stream << " , null";
252  }
253  stream << ", \"" << date_time_ << "\"";
254  // if constant FLOW123D_SOURCE_DIR is defined, we try to erase it from beginning of each CodePoint's filepath
255  #ifdef FLOW123D_SOURCE_DIR
256  string common_path = cmn_prefix(string(FLOW123D_SOURCE_DIR), file_name_);
257  file_name_.erase (0, common_path.size());
258  #endif
259  stream << ", \"" << file_name_ << "\", " << line_ << ", \"" << function_ << "\"";
260  stream << " ]\n";
261 }
262 
263 
264 
265 /**
266  * implementation of operators
267  */
268 
270 {
271  // set mask
272  log.streams_mask_ = mask;
274 
275  return log;
276 }
277 
278 
279 Logger &operator<<(Logger & log, std::ostream & (*pf) (std::ostream &) )
280 {
281  if ( (log.streams_mask_ & StreamMask::cout)() ) pf(log.cout_stream_);
282  if ( (log.streams_mask_ & StreamMask::cerr)() ) pf(log.cerr_stream_);
283  if ( (log.streams_mask_ & StreamMask::log)() ) pf(log.file_stream_);
284  return log;
285 }
Class for storing logger messages.
Definition: logger.hh:134
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:242
static StreamMask cout
Predefined mask of std::cout output.
Definition: logger.hh:49
int operator()(void)
Definition: logger.cc:54
std::stringstream cout_stream_
Store messages printed to cout output stream.
Definition: logger.hh:188
~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:199
StreamMask()
Empty constructor.
Definition: logger.hh:41
friend Logger & operator<<(Logger &log, const T &x)
Definition: logger.hh:216
#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:189
std::string function_
Actual function.
Definition: logger.hh:195
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:52
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:55
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:38
std::string date_time_
Actual date and time.
Definition: logger.hh:197
int mask_
Definition: logger.hh:67
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:193
int get_mpi_rank()
Returns number of actual process, if MPI is not supported returns -1.
int line_
Actual line.
Definition: logger.hh:196
std::stringstream file_stream_
Store messages printed to file.
Definition: logger.hh:190
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:200
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:222
std::string file_name_
Actual file.
Definition: logger.hh:194
int mpi_rank_
Actual process (if MPI is supported)
Definition: logger.hh:198
MsgType type_
Type of message.
Definition: logger.hh:192
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:137