jmc.cpp
cputil.cpp
expr.cpp
- valuewrite.cpp)
+ valuewrite.cpp
+ logger.cpp)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
--- /dev/null
+#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);
+}
--- /dev/null
+#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__));
#include "manageddebugger.h"
#include "miprotocol.h"
#include "vscodeprotocol.h"
+#include "logger.h"
static const uint16_t DEFAULT_SERVER_PORT = 4711;
" 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
);
}
} interpreterType = InterpreterMI;
bool engineLogging = false;
+ LogType logType = NO_LOG;
+ LogLevel logLevel = LOG_INFO;
std::string logFilePath;
uint16_t serverPort = 0;
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;
}
}
+ Logger::setLogging(logType, logLevel);
+ Logger::log("Start logging to file");
+
ManagedDebugger debugger;
std::unique_ptr<Protocol> protocol;
{
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())
[&protocol](std::string text) { protocol->EmitOutputEvent(OutputEvent(OutputStdErr, text)); }
);
+ Logger::log("pidDebugee = " + std::to_string(pidDebuggee));
if (pidDebuggee != 0)
{
debugger.Initialize();