Browse Source

Refactor logger. Require setting logger::logPath before initializing logger.

tags/v2.0.0
Andrew Belt 3 years ago
parent
commit
0a59d4aad3
3 changed files with 45 additions and 38 deletions
  1. +5
    -3
      adapters/standalone.cpp
  2. +2
    -3
      include/logger.hpp
  3. +38
    -32
      src/logger.cpp

+ 5
- 3
adapters/standalone.cpp View File

@@ -108,7 +108,9 @@ int main(int argc, char* argv[]) {
// Initialize environment // Initialize environment
system::init(); system::init();
asset::init(); asset::init();
bool loggerWasTruncated = logger::isTruncated();
if (!settings::devMode) {
logger::logPath = asset::user("log.txt");
}
logger::init(); logger::init();
random::init(); random::init();


@@ -203,8 +205,8 @@ int main(int argc, char* argv[]) {
#endif #endif


// Initialize patch // Initialize patch
if (loggerWasTruncated && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack crashed during the last session, possibly due to a buggy module in your patch. Clear your patch and start over?")) {
// Do nothing
if (logger::wasTruncated() && osdialog_message(OSDIALOG_INFO, OSDIALOG_YES_NO, "Rack crashed during the last session, possibly due to a buggy module in your patch. Clear your patch and start over?")) {
// Do nothing, which leaves a blank patch
} }
else { else {
APP->patch->launch(patchPath); APP->patch->launch(patchPath);


+ 2
- 3
include/logger.hpp View File

@@ -40,10 +40,9 @@ Thread-safe, meaning messages cannot overlap each other in the log.
*/ */
__attribute__((format(printf, 5, 6))) __attribute__((format(printf, 5, 6)))
void log(Level level, const char* filename, int line, const char* func, const char* format, ...); void log(Level level, const char* filename, int line, const char* func, const char* format, ...);
/** Returns whether the current log file failed to end properly, due to a possible crash.
Must be called *before* init().
/** Returns whether the last log file failed to end properly, due to a possible crash.
*/ */
bool isTruncated();
bool wasTruncated();




} // namespace logger } // namespace logger


+ 38
- 32
src/logger.cpp View File

@@ -14,6 +14,36 @@ namespace logger {
std::string logPath; std::string logPath;
static FILE* outputFile = NULL; static FILE* outputFile = NULL;
static std::mutex mutex; static std::mutex mutex;
static bool truncated = false;


static bool fileEndsWith(FILE* file, std::string str) {
// Seek to last `len` characters
size_t len = str.size();
std::fseek(file, -long(len), SEEK_END);
char actual[len];
if (std::fread(actual, 1, len, file) != len)
return false;
return std::string(actual, len) == str;
}

static bool isTruncated() {
if (logPath.empty())
return false;

// Open existing log file
FILE* file = std::fopen(logPath.c_str(), "r");
if (!file)
return false;
DEFER({std::fclose(file);});

if (fileEndsWith(file, "END"))
return false;
// legacy <=v1
if (fileEndsWith(file, "Destroying logger\n"))
return false;
return true;
}




void init() { void init() {
@@ -21,11 +51,11 @@ void init() {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);


// Don't open a file in development mode. // Don't open a file in development mode.
if (settings::devMode) {
if (logPath.empty()) {
outputFile = stderr; outputFile = stderr;
} }
else { else {
logPath = asset::user("log.txt");
truncated = isTruncated();


outputFile = std::fopen(logPath.c_str(), "w"); outputFile = std::fopen(logPath.c_str(), "w");
if (!outputFile) { if (!outputFile) {
@@ -53,22 +83,22 @@ static const char* const levelLabels[] = {
"debug", "debug",
"info", "info",
"warn", "warn",
"fatal"
"fatal",
}; };


static const int levelColors[] = { static const int levelColors[] = {
35, 35,
34, 34,
33, 33,
31
31,
}; };


static void logVa(Level level, const char* filename, int line, const char* func, const char* format, va_list args) { static void logVa(Level level, const char* filename, int line, const char* func, const char* format, va_list args) {
std::lock_guard<std::mutex> lock(mutex);
if (!outputFile) if (!outputFile)
return; return;

double nowTime = system::getTime(); double nowTime = system::getTime();
std::lock_guard<std::mutex> lock(mutex);

if (outputFile == stderr) if (outputFile == stderr)
std::fprintf(outputFile, "\x1B[%dm", levelColors[level]); std::fprintf(outputFile, "\x1B[%dm", levelColors[level]);
std::fprintf(outputFile, "[%.03f %s %s:%d %s] ", nowTime, levelLabels[level], filename, line, func); std::fprintf(outputFile, "[%.03f %s %s:%d %s] ", nowTime, levelLabels[level], filename, line, func);
@@ -88,32 +118,8 @@ void log(Level level, const char* filename, int line, const char* func, const ch
va_end(args); va_end(args);
} }


static bool fileEndsWith(FILE* file, std::string str) {
// Seek to last `len` characters
size_t len = str.size();
std::fseek(file, -long(len), SEEK_END);
char actual[len];
if (std::fread(actual, 1, len, file) != len)
return false;
return std::string(actual, len) == str;
}

bool isTruncated() {
if (logPath.empty())
return false;

// Open existing log file
FILE* file = std::fopen(logPath.c_str(), "r");
if (!file)
return false;
DEFER({std::fclose(file);});

if (fileEndsWith(file, "END"))
return false;
// legacy <=v1
if (fileEndsWith(file, "Destroying logger\n"))
return false;
return true;
bool wasTruncated() {
return truncated;
} }






Loading…
Cancel
Save