Utils/Logger: Add more consistent and flexible configuration options to SyslogUDPTarg...
g0dil [Thu, 11 Dec 2008 12:50:55 +0000 (12:50 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1016 270642c3-0616-0410-b53a-bc976706d245

Utils/Logger/IOStreamTarget.cc
Utils/Logger/IOStreamTarget.cci
Utils/Logger/IOStreamTarget.hh
Utils/Logger/IOStreamTarget.ih [new file with mode: 0644]
Utils/Logger/SyslogUDPTarget.cc
Utils/Logger/SyslogUDPTarget.cci [new file with mode: 0644]
Utils/Logger/SyslogUDPTarget.hh
Utils/Logger/SyslogUDPTarget.test.cc

index 2588059..d1b30e8 100644 (file)
     \brief IOStreamTarget non-inline non-template implementation */
 
 #include "IOStreamTarget.hh"
-//#include "IOStreamTarget.ih"
+#include "IOStreamTarget.ih"
 
 // Custom includes
+#include <errno.h>
 #include <locale>
+#include <sstream>
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/tokenizer.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -40,8 +42,8 @@
 // senf::log::IOStreamTarget
 
 prefix_ senf::log::IOStreamTarget::IOStreamTarget(std::ostream & os)
-    : stream_ (os), noformat_ (false), showTime_ (true), showStream_ (false), showLevel_ (true),
-      showArea_ (true) 
+    : stream_ (os), tag_ (detail::getDefaultTag()), noformat_ (false), showTime_ (true),
+      showStream_ (false), showLevel_ (true), showArea_ (true) 
 {
     std::locale const & loc (datestream_.getloc());
     datestream_.imbue( std::locale(
@@ -69,9 +71,11 @@ prefix_ void senf::log::IOStreamTarget::v_write(time_type timestamp,
                                                 std::string const & area, unsigned level,
                                                 std::string const & message)
 {
-    std::string m (boost::trim_right_copy(message));
+    std::string m (message);
+    boost::trim_right(m);
+    detail::quoteNonPrintable(m);
 
-    if (!showTime_ && !showStream_ && !showLevel_ && !showArea_)
+    if (tag_.empty() && !showTime_ && !showStream_ && !showLevel_ && !showArea_)
         stream_ << m << std::endl;
     else {
         typedef boost::char_separator<char> Separator;
@@ -88,6 +92,8 @@ prefix_ void senf::log::IOStreamTarget::v_write(time_type timestamp,
                 datestream_ << senf::ClockService::abstime(timestamp);
             datestream_ << ' ';
         }
+        if (!tag_.empty())
+            datestream_ << tag_ << ": ";
         if (showStream_)
             datestream_ << '[' << stream << "] ";
         if (showLevel_)
@@ -102,6 +108,22 @@ prefix_ void senf::log::IOStreamTarget::v_write(time_type timestamp,
     }
 }
 
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ void senf::log::detail::quoteNonPrintable(std::string & s)
+{
+    for (std::string::iterator i (s.begin()); i != s.end(); ++i)
+        if (*i < ' ' && *i != '\n')
+            *i = ' ';
+}
+
+prefix_ std::string senf::log::detail::getDefaultTag()
+{
+    std::stringstream ss;
+    ss << ::program_invocation_short_name << '[' << ::getpid() << ']';
+    return ss.str();
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "IOStreamTarget.mpp"
index ffa8289..1943027 100644 (file)
@@ -23,7 +23,7 @@
 /** \file
     \brief IOStreamTarget inline non-template implementation */
 
-//#include "IOStreamTarget.ih"
+#include "IOStreamTarget.ih"
 
 // Custom includes
 
@@ -50,6 +50,11 @@ prefix_ void senf::log::IOStreamTarget::showArea(bool flag)
     showArea_ = flag;
 }
 
+prefix_ void senf::log::IOStreamTarget::tag(std::string const & tag)
+{
+    tag_ = tag;
+}
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index aee7e3f..ba4a3fd 100644 (file)
@@ -79,6 +79,8 @@ namespace log {
                                              By default, the date-time will be written in extended
                                              ISO format.
                                              \param[in] format Date/Time format string */
+
+        void tag(std::string const & tag);
         
     protected:
         void v_write(time_type timestamp, std::string const & stream, 
@@ -88,6 +90,7 @@ namespace log {
     private:
         std::ostream & stream_;
 
+        std::string tag_;
         std::stringstream datestream_;
         bool noformat_;
         bool showTime_;
diff --git a/Utils/Logger/IOStreamTarget.ih b/Utils/Logger/IOStreamTarget.ih
new file mode 100644 (file)
index 0000000..2718bca
--- /dev/null
@@ -0,0 +1,54 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief IOStreamTarget internal header */
+
+#ifndef IH_SENF_Utils_Logger_IOStreamTarget_
+#define IH_SENF_Utils_Logger_IOStreamTarget_ 1
+
+// Custom includes
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+namespace log {
+namespace detail {
+
+    void quoteNonPrintable(std::string & s);
+    std::string getDefaultTag();
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 331485b..f4888f2 100644 (file)
 
 // Custom includes
 #include <sstream>
-#include "../../Socket/Protocols/INet/ConnectedUDPSocketHandle.hh"
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/tokenizer.hpp>
+#include "../../Socket/Protocols/INet/ConnectedUDPSocketHandle.hh"
+#include "IOStreamTarget.hh"
 
 //#include "SyslogUDPTarget.mpp"
 #define prefix_
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4Address const & target,
                                                     int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv4ClientSocketHandle(senf::INet4SocketAddress(target, 514u)) )
+    : facility_ (facility), tag_ (detail::getDefaultTag()),
+      handle_ ( senf::ConnectedUDPv4ClientSocketHandle(senf::INet4SocketAddress(target, 514u)) ),
+      showStream_ (false), showLevel_ (false), showArea_ (true)
 {}
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet4SocketAddress const & target,
                                                     int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv4ClientSocketHandle(target) )
+    : facility_ (facility), tag_ (detail::getDefaultTag()),
+      handle_ ( senf::ConnectedUDPv4ClientSocketHandle(target) ),
+      showStream_ (false), showLevel_ (false), showArea_ (true)
 {}
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6Address const & target,
                                                     int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv6ClientSocketHandle(senf::INet6SocketAddress(target, 514u)) )
+    : facility_ (facility), tag_ (detail::getDefaultTag()),
+      handle_ ( senf::ConnectedUDPv6ClientSocketHandle(senf::INet6SocketAddress(target, 514u)) ),
+      showStream_ (false), showLevel_ (false), showArea_ (true)
 {}
 
 prefix_ senf::log::SyslogUDPTarget::SyslogUDPTarget(senf::INet6SocketAddress const & target,
                                                     int facility)
-    : facility_ (facility),
-      handle_ ( senf::ConnectedUDPv6ClientSocketHandle(target) )
+    : facility_ (facility), tag_ (detail::getDefaultTag()),
+      handle_ ( senf::ConnectedUDPv6ClientSocketHandle(target) ),
+      showStream_ (false), showLevel_ (false), showArea_ (true)
 {}
 
 prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::string const & stream,
@@ -65,10 +70,19 @@ prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::strin
                                                  std::string const & message)
 {
     std::stringstream prefix;
+
     prefix << '<' << (facility_ | senf::log::SyslogTarget::LEVELMAP[level]) << "> ";
-    if (area != "senf::log::DefaultArea")
+    if (!tag_.empty())
+        prefix << tag_ << ": ";
+    if (showStream_)
+        prefix << '[' << stream << "] ";
+    if (showLevel_)
+        prefix << '[' << LEVELNAMES[level] << "] ";
+    if (showArea_ && area != "senf::log::DefaultArea")
         prefix << '[' << area << "] ";
-    std::string m (boost::trim_right_copy(message));
+    std::string m (message);
+    boost::trim_right(m);
+    detail::quoteNonPrintable(m);
 
     typedef boost::char_separator<char> Separator;
     typedef boost::tokenizer<Separator> Tokenizer;
@@ -77,12 +91,13 @@ prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::strin
     Tokenizer::iterator i (tokenizer.begin());
     Tokenizer::iterator const i_end (tokenizer.end());
 
-    std::stringstream line;
+    std::string line;
+    unsigned sz (896-prefix.str().size());
     for (; i != i_end; ++i) 
-        for (unsigned j (0); j < i->size(); j += 896) {
-            line << prefix.str() << std::string(*i, j, 896);
-            handle_.write(line.str());
-            line.str("");
+        for (unsigned j (0); j < i->size(); j += sz) {
+            line = prefix.str();
+            line += std::string(*i, j, sz);
+            handle_.write(line);
         }
 }
 
diff --git a/Utils/Logger/SyslogUDPTarget.cci b/Utils/Logger/SyslogUDPTarget.cci
new file mode 100644 (file)
index 0000000..24f63d2
--- /dev/null
@@ -0,0 +1,65 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief SyslogUDPTarget inline non-template implementation */
+
+//#include "SyslogUDPTarget.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ void senf::log::SyslogUDPTarget::showStream(bool flag)
+{
+    showStream_ = flag;
+}
+
+prefix_ void senf::log::SyslogUDPTarget::showLevel(bool flag)
+{
+    showLevel_ = flag;
+}
+
+prefix_ void senf::log::SyslogUDPTarget::showArea(bool flag)
+{
+    showArea_ = flag;
+}
+
+prefix_ void senf::log::SyslogUDPTarget::tag(std::string const & tag)
+{
+    tag_ = tag;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index a025c3e..6b7e269 100644 (file)
@@ -80,6 +80,11 @@ namespace log {
             space left so a relay may optionally add a timestamp and hostname section, the log
             messages are split after 896 characters. Additionally the log messages are split at each
             newline char since non-printable characters are not allowed.
+
+        \implementation The RFC only \e recommends the exact message format. This allows us to
+            include the \c PRI part but skip the \c HEADER part (which includes the timestamp and
+            hostname) for better performance. We add a space after the \c PRI to force the syslog
+            daemon to skip the \c HEADER part.
      */
     class SyslogUDPTarget
         : public Target
@@ -100,23 +105,33 @@ namespace log {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
+        void showStream(bool flag = true);
+        void showLevel(bool flag = true);
+        void showArea(bool flag = true);
+
+        void tag(std::string const & tag);
+
     private:
         void v_write(time_type timestamp, std::string const & stream, 
                      std::string const & area, unsigned level, 
                      std::string const & message);
 
         int facility_;
+        std::string tag_;
         typedef senf::ClientSocketHandle< senf::MakeSocketPolicy<
             senf::DatagramFramingPolicy,
             senf::ConnectedCommunicationPolicy,
             senf::WriteablePolicy>::policy > Handle;
         Handle handle_;
+        bool showStream_;
+        bool showLevel_;
+        bool showArea_;
     };
 
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
-//#include "SyslogUDPTarget.cci"
+#include "SyslogUDPTarget.cci"
 //#include "SyslogUDPTarget.ct"
 //#include "SyslogUDPTarget.cti"
 #endif
index 0968f08..65e9c8c 100644 (file)
@@ -44,6 +44,7 @@ BOOST_AUTO_UNIT_TEST(syslogUDPTarget)
     senf::UDPv4ClientSocketHandle server (
         senf::INet4SocketAddress(senf::INet4Address::Loopback, 23444u));
 
+    udplog.tag("");
     udplog.route();
 
     SENF_LOG(("Test message"));
@@ -55,8 +56,8 @@ BOOST_AUTO_UNIT_TEST(syslogUDPTarget)
 
     SENF_LOG(("Very long message: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
 
-    BOOST_CHECK_EQUAL( server.read(), "<13> Very long message: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
-    BOOST_CHECK_EQUAL( server.read(), "<13> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
+    BOOST_CHECK_EQUAL( server.read(), "<13> Very long message: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
+    BOOST_CHECK_EQUAL( server.read(), "<13> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////