Kea  1.5.0
log_formatter.h
Go to the documentation of this file.
1 // Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef LOG_FORMATTER_H
8 #define LOG_FORMATTER_H
9 
10 #include <cstddef>
11 #include <string>
12 #include <iostream>
13 
14 #include <exceptions/exceptions.h>
15 #include <boost/lexical_cast.hpp>
16 #include <log/logger_level.h>
17 
18 namespace isc {
19 namespace log {
20 
25 
26 class FormatFailure : public isc::Exception {
27 public:
28  FormatFailure(const char* file, size_t line, const char* what) :
29  isc::Exception(file, line, what)
30  {}
31 };
32 
33 
38 
40 public:
41  MismatchedPlaceholders(const char* file, size_t line, const char* what) :
42  isc::Exception(file, line, what)
43  {}
44 };
45 
46 
52 void
53 checkExcessPlaceholders(std::string* message, unsigned int placeholder);
54 
61 void
62 replacePlaceholder(std::string* message, const std::string& replacement,
63  const unsigned placeholder);
64 
102 template<class Logger> class Formatter {
103 private:
107  mutable Logger* logger_;
108 
110  Severity severity_;
111 
113  std::string* message_;
114 
116  unsigned nextPlaceholder_;
117 
118 
119 public:
134  Formatter(const Severity& severity = NONE, std::string* message = NULL,
135  Logger* logger = NULL) :
136  logger_(logger), severity_(severity), message_(message),
137  nextPlaceholder_(0)
138  {
139  }
140 
146  Formatter(const Formatter& other) :
147  logger_(other.logger_), severity_(other.severity_),
148  message_(other.message_), nextPlaceholder_(other.nextPlaceholder_)
149  {
150  other.logger_ = NULL;
151  }
152 
154  //
157  if (logger_) {
158  try {
159  checkExcessPlaceholders(message_, ++nextPlaceholder_);
160  logger_->output(severity_, *message_);
161  } catch (...) {
162  // Catch and ignore all exceptions here.
163  }
164  delete message_;
165  }
166  }
167 
172  Formatter& operator =(const Formatter& other) {
173  if (&other != this) {
174  logger_ = other.logger_;
175  severity_ = other.severity_;
176  message_ = other.message_;
177  nextPlaceholder_ = other.nextPlaceholder_;
178  other.logger_ = NULL;
179  }
180 
181  return *this;
182  }
183 
191  template<class Arg> Formatter& arg(const Arg& value) {
192  if (logger_) {
193  try {
194  return (arg(boost::lexical_cast<std::string>(value)));
195  } catch (const boost::bad_lexical_cast& ex) {
196  // The formatting of the log message got wrong, we don't want
197  // to output it.
198  deactivate();
199  // A bad_lexical_cast during a conversion to a string is
200  // *extremely* unlikely to fail. However, there is nothing
201  // in the documentation that rules it out, so we need to handle
202  // it. As it is a potentially very serious problem, throw the
203  // exception detailing the problem with as much information as
204  // we can. (Note that this does not include 'value' -
205  // boost::lexical_cast failed to convert it to a string, so an
206  // attempt to do so here would probably fail as well.)
207  isc_throw(FormatFailure, "bad_lexical_cast in call to "
208  "Formatter::arg(): " << ex.what());
209  }
210  } else {
211  return (*this);
212  }
213  }
214 
218  Formatter& arg(const std::string& arg) {
219  if (logger_) {
220  // Note that this method does a replacement and returns the
221  // modified string. If there are multiple invocations of arg() (e.g.
222  // logger.info(msgid).arg(xxx).arg(yyy)...), each invocation
223  // operates on the string returned by the previous one. This
224  // sequential operation means that if we had a message like "%1 %2",
225  // and called .arg("%2").arg(42), we would get "42 42"; the first
226  // call replaces the %1" with "%2" and the second replaces all
227  // occurrences of "%2" with 42. (Conversely, the sequence
228  // .arg(42).arg("%1") would return "42 %1" - there are no recursive
229  // replacements).
230  try {
231  replacePlaceholder(message_, arg, ++nextPlaceholder_ );
232  }
233  catch (...) {
234  // Something went wrong here, the log message is broken, so
235  // we don't want to output it, nor we want to check all the
236  // placeholders were used (because they won't be).
237  deactivate();
238  throw;
239  }
240  }
241  return (*this);
242  }
243 
252  void deactivate() {
253  if (logger_) {
254  delete message_;
255  message_ = NULL;
256  logger_ = NULL;
257  }
258  }
259 };
260 
261 }
262 }
263 
264 #endif
isc::log::Logger
Logger Class.
Definition: log/logger.h:143
isc::log::FormatFailure::FormatFailure
FormatFailure(const char *file, size_t line, const char *what)
Definition: log_formatter.h:28
isc::log::Formatter::arg
Formatter & arg(const std::string &arg)
String version of arg.
Definition: log_formatter.h:218
logger_level.h
isc::log::Severity
Severity
Severity Levels.
Definition: logger_level.h:23
isc::log::MismatchedPlaceholders
Mismatched Placeholders.
Definition: log_formatter.h:39
isc::log::NONE
@ NONE
Definition: logger_level.h:30
isc::log::FormatFailure
Format Failure.
Definition: log_formatter.h:26
isc::log::Formatter::deactivate
void deactivate()
Turn off the output of this logger.
Definition: log_formatter.h:252
isc::log::Formatter::operator=
Formatter & operator=(const Formatter &other)
Assignment operator.
Definition: log_formatter.h:172
isc::log::checkExcessPlaceholders
void checkExcessPlaceholders(string *message, unsigned int placeholder)
Internal excess placeholder checker.
Definition: log_formatter.cc:49
isc::Exception
This is a base class for exceptions thrown from the DNS library module.
Definition: exceptions/exceptions.h:23
isc::log::replacePlaceholder
void replacePlaceholder(string *message, const string &arg, const unsigned placeholder)
The internal replacement routine.
Definition: log_formatter.cc:23
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition: exceptions/exceptions.cc:32
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::asiodns::logger
isc::log::Logger logger("asiodns")
Use the ASIO logger.
Definition: asiodns/logger.h:15
isc::log::Formatter::~ Formatter
~ Formatter()
Destructor.
Definition: log_formatter.h:156
exceptions.h
isc::log::Formatter::Formatter
Formatter(const Formatter &other)
Copy constructor.
Definition: log_formatter.h:146
isc::log::Formatter::arg
Formatter & arg(const Arg &value)
Replaces another placeholder.
Definition: log_formatter.h:191
isc::log::Formatter::Formatter
Formatter(const Severity &severity=NONE, std::string *message=NULL, Logger *logger=NULL)
Constructor of "active" formatter.
Definition: log_formatter.h:134
isc::log::Formatter
The log message formatter.
Definition: log_formatter.h:102
isc::log::MismatchedPlaceholders::MismatchedPlaceholders
MismatchedPlaceholders(const char *file, size_t line, const char *what)
Definition: log_formatter.h:41