The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
log.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 by David White <[email protected]>
3  2004 - 2015 by Guillaume Melquiond <[email protected]>
4  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 /**
17  * @file
18  * Standard logging facilities (implementation).
19  * See also the command line switches --logdomains and --log-@<level@>="domain".
20  */
21 
22 #include "game_errors.hpp"
23 #include "global.hpp"
24 
25 #include "log.hpp"
26 
27 #include <boost/date_time.hpp>
28 
29 #include <map>
30 #include <sstream>
31 #include <ctime>
32 
33 namespace {
34 
35 class null_streambuf : public std::streambuf
36 {
37  virtual int overflow(int c) { return std::char_traits< char >::not_eof(c); }
38 public:
39  null_streambuf() {}
40 };
41 
42 } // end anonymous namespace
43 
44 static std::ostream null_ostream(new null_streambuf);
45 static int indent = 0;
46 static bool timestamp = true;
47 static bool precise_timestamp = false;
48 
49 static boost::posix_time::time_facet facet("%Y%m%d %H:%M:%S%F ");
50 static std::ostream *output_stream = nullptr;
51 
52 static std::ostream& output()
53 {
54  if(output_stream) {
55  return *output_stream;
56  }
57  return std::cerr;
58 }
59 
60 namespace lg {
61 
63  : old_stream_(output_stream)
64 {
66 }
67 
69 {
71 }
72 
73 typedef std::map<std::string, int> domain_map;
74 static domain_map *domains;
75 static int strict_level_ = -1;
76 void timestamps(bool t) { timestamp = t; }
77 void precise_timestamps(bool pt) { precise_timestamp = pt; }
78 
80 {
81  static logger lg("error", 0);
82  return lg;
83 }
84 
86 {
87  static logger lg("warning", 1);
88  return lg;
89 }
90 
92 {
93  static logger lg("info", 2);
94  return lg;
95 }
96 
98 {
99  static logger lg("debug", 3);
100  return lg;
101 }
102 
104 {
105  static log_domain dom("general");
106  return dom;
107 }
108 
110  : domain_(nullptr)
111 {
112  // Indirection to prevent initialization depending on link order.
113  if (!domains) domains = new domain_map;
114  domain_ = &*domains->insert(logd(name, 1)).first;
115 }
116 
118 {
119  std::string::size_type s = name.size();
120  if (name == "all") {
121  for(logd &l : *domains) {
122  l.second = severity;
123  }
124  } else if (s > 2 && name.compare(s - 2, 2, "/*") == 0) {
125  for(logd &l : *domains) {
126  if (l.first.compare(0, s - 1, name, 0, s - 1) == 0)
127  l.second = severity;
128  }
129  } else {
130  domain_map::iterator it = domains->find(name);
131  if (it == domains->end())
132  return false;
133  it->second = severity;
134  }
135  return true;
136 }
138  return set_log_domain_severity(name, lg.get_severity());
139 }
140 
142 {
143  domain_map::iterator it = domains->find(name);
144  if (it == domains->end())
145  return false;
146  severity = it->second;
147  return true;
148 }
149 
151 {
152  std::ostringstream res;
153  for(logd &l : *domains) {
154  if(l.first.find(filter) != std::string::npos)
155  res << l.first << "\n";
156  }
157  return res.str();
158 }
159 
161  strict_level_ = severity;
162 }
163 
166 }
167 
168 static bool strict_threw_ = false;
169 
170 bool broke_strict() {
171  return strict_threw_;
172 }
173 
174 std::string get_timestamp(const time_t& t, const std::string& format) {
175  char buf[100] = {0};
176  tm* lt = localtime(&t);
177  if (lt) {
178  strftime(buf, 100, format.c_str(), lt);
179  }
180  return buf;
181 }
182 std::string get_timespan(const time_t& t) {
183  char buf[100];
184  // There doesn't seem to be any library function for this
185  const time_t minutes = t / 60;
186  const time_t days = minutes / 60 / 24;
187  if(t <= 0) {
188  strncpy(buf, "expired", 100);
189  } else if(minutes == 0) {
190  snprintf(buf, 100, "00:00:%02ld", t);
191  } else if(days == 0) {
192  snprintf(buf, 100, "%02ld:%02ld", minutes / 60, minutes % 60);
193  } else {
194  snprintf(buf, 100, "%ld %02ld:%02ld", days, (minutes / 60) % 24, minutes % 60);
195  }
196  return buf;
197 }
198 
199 static void print_precise_timestamp(std::ostream & out)
200 {
201  facet.put(
202  std::ostreambuf_iterator<char>(out),
203  out,
204  ' ',
205  boost::posix_time::microsec_clock::local_time());
206 }
207 
208 std::ostream &logger::operator()(log_domain const &domain, bool show_names, bool do_indent) const
209 {
210  if (severity_ > domain.domain_->second) {
211  return null_ostream;
212  } else {
213  if (!strict_threw_ && (severity_ <= strict_level_)) {
214  std::stringstream ss;
215  ss << "Error (strict mode, strict_level = " << strict_level_ << "): wesnoth reported on channel " << name_ << " " << domain.domain_->first;
216  std::cerr << ss.str() << std::endl;
217  strict_threw_ = true;
218  }
219  std::ostream& stream = output();
220  if(do_indent) {
221  for(int i = 0; i != indent; ++i)
222  stream << " ";
223  }
224  if (timestamp) {
225  if(precise_timestamp) {
226  print_precise_timestamp(stream);
227  } else {
228  stream << get_timestamp(time(nullptr));
229  }
230  }
231  if (show_names) {
232  stream << name_ << ' ' << domain.domain_->first << ": ";
233  }
234  return stream;
235  }
236 }
237 
238 void scope_logger::do_log_entry(log_domain const &domain, const std::string& str)
239 {
240  output_ = &debug()(domain, false, true);
241  str_ = str;
242  ticks_ = boost::posix_time::microsec_clock::local_time();
243  (*output_) << "{ BEGIN: " << str_ << "\n";
244  ++indent;
245 }
246 
248 {
249  const long ticks = (boost::posix_time::microsec_clock::local_time() - ticks_).total_milliseconds();
250  --indent;
251  do_indent();
252  if (timestamp) (*output_) << get_timestamp(time(nullptr));
253  (*output_) << "} END: " << str_ << " (took " << ticks << "ms)\n";
254 }
255 
257 {
258  for(int i = 0; i != indent; ++i)
259  (*output_) << " ";
260 }
261 
262 std::stringstream& wml_error()
263 {
264  static std::stringstream lg;
265  return lg;
266 }
267 
268 } // end namespace lg
269 
static int strict_level_
Definition: log.cpp:75
size_t strftime(char *str, size_t count, const std::string &format, const std::tm *time)
Definition: strftime.cpp:132
char const * name_
Definition: log.hpp:115
static domain_map * domains
Definition: log.cpp:74
static void print_precise_timestamp(std::ostream &out)
Definition: log.cpp:199
std::string get_timestamp(const time_t &t, const std::string &format)
Definition: log.cpp:174
const GLfloat * c
Definition: glew.h:12741
std::ostream & operator()(log_domain const &domain, bool show_names=true, bool do_indent=false) const
Definition: log.cpp:208
logger & info()
Definition: log.cpp:91
void timestamps(bool t)
Definition: log.cpp:76
std::string str_
Definition: log.hpp:150
void do_indent() const
Definition: log.cpp:256
int get_severity() const
Definition: log.hpp:127
GLdouble GLdouble t
Definition: glew.h:1366
static std::ostream * output_stream
Definition: log.cpp:50
std::pair< const std::string, int > logd
Definition: log.hpp:94
GLdouble l
Definition: glew.h:6966
bool broke_strict()
Definition: log.cpp:170
GLuint GLuint stream
Definition: glew.h:5239
bool set_log_domain_severity(std::string const &name, int severity)
Definition: log.cpp:117
static std::ostream & output()
Definition: log.cpp:52
void do_log_entry(log_domain const &domain, const std::string &str)
Definition: log.cpp:238
static bool precise_timestamp
Definition: log.cpp:47
GLenum GLuint GLsizei const char * buf
Definition: glew.h:2498
log_domain(char const *name)
Definition: log.cpp:109
int severity_
Definition: log.hpp:116
ptime ticks_
Definition: log.hpp:148
std::ostream * old_stream_
The previously set redirection.
Definition: log.hpp:91
std::ostream * output_
Definition: log.hpp:149
logger & debug()
Definition: log.cpp:97
static int indent
Definition: log.cpp:45
GLenum severity
Definition: glew.h:2497
log_domain & general()
Definition: log.cpp:103
std::map< std::string, int > domain_map
Definition: log.cpp:73
Definition: pump.hpp:42
GLuint res
Definition: glew.h:9258
static boost::posix_time::time_facet facet("%Y%m%d %H:%M:%S%F ")
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:262
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glew.h:1222
logger & err()
Definition: log.cpp:79
void set_strict_severity(int severity)
Definition: log.cpp:160
size_t i
Definition: function.cpp:1057
std::string get_timespan(const time_t &t)
Definition: log.cpp:182
bool get_log_domain_severity(std::string const &name, int &severity)
Definition: log.cpp:141
tredirect_output_setter(std::ostream &stream)
Constructor.
Definition: log.cpp:62
GLuint const GLchar * name
Definition: glew.h:1782
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glew.h:3448
static bool strict_threw_
Definition: log.cpp:168
logger & warn()
Definition: log.cpp:85
static bool timestamp
Definition: log.cpp:46
std::string list_logdomains(const std::string &filter)
Definition: log.cpp:150
Standard logging facilities (interface).
static std::ostream null_ostream(new null_streambuf)
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
GLdouble s
Definition: glew.h:1358
GLsizei const GLcharARB ** string
Definition: glew.h:4503
void do_log_exit()
Definition: log.cpp:247
void precise_timestamps(bool pt)
Definition: log.cpp:77
logd * domain_
Definition: log.hpp:99