From 7e9f45c3980534ce1e0831a7bd27c778df8951ac Mon Sep 17 00:00:00 2001
From: Stephen Roderick <kiwi.net@mac.com>
Date: Mon, 29 Mar 2010 17:36:54 -0400
Subject: [PATCH] cmake: Add support to log through log4cpp, instead of directly to file

Replaces direct iostream logging to "orocos.log" with logging to
log4cpp. Parent application can/must setup log4cpp category(-ies)
to send the log entries somewhere useful (eg file, socket).

WARNING both RTT::Logger log levels and also log4cpp priorities dictate
what will be logged. You are recommended to set one to debug and use
the other to control the actual logging level (NB RTT defaults to
always logging at least INFO to file. This constraint remains).
---
 config/FindLog4cpp.cmake |   36 ++++++++++++++++++++++++++++++++++++
 src/CMakeLists.txt       |   14 +++++++++++++-
 src/Logger.cpp           |   45 +++++++++++++++++++++++++++++++++++++++++----
 src/Logger.hpp           |    7 +++++++
 src/targets/target.in    |    1 +
 5 files changed, 98 insertions(+), 5 deletions(-)
 create mode 100644 config/FindLog4cpp.cmake

diff --git a/config/FindLog4cpp.cmake b/config/FindLog4cpp.cmake
new file mode 100644
index 0000000..04f4bce
--- /dev/null
+++ b/config/FindLog4cpp.cmake
@@ -0,0 +1,36 @@
+################################################################################
+#
+# CMake script for finding Log4cpp.
+# The default CMake search process is used to locate files.
+#
+# This script creates the following variables:
+#  LOG4CPP_FOUND: Boolean that indicates if the package was found
+#  LOG4CPP_INCLUDE_DIRS: Paths to the necessary header files
+#  LOG4CPP_LIBRARIES: Package libraries
+#  LOG4CPP_LIBRARY_DIRS: Path to package libraries
+#
+################################################################################
+
+include(FindPackageHandleStandardArgs)
+
+# Find headers and libraries
+find_path(LOG4CPP_INCLUDE_DIR NAMES log4cpp/Category.hh)
+find_library(LOG4CPP_LIBRARY NAMES log4cpp)
+
+# Set LOG4CPP_FOUND honoring the QUIET and REQUIRED arguments
+find_package_handle_standard_args(LOG4CPP DEFAULT_MSG LOG4CPP_LIBRARY LOG4CPP_INCLUDE_DIR)
+
+# Output variables
+if(LOG4CPP_FOUND)
+  # Include dirs
+  set(LOG4CPP_INCLUDE_DIRS ${LOG4CPP_INCLUDE_DIR})
+
+  # Libraries
+  set(LOG4CPP_LIBRARIES ${LOG4CPP_LIBRARY})
+
+  # Link dirs
+  get_filename_component(LOG4CPP_LIBRARY_DIRS ${LOG4CPP_LIBRARY} PATH)
+endif()
+
+# Advanced options for not cluttering the cmake UIs
+mark_as_advanced(LOG4CPP_INCLUDE_DIR LOG4CPP_LIBRARY)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b73cdd2..6fc24e6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,6 +2,8 @@
 include (CMakeDependentOption)
 include (CreatePCFlags)
 
+SET(EXTRA_LIBRARIES)
+
 ###
 ### List user options first before traversing sub-directories:
 ### All user options must be defined in this file, sub-directories can
@@ -51,6 +53,7 @@ OPTION(OROBLD_DISABLE_LOGGING "Disable Logging Infrastructure" OFF)
 CMAKE_DEPENDENT_OPTION(OROSEM_PRINTF_LOGGING "Logger uses printf()/fprintf() instead of std::iostream." OFF "NOT OROBLD_DISABLE_LOGGING" OFF)
 CMAKE_DEPENDENT_OPTION(OROSEM_FILE_LOGGING "Logger logs to orocos.log file." ON "NOT OROBLD_DISABLE_LOGGING" OFF)
 CMAKE_DEPENDENT_OPTION(OROSEM_REMOTE_LOGGING "Logger allows remote log retrieval." ON "NOT OROBLD_DISABLE_LOGGING" OFF)
