Logger: implementation
authorAlexander Aksenov <a.aksenov@samsung.com>
Mon, 22 Oct 2018 17:13:37 +0000 (20:13 +0300)
committerAlexander Aksenov <a.aksenov@samsung.com>
Tue, 30 Oct 2018 09:40:46 +0000 (12:40 +0300)
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
src/debug/netcoredbg/CMakeLists.txt
src/debug/netcoredbg/logger.cpp [new file with mode: 0644]
src/debug/netcoredbg/logger.h [new file with mode: 0644]
src/debug/netcoredbg/main.cpp

index 5a39cc7..ad72280 100644 (file)
@@ -42,7 +42,8 @@ set(netcoredbg_SRC
     jmc.cpp
     cputil.cpp
     expr.cpp
-    valuewrite.cpp)
+    valuewrite.cpp
+    logger.cpp)
 
 set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
diff --git a/src/debug/netcoredbg/logger.cpp b/src/debug/netcoredbg/logger.cpp
new file mode 100644 (file)
index 0000000..65e6e3e
--- /dev/null
@@ -0,0 +1,94 @@
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <ctime>
+#include <iomanip>
+#include <chrono>
+#include "logger.h"
+
+
+
+
+class NoLogger : public LoggerImpl
+{
+    public:
+        NoLogger() {}
+        ~NoLogger() override {}
+        void log(LogLevel level, const std::string& msg) override {}
+};
+
+class FileLogger : public LoggerImpl
+{
+    LogLevel l;
+
+    private:
+        const std::string filenameBase = "netcoredbg_";
+        std::ofstream logFile;
+        std::time_t timeNow;
+
+    public:
+        FileLogger(LogLevel level);
+        ~FileLogger() override;
+        void log(LogLevel level, const std::string& msg) override;
+
+};
+
+
+
+FileLogger::FileLogger(LogLevel level)
+{
+    auto time = std::time(nullptr);
+    std::ostringstream oss;
+
+    oss << std::put_time(std::localtime(&time), "%Y_%m_%d__%H_%M_%S");
+
+    logFile.open(filenameBase + oss.str() + ".log", std::ios::out | std::ios::trunc);
+    l = level;
+}
+
+FileLogger::~FileLogger()
+{
+    logFile.close();
+}
+
+void FileLogger::log(LogLevel level, const std::string& msg)
+{
+    if (level < l)
+        return;
+
+    auto time = std::time(nullptr);
+
+    if (logFile.is_open()) {
+        logFile << std::put_time(std::localtime(&time), "%y-%m-%d %OH:%OM:%OS") << " " << msg + "\n";
+        logFile.flush();
+    }
+}
+
+
+
+
+
+std::shared_ptr<LoggerImpl> Logger::logger = std::make_shared<NoLogger>();
+
+void Logger::setLogging(LogType type, LogLevel level)
+{
+    switch (type) {
+    case FILE_LOG:
+        logger = std::make_shared<FileLogger>(level);
+        break;
+    case NO_LOG:
+    default:
+        logger = std::make_shared<NoLogger>();
+        break;
+    }
+}
+
+void Logger::log(const std::string& msg)
+{
+    logger->log(LOG_INFO, msg);
+}
+
+FuncLogger Logger::getFuncLogger(const std::string &func)
+{
+    return FuncLogger(logger, func);
+}
diff --git a/src/debug/netcoredbg/logger.h b/src/debug/netcoredbg/logger.h
new file mode 100644 (file)
index 0000000..e0cb697
--- /dev/null
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <string>
+#include <memory>
+
+
+enum LogType {
+    NO_LOG = 0,
+    FILE_LOG,
+};
+
+enum LogLevel {
+    LOG_DEBUG = 0,
+    LOG_INFO,
+};
+
+
+class LoggerImpl
+{
+    public:
+        virtual ~LoggerImpl() {};
+        virtual void log(LogLevel level, const std::string& msg) = 0;
+};
+
+class FuncLogger
+{
+    private:
+        const std::shared_ptr<LoggerImpl> &logger;
+        const std::string func;
+
+    public:
+        FuncLogger(const std::shared_ptr<LoggerImpl> &logger, const std::string &func) : logger(logger), func(func)
+        {
+            logger->log(LOG_DEBUG, "> " + func);
+        }
+
+        ~FuncLogger()
+        {
+            logger->log(LOG_DEBUG, "< " + func);
+        }
+};
+
+class Logger
+{
+    private:
+        static std::shared_ptr<LoggerImpl> logger;
+
+    public:
+        Logger() {}
+        static void setLogging(LogType type, LogLevel level = LOG_INFO);
+        static void log(const std::string& msg);
+        static FuncLogger getFuncLogger(const std::string &func);
+};
+
+#ifdef WIN32
+#define __CROSS_FUNCTION__ __FUNCSIG__
+#else // WIN32
+#define __CROSS_FUNCTION__ __PRETTY_FUNCTION__
+#endif // WIN32
+
+#define LogFuncEntry()  \
+    FuncLogger __funcLogger__ = Logger::getFuncLogger(std::string(__CROSS_FUNCTION__));
index f941bc7..9614b76 100644 (file)
@@ -11,6 +11,7 @@
 #include "manageddebugger.h"
 #include "miprotocol.h"
 #include "vscodeprotocol.h"
