LSSTApplications  10.0+286,10.0+36,10.0+46,10.0-2-g4f67435,10.1+152,10.1+37,11.0,11.0+1,11.0-1-g47edd16,11.0-1-g60db491,11.0-1-g7418c06,11.0-2-g04d2804,11.0-2-g68503cd,11.0-2-g818369d,11.0-2-gb8b8ce7
LSSTDataManagementBasePackage
Log.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2008, 2009, 2010 LSST Corporation.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <http://www.lsstcorp.org/LegalNotices/>.
21  */
22 
28 #include <cstring>
29 #include <cstdio>
30 
31 #include "lsst/pex/logging/Log.h"
33 
34 #include <boost/shared_ptr.hpp>
35 
36 namespace lsst {
37 namespace pex {
38 namespace logging {
39 
40 //@cond
41 
42 using std::string;
43 using std::list;
44 using std::ostream;
45 using boost::shared_ptr;
47 
49 // Log
51 
52 /*
53  * the conventional importance level for messages that aid in debugging.
54  * This value is set to -10 with the intention that messages with
55  * negative importance levels (or more precisely, >= -10) will be printed
56  * when the threshold is set to this value.
57  */
58 const int Log::DEBUG = -10;
59 
60 /*
61  * the conventional importance level for messages that are informational
62  * and which report on normal behavior. The value is set to 0 with the
63  * intention that this is the default threshold for logs and their
64  * destinations.
65  */
66 const int Log::INFO = 0;
67 
68 /*
69  * the conventional importance level for messages that warn about
70  * abnormal but non-fatal behavior. The value is set to 10.
71  */
72 const int Log::WARN = 10;
73 
74 /*
75  * the conventional importance level for messages that report on fatal
76  * behavior. The value is set to 20. Note that the logging module
77  * makes no attempt to shutdown execution or other wise affect control
78  * flow when a message having a importance exceeding this level.
79  */
80 const int Log::FATAL = 20;
81 
82 /*
83  * a magic threshold value that indicates that a threshold of a Log
84  * should be set to its nearest ancestor
85  */
87 
88 /*
89  * create a null log. This constructor should
90  * not normally be employed to obtain a Log; the static getDefaultLog()
91  * method should be used instead. This is provided primarily for
92  * subclasses and containers that require a no-arg constructor.
93  * @param threshold the initial importance threshold for this log
94  * @param name the initial name for this log. An empty string
95  * (the default) denotes a root log.
96  */
97 Log::Log(const int threshold, const string& name)
98  : _threshold(threshold), _defShowAll(new bool(false)), _myShowAll(),
99  _name(name), _thresholds(new threshold::Memory(Log::_sep)),
100  _destinations(), _preamble(new PropertySet())
101 {
102  _thresholds->setRootThreshold(threshold);
103  if (name.length() > 0) _thresholds->setThresholdFor(name, threshold);
104  _myShowAll = _defShowAll;
105  completePreamble();
106 }
107 
108 /*
109  * create a fully configured Log. This constructor is
110  * not normally employed to obtain a Log; the static getDefaultLog()
111  * method or the createChildLog() method of should be used instead.
112  * @param destinations the list of LogDestinations to attach to this
113  * Log.
114  * @param preamble a list of data properties that should be included
115  * with every recorded message to the Log. This
116  * constructor will automatically a property ("LOG")
117  * giving the Log name.
118  * @param name the name to give this log. By default, the
119  * name will be an empty string, signifying a
120  * root log.
121  * @param threshold the importance threshold to assign to this Log.
122  * Messages sent to this log must have a importance
123  * level equal to or greater than this value to
124  * be recorded. (Note that thresholds associated
125  * with destinations have their own thresholds that
126  * will override this one.)
127  */
128 Log::Log(const list<shared_ptr<LogDestination> > &destinations,
129  const PropertySet &preamble,
130  const string &name, const int threshold, bool defaultShowAll)
131  : _threshold(threshold), _defShowAll(new bool(defaultShowAll)),
132  _myShowAll(), _name(name), _thresholds(new threshold::Memory(Log::_sep)),
133  _destinations(destinations), _preamble(preamble.deepCopy())
134 {
135  _thresholds->setRootThreshold(threshold);
136  if (name.length() > 0) _thresholds->setThresholdFor(name, threshold);
137  completePreamble();
138 }
139 
140 /*
141  * create a copy
142  */
143 Log::Log(const Log& that)
144  : _threshold(that._threshold), _defShowAll(that._defShowAll),
145  _myShowAll(that._myShowAll), _name(that._name),
146  _thresholds(that._thresholds), _destinations(that._destinations),
147  _preamble(that._preamble->deepCopy())
148 { }
149 
150 /*
151  * delete this Log
152  */
153 Log::~Log() { }
154 
155 /*
156  * create a copy
157  */
158 Log& Log::operator=(const Log& that) {
159  _threshold = that._threshold;
160  _defShowAll = that._defShowAll;
161  _myShowAll = that._myShowAll;
162  _name = that._name;
163  _thresholds = that._thresholds;
164  _destinations = that._destinations;
165  _preamble = that._preamble->deepCopy();
166  return *this;
167 }
168 
169 void Log::completePreamble() {
170  _preamble->set<string>("LOG", _name);
171 }
172 
173 /*
174  * create a child of a given Log
175  * @param parent the Log that will serve as its parent.
176  * @param childName the name of the child log, relative to the given
177  * parent. The full child name will be
178  * constructed from this name prepended by the
179  * parent's name and a ".". If the parent Log
180  * is a root Log, then the "." is not prepended.
181  * @param threshold the threshold for the new child Log. The default
182  * value is Log::INHERIT_THRESHOLD which means that
183  * it will be set to the threshold of the parent.
184  */
185 Log::Log(const Log& parent, const string& childName, int threshold)
186  : _threshold(threshold), _defShowAll(parent._defShowAll),
187  _myShowAll(), _name(parent.getName()), _thresholds(parent._thresholds),
188  _destinations(parent._destinations),
189  _preamble(parent._preamble->deepCopy())
190 {
191  if (_name.length() > 0) _name += _sep;
192  _name += childName;
193 
194  if (_threshold > INHERIT_THRESHOLD)
195  _thresholds->setThresholdFor(_name, _threshold);
196 
197  completePreamble();
198 }
199 
200 /*
201  * set the importance threshold for a child Log. When a child Log of the
202  * same name is created, it will be assigned this threshold. Any existing
203  * Log object with name that has already explicitly set its importance
204  * threshold will not be affected; however, those that are set to inherit
205  * the threshold will be.
206  * @param name the relative name of the child log. This cannot be an
207  * empty string.
208  * @param threshold the importance threshold to set Logs with this name to.
209  */
210 void Log::setThresholdFor(const string& name, int threshold) {
211  string fullname(getName());
212  if (fullname.length() > 0) fullname += _sep;
213  fullname += name;
214  _thresholds->setThresholdFor(fullname, threshold);
215 }
216 
217 int Log::getThresholdFor(const string& name) const {
218  string fullname(getName());
219  if (_name.length() > 0) fullname += _sep;
220  return _thresholds->getThresholdFor(fullname+name);
221 }
222 
223 /*
224  * create a child Log. A child Log is a Log that is attached to a sub
225  * channel of this log. Its full name will be formed from this parent's
226  * name followed by a dot-delimiter (".") followed by the childName
227  * parameter (e.g. "parentName.childName"), unless the parent is the
228  * root Log (whose name is an empty string), in which case the full child
229  * name will just be the value of childName.
230  *
231  * This method will create a new Log object and return it as a pointer.
232  * The caller is responsible for deleting the object.
233  *
234  * If the threshold for the child Log is not provided, it is set to the
235  * threshold of this Log, its parent.
236  *
237  * If the threshold for the child Log is not provided, it is set to the
238  * threshold the channel had the last it was accessed. If this is the
239  * first time the channel will be used it will be set to the current
240  * threshold of its parent.
241  *
242  * @param childName the name of the new child log relative to this one.
243  * The full name of the child log will be the parent's
244  * name followed by a "." (if the length of the parent's
245  * name is non-zero), followed by the given child name.
246  * This cannot be an empty string.
247  * @param threshold the importance threshold to set for this Log. If not
248  * provided, it will default to the threshold of this
249  * log, its parent.
250  */
251 Log *Log::createChildLog(const string& childName, int threshold) const {
252  return new Log(*this, childName, threshold);
253 }
254 
255 /*
256  * send a message to the log
257  * @param importance how loud the message should be
258  * @param message a simple bit of text to send in the message
259  * @param properties a list of properties to include in the message.
260  */
261 void Log::log(int importance, const string& message,
262  const PropertySet& properties)
263 {
264  int threshold = getThreshold();
265  if (importance < threshold)
266  return;
267  LogRecord rec(threshold, importance, *_preamble, willShowAll());
268  rec.addComment(message);
269  rec.addProperties(properties);
270  send(rec);
271 }
272 
273 /*
274  * send a simple message to the log
275  * @param importance how loud the message should be
276  * @param message a simple bit of text to send in the message
277  */
278 void Log::log(int importance, const string& message) {
279  int threshold = getThreshold();
280  if (importance < threshold)
281  return;
282  LogRecord rec(threshold, importance, *_preamble, willShowAll());
283  rec.addComment(message);
284  send(rec);
285 }
286 
287 /*
288  * send a simple, formatted message. Use of this function tends to
289  * perform better than log(int, boost::format) as the formatting is
290  * only done if the message will actually get recorded.
291  * @param importance how loud the message should be
292  * @param fmt a printf-style format string
293  * @param ... the inputs to the formatting.
294  */
295 void Log::format(int importance, const char *fmt, ...) {
296  int threshold = getThreshold();
297  if (importance < threshold) return;
298  va_list ap;
299  va_start(ap, fmt);
300  _format(importance, fmt, ap);
301  va_end(ap);
302 }
303 
304 void Log::_format(int importance, const char* fmt, va_list ap) {
305  va_list aq;
306  va_copy(aq, ap);
307  // find out how long the formatted string will be
308  const int len = vsnprintf(NULL, 0, fmt, ap) + 1; // "+ 1" for the '\0'
309  va_end(ap);
310  // allocate a string of the appropriate length
311  char msg[len];
312  (void)vsnprintf(msg, len, fmt, aq);
313  va_end(aq);
314  log(importance, msg);
315 }
316 
317 /*
318  * format and send a message using a variable argument list. This does
319  * not check the Log threshold; it assumes this has already been done.
320  */
321 void Log::_send(int threshold, int importance, const char *fmt, va_list ap) {
322  const int len = strlen(fmt) + 100; // guess the length
323  char message[len];
324  vsnprintf(message, len, fmt, ap);
325 
326  LogRecord rec(threshold, importance, *_preamble, willShowAll());
327  rec.addComment(message);
328  send(rec);
329 }
330 
331 
332 /*
333  * send a fully formed LogRecord to the log destinations
334  */
335 void Log::send(const LogRecord& record) {
336  if (record.getImportance() < getThreshold())
337  return;
338  list<shared_ptr<LogDestination> >::iterator i;
339  for(i = _destinations.begin(); i != _destinations.end(); i++) {
340  (*i)->write(record);
341  }
342 }
343 
344 /*
345  * add a destination to this log. The destination stream will included
346  * in all child Logs created from this log after a call to this function.
347  * All previously created logs, including ancestor logs, will be
348  * unaffected. The IndentedFormatter format will be used with this new
349  * destination.
350  * @param destination the stream to send messages to
351  * @param threshold the importance threshold to use to filter messages
352  * sent to the stream.
353  */
354 void Log::addDestination(ostream& destination, int threshold) {
355  shared_ptr<LogFormatter> frmtr(new IndentedFormatter());
356  addDestination(destination, threshold, frmtr);
357 }
358 
359 /*
360  * add a destination to this log. The destination stream will included
361  * in all child Logs created from this log after a call to this function.
362  * All previously created logs, including ancestor logs, will be
363  * unaffected.
364  * @param destination a pointer to the stream to send messages to. The
365  * caller is responsible for ensuring that the
366  * stream is neither closed nor its memory freed
367  * for the life of this Log.
368  * @param threshold the importance threshold to use to filter messages
369  * sent to the stream.
370  * @param formatter the log formatter to use.
371  */
372 void Log::addDestination(ostream& destination, int threshold,
373  const shared_ptr<LogFormatter> &formatter)
374 {
375  shared_ptr<LogDestination> dest(
376  new LogDestination(&destination, formatter, threshold));
377  addDestination(dest);
378 }
379 
380 Log& Log::getDefaultLog() {
381  if (defaultLog == 0) {
382  Log::setDefaultLog(new ScreenLog());
383  }
384 
385  return *defaultLog;
386 }
387 
388 void Log::setDefaultLog(Log *deflog) {
389  if (defaultLog != 0) delete defaultLog;
390  defaultLog = deflog;
391  if (defaultLog != 0) {
392  defaultLog->markPersistent();
393  }
394 }
395 
396 void Log::createDefaultLog(const list<shared_ptr<LogDestination> >& dests,
397  const PropertySet& preamble,
398  const string& name, const int threshold)
399 {
400  Log::setDefaultLog(new Log(dests, preamble, name, threshold));
401 }
402 
403 void Log::closeDefaultLog() { setDefaultLog(0); }
404 
405 Log *Log::defaultLog = 0;
406 const string Log::_sep(".");
407 
408 LogRec::~LogRec() {
409  if (! _sent) *this << endr;
410 }
411 
412 // this used to be inlined but it was causing problems in SWIG/Python-land.
413 // I'm not sure that the problem has really been solved by un-inlining it
414 // or just hidden it away.
415 LogRec& LogRec::operator<<(const string& comment) {
416  addComment(comment);
417  return *this;
418 }
419 
420 // @endcond
421 
422 }}} // end lsst::pex::logging
423 
table::Key< std::string > name
Definition: ApCorrMap.cc:71
std::string const & _name
Definition: Mask.cc:678
static const int WARN
Definition: Log.h:177
std::ostream & operator<<(std::ostream &os, CameraPoint const &cameraPoint)
Definition: CameraPoint.cc:29
lsst::daf::base::PropertySet PropertySet
Definition: Wcs.cc:58
static const int INHERIT_THRESHOLD
Definition: Log.h:183
static const int INFO
Definition: Log.h:171
static const int FATAL
Definition: Log.h:191
definition of the ScreenLog class
Class for storing generic metadata.
Definition: PropertySet.h:82
static const int DEBUG
Definition: Log.h:163
Log(const int threshold=INFO, const std::string &name="")
static void log(std::string const &loggername, log4cxx::LevelPtr level, std::string const &filename, std::string const &funcname, unsigned int lineno, char const *fmt,...)
Definition: Log.cc:360