+CMAKE_DEPENDENT_OPTION(OROSEM_LOG4CPP_LOGGING "Logger logs to log4cpp infrastructure (replaces file and printf logging) ." OFF "NOT OROBLD_DISABLE_LOGGING;OROSEM_FILE_LOGGING" OFF)
 
 IF (OROSEM_REMOTE_LOGGING AND NOT OROBLD_DISABLE_LOGGING)
   SET(ORONUM_LOGGING_BUFSIZE 1000 CACHE STRING "Maximum number of lines kept for remote log retrieval.")
@@ -58,6 +61,15 @@ ELSE (OROSEM_REMOTE_LOGGING AND NOT OROBLD_DISABLE_LOGGING)
   SET(ORONUM_LOGGING_BUFSIZE CACHE INTERNAL "")
 ENDIF (OROSEM_REMOTE_LOGGING AND NOT OROBLD_DISABLE_LOGGING)
 
+IF (OROSEM_LOG4CPP_LOGGING)
+  FIND_PACKAGE(Log4cpp REQUIRED)
+
+  INCLUDE_DIRECTORIES(${LOG4CPP_INCLUDE_DIRS})
+  # add library to .pc file?
+  LIST(APPEND EXTRA_LIBRARIES ${LOG4CPP_LIBRARIES})
+
+ENDIF (OROSEM_LOG4CPP_LOGGING)
+
 ### Execution Engine
 OPTION(OROPKG_EXECUTION_ADVANCED "Advanced Execution Engine configuration" OFF)
 CMAKE_DEPENDENT_OPTION(OROPKG_EXECUTION_ENGINE_EVENTS "Enable Event Processing." ON "OROPKG_EXECUTION_ADVANCED" ON)
@@ -183,7 +195,7 @@ ENDIF ( BUILD_STATIC )
     COMPILE_FLAGS "${CMAKE_CXX_FLAGS_ADD} ${RTT_CFLAGS} -DOROCOS_TARGET=${OROCOS_TARGET}"
     CLEAN_DIRECT_OUTPUT 1)
     
-  target_link_libraries(orocos-rtt-dynamic_${OROCOS_TARGET} ${OROCOS-RTT_LIBRARIES})
+  target_link_libraries(orocos-rtt-dynamic_${OROCOS_TARGET} ${OROCOS-RTT_LIBRARIES} ${EXTRA_LIBRARIES})
 
 create_pc_flags( "${OROCOS-RTT_DEFINITIONS}" "${OROCOS-RTT_INCLUDE_DIRS}" "${OROCOS-RTT_LIBRARIES}" RTT_DEFINES RTT_CFLAGS RTT_LINKFLAGS)
 create_pc_flags( "${RTT_DUMMY}" "${RTT_DUMMY}" "${OROCOS-RTT_USER_LINK_LIBS}" RTT_DUMMY RTT_DUMMY RTT_USER_LINK_LIBS)
diff --git a/src/Logger.cpp b/src/Logger.cpp
index 9acf1a3..b06d414 100644
--- a/src/Logger.cpp
+++ b/src/Logger.cpp
@@ -52,6 +52,9 @@
 #  include <ostream>
 #  ifdef OROSEM_FILE_LOGGING
 #   include <fstream>
+#   ifdef  OROSEM_LOG4CPP_LOGGING
+#    include <log4cpp/Category.hh>
+#   endif
 #  endif
 #  ifdef OROSEM_REMOTE_LOGGING
 #   include <sstream>
@@ -84,6 +87,31 @@ namespace RTT
 
 #ifndef OROBLD_DISABLE_LOGGING
 
