diff --git a/Framework/Logging/CMakeLists.txt b/Framework/Logging/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..51da77cf702a67e44ecfa5ba810a086b147951dd
--- /dev/null
+++ b/Framework/Logging/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+
+add_library (CORSIKAlogging INTERFACE)
+
+target_include_directories (CORSIKAlogging INTERFACE ${PROJECT_SOURCE_DIR}/Framework)
+
+target_include_directories (CORSIKAlogging INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/Framework>
+                                                     $<INSTALL_INTERFACE:include/Framework>
+                                                     )
+
+install (FILES Logger.h
+         DESTINATION include/Logging)
+
diff --git a/Framework/Logging/Logger.h b/Framework/Logging/Logger.h
new file mode 100644
index 0000000000000000000000000000000000000000..73275ceb130a01c1ca148c2040cfcb2566e287f9
--- /dev/null
+++ b/Framework/Logging/Logger.h
@@ -0,0 +1,142 @@
+#ifndef _include_logger_h_
+#define _include_logger_h_
+
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <typeinfo>
+#include <fstream>
+
+#include <boost/format.hpp>
+ 
+using namespace std;
+using namespace boost;
+
+
+class MessageOff {
+ protected:
+  template<typename First, typename ... Strings> std::string message(const First& arg, const Strings&... rest) {
+    return "";
+  }
+};
+  
+class messageconst {
+ protected:
+  std::string message() { return "\n"; }
+
+  template<typename First, typename ... Strings> std::string message(const First& arg, const Strings&... rest) {
+    std::ostringstream ss;
+    ss << arg << message(rest...);
+    return ss.str();
+  }
+  
+  template<typename ... Strings> std::string message(const int& arg, const Strings&... rest) {
+    return std::to_string(arg) + message(rest...);
+  }
+
+  template<typename ... Strings> std::string message(const double& arg, const Strings&... rest) {
+    return std::to_string(arg) + message(rest...);
+  }
+  
+  template<typename ... Strings> std::string message(char const * arg, const Strings&... rest) {
+    return std::string(arg) + message(rest...);
+  }
+  
+  template<typename ... Strings> std::string message(const std::string& arg, const Strings&... rest) {
+    return arg + message(rest...);
+  }
+  
+  // ----------------------
+  // boost format
+  template<typename ... Strings> std::string message(const boost::format& fmt, const Strings&... rest) {
+    boost::format FMT(fmt);
+    return bformat(FMT, rest...);
+  }
+  
+  template<typename Arg, typename ... Strings> std::string bformat(boost::format& fmt, const Arg& arg, const Strings&... rest) {
+    fmt % arg;
+    return bformat(fmt, rest...);
+  }
+
+  std::string bformat(boost::format& fmt) { return fmt.str() + "\n"; }
+};
+
+
+struct NoBuffer {
+  inline bool Test(const std::string&) const { return false; }
+  inline std::string GetString() const { return std::string(""); }
+  inline void Clear() {}
+  inline void Add(const std::string&) {}
+};
+
+struct StdBuffer {
+  StdBuffer(const int size) : fSize(size) {}
+  inline bool Test(const std::string& s) { return int(fBuffer.tellp())+s.length() < fSize; }
+  inline std::string GetString() const { return fBuffer.str(); }
+  inline void Clear() { fBuffer.str(""); }
+  inline void Add(const std::string& s) { fBuffer << s; }
+private:
+  int fSize;
+  std::ostringstream fBuffer;
+};
+
+
+template<typename TStream, typename TBuffer=StdBuffer> 
+class Sink {
+ public:
+  Sink(TStream& out, TBuffer buffer = {} ) : fOutput(out), fBuffer(std::move(buffer)) {} 
+  void operator<<(const std::string& msg) {
+    if (!fBuffer.Test(msg)) {
+      fOutput << fBuffer.GetString();
+      fBuffer.Clear();
+    }
+    if (!fBuffer.Test(msg))
+      fOutput << msg;
+    else 
+      fBuffer.Add(msg);
+  }
+ void Close() { fOutput << fBuffer.GetString(); }
+ private:
+  TStream& fOutput;
+  TBuffer fBuffer;
+};
+
+
+
+struct NoSink { inline void operator<<(const std::string&) {} inline void Close() {} };
+
+
+template<typename TSink=NoSink,typename M=messageconst> 
+class logger : private M {
+  
+  using M::message;
+
+ public:
+  // logger() : fName("") {}
+  logger(const std::string color, const std::string name, TSink& sink) : fSink(sink), fName(color+"["+name+"]\033[39m ")  {} 
+  ~logger() { fSink.Close(); }
+  
+  // logger(const logger&) = delete;
+  
+  template<typename ... Strings>
+  void log(const Strings&... inputs) {
+    fSink << M::message(inputs...);
+  }
+
+  const std::string& GetName() const { return fName; }
+  
+ private:
+  TSink& fSink;
+  std::string fName;
+};
+
+
+
+#define LOG(__LOGGER,...) \
+  __LOGGER.log(__LOGGER.GetName(), __FILE__,":", __LINE__, " (", __func__, ") -> ", ##__VA_ARGS__);
+
+
+
+
+#endif
+ 
diff --git a/Framework/Logging/Logging.h b/Framework/Logging/Logging.h
new file mode 100644
index 0000000000000000000000000000000000000000..548e508529a3358429ccdfc8d6cfeb0d9a33054c
--- /dev/null
+++ b/Framework/Logging/Logging.h
@@ -0,0 +1,27 @@
+#ifndef _include_logging_h_
+#define _include_logging_h_
+
+#include <logger.h>
+
+#include <map>
+#include <string>
+#include <any>
+
+class Logging {
+  
+  Logging() {}
+  
+ public:
+  
+  static Logging& GetInstance() { static Logging fgLog; return fgLog; }
+
+  template<typename TLogger>
+    void AddLogger(const std::string& name, const TLogger& logger) { fLoggers[name] = logger; }
+
+  auto& GetLogger(const std::string& name) { return fLoggers[name]; }
+  
+ private:
+  std::map<std::string, std::any> fLoggers;
+};
+
+#endif
diff --git a/Framework/Logging/Makefile b/Framework/Logging/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c6c84cac0c0fd96166af6eb86fa9e390a2ad3811
--- /dev/null
+++ b/Framework/Logging/Makefile
@@ -0,0 +1,10 @@
+CXXFLAGS+=-I. --std=c++14 -O3
+
+all: test test_off
+
+#test: test.o
+#	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@
+
+clean:
+	rm -rf *.o test test_off *.dat *.log
+