+#include "logger.h"
 
 static const uint16_t DEFAULT_SERVER_PORT = 4711;
 
@@ -27,7 +28,11 @@ static void print_help()
         "                                      Only supported by the VsCode interpreter.\n"
         "--server[=port_num]                   Start the debugger listening for requests on the\n"
         "                                      specified TCP/IP port instead of stdin/out. If port is not specified\n"
-        "                                      TCP %i will be used.\n",
+        "                                      TCP %i will be used.\n"
+        "--log-file[=<debug>]                  Enable logging to file which is created in 'current'. Supported\n"
+        "                                      two log levels: info and debug. Info contains info, warn and error\n"
+        "                                      messages, debug the same and debug messages in addition. Info level\n"
+        "                                      is the default one.\n",
         (int)DEFAULT_SERVER_PORT
     );
 }
@@ -43,6 +48,8 @@ int main(int argc, char *argv[])
     } interpreterType = InterpreterMI;
 
     bool engineLogging = false;
+    LogType logType = NO_LOG;
+    LogLevel logLevel = LOG_INFO;
     std::string logFilePath;
 
     uint16_t serverPort = 0;
@@ -94,6 +101,21 @@ int main(int argc, char *argv[])
             print_help();
             return EXIT_SUCCESS;
         }
+        else if (strcmp(argv[i], "--log-file") == 0)
+        {
+            logType = FILE_LOG;
+            continue;
+        }
+        else if (strstr(argv[i], "--log-file=") == argv[i])
+        {
+            const std::string &debug = "debug";
+
+            logType = FILE_LOG;
+            if (std::string(argv[i] + strlen("--log-file=")) == debug)
+                logLevel = LOG_DEBUG;
+            else
+                logLevel = LOG_INFO;
+        }
         else if (strcmp(argv[i], "--server") == 0)
         {
             serverPort = DEFAULT_SERVER_PORT;
@@ -135,6 +157,9 @@ int main(int argc, char *argv[])
         }
     }
 
+    Logger::setLogging(logType, logLevel);
+    Logger::log("Start logging to file");
+
     ManagedDebugger debugger;
     std::unique_ptr<Protocol> protocol;
 
@@ -142,23 +167,28 @@ int main(int argc, char *argv[])
     {
         case InterpreterMI:
         {
+            Logger::log("InterpreterMI selected");
             if (engineLogging)
             {
                 fprintf(stderr, "Error: Engine logging is only supported in VsCode interpreter mode.\n");
+                Logger::log("Error: Engine logging is only supported in VsCode interpreter mode.");
                 return EXIT_FAILURE;
             }
             MIProtocol *miProtocol = new MIProtocol();
             protocol.reset(miProtocol);
             miProtocol->SetDebugger(&debugger);
+            Logger::log("SetDebugger for InterpreterMI");
             if (!execFile.empty())
                 miProtocol->SetLaunchCommand(execFile, execArgs);
             break;
         }
         case InterpreterVSCode:
         {
+            Logger::log("InterpreterVSCode selected");
             VSCodeProtocol *vsCodeProtocol = new VSCodeProtocol();
             protocol.reset(vsCodeProtocol);
             vsCodeProtocol->SetDebugger(&debugger);
+            Logger::log("SetDebugger for InterpreterVSCode");
             if (engineLogging)
                 vsCodeProtocol->EngineLogging(logFilePath);
             if (!execFile.empty())
@@ -175,6 +205,7 @@ int main(int argc, char *argv[])
         [&protocol](std::string text) { protocol->EmitOutputEvent(OutputEvent(OutputStdErr, text)); }
     );
 
+    Logger::log("pidDebugee = " + std::to_string(pidDebuggee));
     if (pidDebuggee != 0)
     {
         debugger.Initialize();