+#ifdef  OROSEM_LOG4CPP_LOGGING
+
+    const std::string Logger::log4cppCategoryName = "org.orocos.rtt";
+
+    log4cpp::Priority::Value level2Priority(const int logLevel)
+    {
+        log4cpp::Priority::Value value = log4cpp::Priority::NOTSET;
+        switch (logLevel)
+        {
+            case Never:     value = log4cpp::Priority::NOTSET; break;
+            case Fatal:     value = log4cpp::Priority::FATAL;  break;
+            case Critical:  value = log4cpp::Priority::CRIT;   break;
+            case Error:     value = log4cpp::Priority::ERROR;  break;
+            case Warning:   value = log4cpp::Priority::WARN;   break;
+            case Info:      value = log4cpp::Priority::INFO;   break;
+            case Debug:     value = log4cpp::Priority::DEBUG;  break;
+                // best we can do!?
+            case RealTime:  value = log4cpp::Priority::DEBUG;  break;
+            default:        value = log4cpp::Priority::NOTSET; break;
+        }
+        return value;
+    }
+
+#endif
+
     Logger& Logger::log() {
         return *Instance();
     }
@@ -104,9 +132,13 @@ namespace RTT
 #ifdef OROSEM_REMOTE_LOGGING
               messagecnt(0),
 #endif
-#if defined(OROSEM_FILE_LOGGING) && !defined(OROSEM_PRINTF_LOGGING)
+#if     defined(OROSEM_FILE_LOGGING)
+#if     defined(OROSEM_LOG4CPP_LOGGING)
+              category(log4cpp::Category::getInstance(RTT::Logger::log4cppCategoryName)),
+#elif   !defined(OROSEM_PRINTF_LOGGING)
               logfile("orocos.log"),
 #endif
+#endif
               inloglevel(Info),
               outloglevel(Warning),
               timestamp(0),
@@ -114,7 +146,7 @@ namespace RTT
               mlogStdOut(true), mlogFile(true),
               moduleptr("Logger")
         {
-#if defined(OROSEM_FILE_LOGGING) && defined(OROSEM_PRINTF_LOGGING)
+#if defined(OROSEM_FILE_LOGGING) && !defined(OROSEM_LOG4CPP_LOGGING) && defined(OROSEM_PRINTF_LOGGING)
             logfile = fopen("orocos.log","w");
 #endif
         }
@@ -159,8 +191,10 @@ namespace RTT
             }
 
             if ( maylogFile() ) {
-#ifdef OROSEM_FILE_LOGGING
-#ifndef OROSEM_PRINTF_LOGGING
+#if     defined(OROSEM_FILE_LOGGING)
+#if     defined(OROSEM_LOG4CPP_LOGGING)
+                category.log(level2Priority(inloglevel), fileline.str());
+#elif   !defined(OROSEM_PRINTF_LOGGING)
                 logfile << res << fileline.str() << pf;
 #else
                 fprintf( logfile, "%s%s\n", res.c_str(), fileline.str().c_str() );
@@ -194,6 +228,9 @@ namespace RTT
         unsigned int messagecnt;
 #endif
 #if defined(OROSEM_FILE_LOGGING)
+#if     defined(OROSEM_LOG4CPP_LOGGING)
+        log4cpp::Category&   category;
+#endif
 # ifndef OROSEM_PRINTF_LOGGING
         std::ofstream logfile;
 # else
diff --git a/src/Logger.hpp b/src/Logger.hpp
index f4dfa10..a3f3ffc 100644
--- a/src/Logger.hpp
+++ b/src/Logger.hpp
@@ -301,6 +301,13 @@ namespace RTT
          */
         void lognl();
 
+#ifdef  OROSEM_LOG4CPP_LOGGING
+        /** 
+         * Name of the log4cpp category that RTT logs to
+         */
+        static const std::string log4cppCategoryName;
+#endif
+
     private:
         /**
          * Returns true if the next message will be logged.
diff --git a/src/targets/target.in b/src/targets/target.in
index e451b66..849fc1d 100644
--- a/src/targets/target.in
+++ b/src/targets/target.in
@@ -53,6 +53,7 @@
 #cmakedefine OROSEM_PRINTF_LOGGING
 #cmakedefine OROSEM_FILE_LOGGING
 #cmakedefine OROSEM_REMOTE_LOGGING
+#cmakedefine OROSEM_LOG4CPP_LOGGING
 #define ORONUM_LOGGING_BUFSIZE @ORONUM_LOGGING_BUFSIZE@
 
 #define OROPKG_OS
-- 
1.7.0.2

