Browse Source

[trac901] The formatter interface

But it's mostly empty for now.
Michal 'vorner' Vaner 14 years ago
parent
commit
cf46f37033
2 changed files with 109 additions and 0 deletions
  1. 1 0
      src/lib/log/Makefile.am
  2. 108 0
      src/lib/log/log_formatter.h

+ 1 - 0
src/lib/log/Makefile.am

@@ -21,6 +21,7 @@ liblog_la_SOURCES += message_initializer.cc message_initializer.h
 liblog_la_SOURCES += message_reader.cc message_reader.h
 liblog_la_SOURCES += message_types.h
 liblog_la_SOURCES += root_logger_name.cc root_logger_name.h
+liblog_la_SOURCES += log_formatter.h
 
 EXTRA_DIST  = README
 EXTRA_DIST += messagedef.mes

+ 108 - 0
src/lib/log/log_formatter.h

@@ -0,0 +1,108 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __LOG_FORMATTER_H
+#define __LOG_FORMMATER_H
+
+#include <string>
+
+namespace isc {
+namespace log {
+
+///
+/// \brief The log message formatter
+///
+/// This class allows us to format logging messages conveniently. We
+/// call something like logger.warn(WARN_MSG).arg(15).arg(dnsMsg). This
+/// outputs some text with placeholders replaced by the arguments, if
+/// the logging verbosity is at WARN level or more.
+///
+/// To make this work, we use the Formatter. The warn (or whatever logging
+/// function) returns a Formatter object. That one holds the string to be
+/// output with the placeholders. It also remembers if there should be any
+/// output at all (eg. if the logging is enabled for this level). When there's
+/// no .arg call on the object, it is destroyed right away and we use the
+/// destructor to output the text (but only in case we should output anything).
+///
+/// If there's an .arg call, it replaces a placeholder with the argument
+/// converted to string and produces another Formatter. We mark the current
+/// Formatter so it won't output anything in it's destructor and the task
+/// to do the output is moved onto the new object. Again, the last one in
+/// the chain is destroyed without any modification and does the real output.
+///
+/// Of course, if the logging is turned off, we don't bother with any replacing
+/// and just return new empty Formatter. As everything here is in the header
+/// file, compiler should be able to easily optimise most of the work with
+/// creating and destroying objects and simply do the replacing only.
+///
+/// User of logging code should not really care much about this class, only
+/// call the .arg method to generate the correct output.
+template<class Logger> class Formatter {
+private:
+    /// \brief The logger we will use to output the final message
+    Logger& logger_;
+    /// \brief Prefix (eg. "ERROR", "DEBUG" or like that)
+    const char* prefix_;
+    /// \brief The messages with %1, %2... placeholders
+    const std::string message_;
+    /// \brief Which will be the next placeholder to replace
+    const unsigned nextPlaceholder_;
+    /// \brief Should we do output?
+    bool active_;
+public:
+    /// \brief Constructor of "active" formatter
+    ///
+    /// This will create a formatter in active mode -- the one when it
+    /// will generate output.
+    ///
+    /// \param prefix The prefix, like "ERROR" or "DEBUG"
+    /// \param message The message with placeholders
+    /// \param nextPlaceholder It is the number of next placeholder which
+    ///     should be replaced. It should be called with 1, higher numbers
+    ///     are used internally in the chain.
+    /// \param logger The logger where the final output will go.
+    Formatter(const char* prefix, const std::string& message,
+              const unsigned& nextPlaceholder, Logger& logger) :
+        prefix_(prefix), message_(message),
+        nextPlaceholder_(nextPlaceholder), logger_(logger),
+        active_(true)
+    {
+    }
+    /// \brief Constructor of "inactive" formatter
+    ///
+    /// This will create a formatter that produces no output.
+    Formatter() :
+        active_(false)
+    {
+    }
+    /// \brief Destructor.
+    //
+    /// This is the place where output happens if the formatter is active.
+    ~ Formatter() {
+
+    }
+    /// \brief Replaces another placeholder
+    ///
+    /// Replaces another placeholder and returns a new formatter with it.
+    /// Deactivates the current formatter. In case the formatter is not active,
+    /// only produces another inactive formatter.
+    template<class Arg> Formatter arg(const Arg& arg) {
+
+    }
+};
+
+}
+}
+
+#endif