changeset 1490:596927722403

support of --logdir by the internal logger
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 04 Aug 2015 14:04:48 +0200
parents 1389834e130f
children e460341872dc
files CMakeLists.txt Core/Logging.cpp Core/Toolbox.cpp Core/Toolbox.h OrthancServer/main.cpp
diffstat 5 files changed, 115 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Aug 04 12:22:08 2015 +0200
+++ b/CMakeLists.txt	Tue Aug 04 14:04:48 2015 +0200
@@ -25,7 +25,7 @@
 SET(DCMTK_DICTIONARY_DIR "" CACHE PATH "Directory containing the DCMTK dictionaries \"dicom.dic\" and \"private.dic\" (only when using system version of DCMTK)") 
 SET(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages")
 SET(UNIT_TESTS_WITH_HTTP_CONNEXIONS ON CACHE BOOL "Allow unit tests to make HTTP requests")
-SET(ENABLE_GOOGLE_LOG ON CACHE BOOL "Enable Google Log (otherwise, an internal logger is used)")
+SET(ENABLE_GOOGLE_LOG OFF CACHE BOOL "Enable Google Log (otherwise, an internal logger is used)")
 SET(ENABLE_JPEG ON CACHE BOOL "Enable JPEG decompression")
 SET(ENABLE_JPEG_LOSSLESS ON CACHE BOOL "Enable JPEG-LS (Lossless) decompression")
 SET(ENABLE_PLUGINS ON CACHE BOOL "Enable plugins")
--- a/Core/Logging.cpp	Tue Aug 04 12:22:08 2015 +0200
+++ b/Core/Logging.cpp	Tue Aug 04 14:04:48 2015 +0200
@@ -94,7 +94,9 @@
  *********************************************************/
 
 #include "OrthancException.h"
+#include "Toolbox.h"
 
+#include <fstream>
 #include <boost/filesystem.hpp>
 #include <boost/thread.hpp>
 
@@ -119,16 +121,86 @@
 static boost::mutex  mutex_;
 static bool infoEnabled_ = false;
 static bool traceEnabled_ = false;
-static std::ostream& error_ = std::cerr;
-static std::ostream& warning_ = std::cerr;
-static std::ostream& info_ = std::cerr;
-static std::ostream& trace_ = std::cerr;
+
+static std::ostream* error_ = &std::cerr;
+static std::ostream* warning_ = &std::cerr;
+static std::ostream* info_ = &std::cerr;
 static NullStream null_;
 
+static std::auto_ptr<std::ofstream> errorFile_;
+static std::auto_ptr<std::ofstream> warningFile_;
+static std::auto_ptr<std::ofstream> infoFile_;
+
 namespace Orthanc
 {
   namespace Logging
   {
+    static void GetLogPath(boost::filesystem::path& log,
+                           boost::filesystem::path& link,
+                           const char* level,
+                           const std::string& directory)
+    {
+      /**
+         From Google Log documentation:
+
+         Unless otherwise specified, logs will be written to the filename
+         "<program name>.<hostname>.<user name>.log.<severity level>.",
+         followed by the date, time, and pid (you can't prevent the date,
+         time, and pid from being in the filename).
+
+         In this implementation : "hostname" and "username" are not used
+      **/
+
+      boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
+      boost::filesystem::path root(directory);
+      boost::filesystem::path exe(Toolbox::GetPathToExecutable());
+      
+      if (!boost::filesystem::exists(root) ||
+          !boost::filesystem::is_directory(root))
+      {
+        throw OrthancException(ErrorCode_CannotWriteFile);
+      }
+
+      char date[64];
+      sprintf(date, "%04d%02d%02d-%02d%02d%02d.%d",
+              static_cast<int>(now.date().year()),
+              now.date().month().as_number(),
+              now.date().day().as_number(),
+              now.time_of_day().hours(),
+              now.time_of_day().minutes(),
+              now.time_of_day().seconds(),
+              Toolbox::GetProcessId());
+
+      std::string programName = exe.filename().replace_extension("").string();
+
+      log = (root / (programName + ".log." +
+                     std::string(level) + "." +
+                     std::string(date)));
+
+      link = (root / (programName + "." + std::string(level)));
+    }
+
+
+    static void PrepareLogFile(std::ostream*& stream,
+                               std::auto_ptr<std::ofstream>& file,
+                               const char* level,
+                               const std::string& directory)
+    {
+      boost::filesystem::path log, link;
+      GetLogPath(log, link, level, directory);
+
+      printf("[%s]\n", log.string().c_str());
+
+#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
+      boost::filesystem::remove(link);
+      boost::filesystem::create_symlink(log.filename(), link);
+#endif
+
+      file.reset(new std::ofstream(log.c_str()));
+      stream = file.get();
+    }
+
+
     void Initialize()
     {
       infoEnabled_ = false;
@@ -137,6 +209,9 @@
 
     void Finalize()
     {
+      errorFile_.reset(NULL);
+      warningFile_.reset(NULL);
+      infoFile_.reset(NULL);
     }
 
     void EnableInfoLevel(bool enabled)
@@ -152,8 +227,7 @@
       
       if (enabled)
       {
-        // Also enable the "INFO" level when trace-level debugging is
-        // enabled
+        // Also enable the "INFO" level when trace-level debugging is enabled
         infoEnabled_ = true;
       }
     }
@@ -161,7 +235,9 @@
     void SetTargetFolder(const std::string& path)
     {
       boost::mutex::scoped_lock lock(mutex_);
-      // TODO
+      PrepareLogFile(error_, errorFile_, "ERROR", path);
+      PrepareLogFile(warning_, warningFile_, "WARNING", path);
+      PrepareLogFile(info_, infoFile_, "INFO", path);
     }
 
     InternalLogger::InternalLogger(const char* level,
@@ -173,22 +249,22 @@
 
       if (strcmp(level, "ERROR") == 0)
       {
-        stream_ = &error_;
+        stream_ = error_;
         c = 'E';
       }
       else if (strcmp(level, "WARNING") == 0)
       {
-        stream_ = &warning_;
+        stream_ = warning_;
         c = 'W';
       }
       else if (strcmp(level, "INFO") == 0)
       {
-        stream_ = infoEnabled_ ? &info_ : &null_;
+        stream_ = infoEnabled_ ? info_ : &null_;
         c = 'I';
       }
       else if (strcmp(level, "TRACE") == 0)
       {
-        stream_ = traceEnabled_ ? &trace_ : &null_;
+        stream_ = traceEnabled_ ? info_ : &null_;
         c = 'T';
       }
       else 
@@ -206,7 +282,7 @@
         /**
            From Google Log documentation:
 
-           Log lines have this form:
+           "Log lines have this form:
 
            Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg...
 
@@ -219,7 +295,9 @@
            threadid         The space-padded thread ID as returned by GetTID() (this matches the PID on Linux)
            file             The file name
            line             The line number
-           msg              The user-supplied message
+           msg              The user-supplied message"
+
+           In this implementation, "threadid" is not printed.
          **/
 
         char date[32];
--- a/Core/Toolbox.cpp	Tue Aug 04 12:22:08 2015 +0200
+++ b/Core/Toolbox.cpp	Tue Aug 04 14:04:48 2015 +0200
@@ -56,7 +56,7 @@
 
 #if defined(_WIN32)
 #include <windows.h>
-#include <process.h>   // For "_spawnvp()"
+#include <process.h>   // For "_spawnvp()" and "_getpid()"
 #else
 #include <unistd.h>    // For "execvp()"
 #include <sys/wait.h>  // For "waitpid()"
@@ -1265,5 +1265,14 @@
     }
   }
 
+
+  int Toolbox::GetProcessId()
+  {
+#if defined(_WIN32)
+    return static_cast<int>(_getpid());
+#else
+    return static_cast<int>(getpid());
+#endif
+  }
 }
 
--- a/Core/Toolbox.h	Tue Aug 04 12:22:08 2015 +0200
+++ b/Core/Toolbox.h	Tue Aug 04 14:04:48 2015 +0200
@@ -170,5 +170,7 @@
 
     bool StartsWith(const std::string& str,
                     const std::string& prefix);
+
+    int GetProcessId();
   }
 }
--- a/OrthancServer/main.cpp	Tue Aug 04 12:22:08 2015 +0200
+++ b/OrthancServer/main.cpp	Tue Aug 04 14:04:48 2015 +0200
@@ -652,7 +652,17 @@
 
     if (boost::starts_with(argv[i], "--logdir="))
     {
-      Logging::SetTargetFolder(std::string(argv[i]).substr(9));
+      std::string directory = std::string(argv[i]).substr(9);
+
+      try
+      {
+        Logging::SetTargetFolder(directory);
+      }
+      catch (OrthancException&)
+      {
+        fprintf(stderr, "The directory where to store the log files (%s) is inexistent, aborting.\n", directory.c_str());
+        return -1;
+      }
     }
 
     if (boost::starts_with(argv[i], "--config="))