changeset 3460:fbe22748cd9c

added logging OrthancHelpers
author Alain Mazy <alain@mazy.be>
date Tue, 09 Jul 2019 10:30:30 +0200
parents 9ea218c90057
children 7fc9dd4882ec
files Resources/Samples/CppHelpers/Logging/ILogger.h Resources/Samples/CppHelpers/Logging/NullLogger.h Resources/Samples/CppHelpers/Logging/OrthancLogger.cpp Resources/Samples/CppHelpers/Logging/OrthancLogger.h Resources/Samples/CppHelpers/Logging/OrthancPluginLogger.cpp Resources/Samples/CppHelpers/Logging/OrthancPluginLogger.h Resources/Samples/CppHelpers/README.md
diffstat 7 files changed, 326 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/Logging/ILogger.h	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,146 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <boost/algorithm/string.hpp>
+#include <boost/thread.hpp>
+
+namespace OrthancHelpers
+{
+
+  // Interface for loggers providing the same interface
+  // in Orthanc framework or in an Orthanc plugins.
+  // Furthermore, compared to the LOG and VLOG macros,
+  // these loggers will provide "contexts".
+  class ILogger
+  {
+  public:
+    virtual ~ILogger() {}
+    virtual void Trace(const char* message) = 0;
+    virtual void Trace(const std::string& message) = 0;
+    virtual void Info(const char* message) = 0;
+    virtual void Info(const std::string& message) = 0;
+    virtual void Warning(const char* message) = 0;
+    virtual void Warning(const std::string& message) = 0;
+    virtual void Error(const char* message) = 0;
+    virtual void Error(const std::string& message) = 0;
+
+    virtual void EnterContext(const char* message) = 0;
+    virtual void EnterContext(const std::string& message) = 0;
+    virtual void LeaveContext() = 0;
+  };
+
+
+  // Implements ILogger by providing contexts.  Contexts defines
+  // the "call-stack" of the logs and are prepended to the log.
+  // check LogContext class for more details
+  class BaseLogger : public ILogger
+  {
+    boost::thread_specific_ptr<std::vector<std::string>> contexts_;
+    bool logContextChanges_;
+
+  public:
+
+    BaseLogger()
+      : logContextChanges_(false)
+    {
+    }
+
+    void EnableLogContextChanges(bool enable)
+    {
+      logContextChanges_ = enable;
+    }
+
+    virtual void EnterContext(const char* message)
+    {
+      EnterContext(std::string(message));
+    }
+
+    virtual void EnterContext(const std::string& message)
+    {
+      if (!contexts_.get())
+      {
+        contexts_.reset(new std::vector<std::string>());
+      }
+      contexts_->push_back(message);
+
+      if (logContextChanges_)
+      {
+        Info(".. entering");
+      }
+    }
+
+    virtual void LeaveContext()
+    {
+      if (logContextChanges_)
+      {
+        Info(".. leaving");
+      }
+
+      contexts_->pop_back();
+      if (contexts_->size() == 0)
+      {
+        contexts_.reset(NULL);
+      }
+    }
+
+  protected:
+
+    virtual std::string GetContext()
+    {
+      if (contexts_.get() != NULL && contexts_->size() > 0)
+      {
+        return "|" + boost::algorithm::join(*contexts_, " | ") + "|";
+      }
+      else
+      {
+        return std::string("|");
+      }
+    }
+  };
+
+
+  /* RAII to set a Log context.
+  * Example:
+  * ILogger* logger = new OrthancPluginLogger(..);
+  * {
+  *   LogContext logContext(logger, "A");
+  *   {
+  *     LogContext nestedLogContext(logger, "B");
+  *     logger->Error("out of memory");
+  *   }
+  * }
+  * will produce:
+  * |A | B| out of memory
+  *
+  * furthermore, if LogContextChanges are enabled in the BaseLogger,
+  * you'll get;
+  * |A| .. entering
+  * |A | B| .. entering
+  * |A | B| out of memory
+  * |A | B| .. leaving
+  * |A| .. leaving
+  */
+  class LogContext
+  {
+    ILogger* logger_;
+  public:
+    LogContext(ILogger* logger, const char* context) :
+      logger_(logger)
+    {
+      logger_->EnterContext(context);
+    }
+
+    LogContext(ILogger* logger, const std::string& context) :
+      logger_(logger)
+    {
+      logger_->EnterContext(context);
+    }
+
+    ~LogContext()
+    {
+      logger_->LeaveContext();
+    }
+
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/Logging/NullLogger.h	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "ILogger.h"
+
+namespace OrthancHelpers
+{
+  // a logger ... that does not log.
+  // Instead of writing:
+  // if (logger != NULL)
+  // {
+  //   logger->Info("hello")   ;
+  // }
+  // you should create a NullLogger:
+  // logger = new NullLogger();
+  // ...
+  // logger->Info("hello");
+  class NullLogger : public BaseLogger {
+  public:
+    NullLogger() {}
+
+    virtual void Trace(const char* message) {}
+    virtual void Trace(const std::string& message) {}
+    virtual void Info(const char* message) {}
+    virtual void Info(const std::string& message) {}
+    virtual void Warning(const char* message) {}
+    virtual void Warning(const std::string& message) {}
+    virtual void Error(const char* message) {}
+    virtual void Error(const std::string& message) {}
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/Logging/OrthancLogger.cpp	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,46 @@
+#include "OrthancLogger.h"
+#include "Logging.h"
+
+namespace OrthancHelpers
+{
+
+  void OrthancLogger::Trace(const char *message)
+  {
+    VLOG(1) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Trace(const std::string& message)
+  {
+    VLOG(1) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Info(const char *message)
+  {
+    LOG(INFO) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Info(const std::string& message)
+  {
+    LOG(INFO) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Warning(const char *message)
+  {
+    LOG(WARNING) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Warning(const std::string& message)
+  {
+    LOG(WARNING) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Error(const char *message)
+  {
+    LOG(ERROR) << GetContext() << " " << message;
+  }
+
+  void OrthancLogger::Error(const std::string& message)
+  {
+    LOG(ERROR) << GetContext() << " " << message;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/Logging/OrthancLogger.h	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "ILogger.h"
+
+namespace OrthancHelpers
+{
+
+  class OrthancLogger : public BaseLogger
+  {
+  public:
+    virtual void Trace(const char *message);
+    virtual void Trace(const std::string &message);
+    virtual void Info(const char *message);
+    virtual void Info(const std::string &message);
+    virtual void Warning(const char *message);
+    virtual void Warning(const std::string &message);
+    virtual void Error(const char *message);
+    virtual void Error(const std::string &message);
+  };
+} // namespace OrthancHelpers
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/Logging/OrthancPluginLogger.cpp	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,55 @@
+#include "OrthancPluginLogger.h"
+
+namespace OrthancHelpers
+{
+
+  OrthancPluginLogger::OrthancPluginLogger(OrthancPluginContext *context)
+    : pluginContext_(context),
+      hasAlreadyLoggedTraceWarning_(false)
+  {
+  }
+
+  void OrthancPluginLogger::Trace(const char *message)
+  {
+    Trace(std::string(message));
+  }
+
+  void OrthancPluginLogger::Trace(const std::string &message)
+  {
+    if (!hasAlreadyLoggedTraceWarning_)
+    {
+      Warning("Trying to log 'TRACE' level information in a plugin is not possible.  These logs won't appear.");
+      hasAlreadyLoggedTraceWarning_ = true;
+    }
+  }
+
+  void OrthancPluginLogger::Info(const char *message)
+  {
+    Info(std::string(message));
+  }
+
+  void OrthancPluginLogger::Info(const std::string &message)
+  {
+    OrthancPluginLogInfo(pluginContext_, (GetContext() + " " + message).c_str());
+  }
+
+  void OrthancPluginLogger::Warning(const char *message)
+  {
+    Warning(std::string(message));
+  }
+
+  void OrthancPluginLogger::Warning(const std::string &message)
+  {
+    OrthancPluginLogWarning(pluginContext_, (GetContext() + " " + message).c_str());
+  }
+
+  void OrthancPluginLogger::Error(const char *message)
+  {
+    Error(std::string(message));
+  }
+
+  void OrthancPluginLogger::Error(const std::string &message)
+  {
+    OrthancPluginLogError(pluginContext_, (GetContext() + " " + message).c_str());
+  }
+} // namespace OrthancHelpers
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/Logging/OrthancPluginLogger.h	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "ILogger.h"
+#include <orthanc/OrthancCPlugin.h>
+
+namespace OrthancHelpers
+{
+
+  class OrthancPluginLogger : public BaseLogger
+  {
+    OrthancPluginContext *pluginContext_;
+    bool hasAlreadyLoggedTraceWarning_;
+
+  public:
+    OrthancPluginLogger(OrthancPluginContext *context);
+
+    virtual void Trace(const char *message);
+    virtual void Trace(const std::string &message);
+    virtual void Info(const char *message);
+    virtual void Info(const std::string &message);
+    virtual void Warning(const char *message);
+    virtual void Warning(const std::string &message);
+    virtual void Error(const char *message);
+    virtual void Error(const std::string &message);
+  };
+} // namespace OrthancHelpers
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Samples/CppHelpers/README.md	Tue Jul 09 10:30:30 2019 +0200
@@ -0,0 +1,3 @@
+This folder contains a bunch of helpers that are used in multiple Orthanc side projects (either plugins, standalone executables using the Orthanc framework or orthanc-stone based applications)
+
+When writing plugins, you may also want to check the Plugins/Samples/Common folder for other helpers.
\ No newline at end of file