diff Resources/Samples/CppHelpers/Logging/ILogger.h @ 3460:fbe22748cd9c

added logging OrthancHelpers
author Alain Mazy <alain@mazy.be>
date Tue, 09 Jul 2019 10:30:30 +0200
parents
children b61e74e68d41
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();
+    }
+
+  };
+}