Skip to content

Commit

Permalink
Core: Refactor log_error to unify color handling
Browse files Browse the repository at this point in the history
• Can now detect & output color on CI
  • Loading branch information
Repiteo committed Dec 22, 2024
1 parent 0454122 commit 643187d
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 126 deletions.
29 changes: 11 additions & 18 deletions core/io/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,34 +55,27 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c
return;
}

const char *err_type = "ERROR";
const char *err_details = p_rationale && p_rationale[0] ? p_rationale : p_code;

switch (p_type) {
case ERR_ERROR:
err_type = "ERROR";
break;
case ERR_WARNING:
err_type = "WARNING";
logf_error("WARNING: %s\n", err_details);
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
break;
case ERR_SCRIPT:
err_type = "SCRIPT ERROR";
logf_error("SCRIPT ERROR: %s\n", err_details);
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
break;
case ERR_SHADER:
err_type = "SHADER ERROR";
logf_error("SHADER ERROR: %s\n", err_details);
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
break;
case ERR_ERROR:
default:
ERR_PRINT("Unknown error type");
logf_error("ERROR: %s\n", err_details);
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
break;
}

const char *err_details;
if (p_rationale && *p_rationale) {
err_details = p_rationale;
} else {
err_details = p_code;
}

logf_error("%s: %s\n", err_type, err_details);
logf_error(" at: %s (%s:%i)\n", p_function, p_file, p_line);
}

void Logger::logf(const char *p_format, ...) {
Expand Down
31 changes: 13 additions & 18 deletions drivers/unix/os_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,27 +1050,22 @@ void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, i
return;
}

const char *err_details;
if (p_rationale && p_rationale[0]) {
err_details = p_rationale;
} else {
err_details = p_code;
}
const char *err_details = p_rationale && p_rationale[0] ? p_rationale : p_code;

// Disable color codes if stdout is not a TTY.
// Disable color codes if stdout is not a TTY or CI.
// This prevents Godot from writing ANSI escape codes when redirecting
// stdout and stderr to a file.
const bool tty = isatty(fileno(stdout));
const char *gray = tty ? "\E[0;90m" : "";
const char *red = tty ? "\E[0;91m" : "";
const char *red_bold = tty ? "\E[1;31m" : "";
const char *yellow = tty ? "\E[0;93m" : "";
const char *yellow_bold = tty ? "\E[1;33m" : "";
const char *magenta = tty ? "\E[0;95m" : "";
const char *magenta_bold = tty ? "\E[1;35m" : "";
const char *cyan = tty ? "\E[0;96m" : "";
const char *cyan_bold = tty ? "\E[1;36m" : "";
const char *reset = tty ? "\E[0m" : "";
const bool color = OS::get_singleton()->has_environment("CI") || OS::get_singleton()->get_stdout_type() == OS::STD_HANDLE_CONSOLE;
const char *gray = color ? "\u001b[0;90m" : "";
const char *red = color ? "\u001b[0;31m" : "";
const char *red_bold = color ? "\u001b[1;31m" : "";
const char *yellow = color ? "\u001b[0;33m" : "";
const char *yellow_bold = color ? "\u001b[1;33m" : "";
const char *magenta = color ? "\u001b[0;35m" : "";
const char *magenta_bold = color ? "\u001b[1;35m" : "";
const char *cyan = color ? "\u001b[0;36m" : "";
const char *cyan_bold = color ? "\u001b[1;36m" : "";
const char *reset = color ? "\u001b[0m" : "";

switch (p_type) {
case ERR_WARNING:
Expand Down
40 changes: 26 additions & 14 deletions platform/macos/macos_terminal_logger.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,49 +32,61 @@

#ifdef MACOS_ENABLED

#include "core/os/os.h"

#include <os/log.h>

void MacOSTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) {
if (!should_log(true)) {
return;
}

const char *err_details;
if (p_rationale && p_rationale[0]) {
err_details = p_rationale;
} else {
err_details = p_code;
}
const char *err_details = p_rationale && p_rationale[0] ? p_rationale : p_code;

// Disable color codes if stdout is not a TTY or CI.
// This prevents Godot from writing ANSI escape codes when redirecting
// stdout and stderr to a file.
const bool color = OS::get_singleton()->has_environment("CI") || OS::get_singleton()->get_stdout_type() == OS::STD_HANDLE_CONSOLE;
const char *gray = color ? "\u001b[0;90m" : "";
const char *red = color ? "\u001b[0;31m" : "";
const char *red_bold = color ? "\u001b[1;31m" : "";
const char *yellow = color ? "\u001b[0;33m" : "";
const char *yellow_bold = color ? "\u001b[1;33m" : "";
const char *magenta = color ? "\u001b[0;35m" : "";
const char *magenta_bold = color ? "\u001b[1;35m" : "";
const char *cyan = color ? "\u001b[0;36m" : "";
const char *cyan_bold = color ? "\u001b[1;36m" : "";
const char *reset = color ? "\u001b[0m" : "";

switch (p_type) {
case ERR_WARNING:
os_log_info(OS_LOG_DEFAULT,
"WARNING: %{public}s\nat: %{public}s (%{public}s:%i)",
err_details, p_function, p_file, p_line);
logf_error("\E[1;33mWARNING:\E[0;93m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
logf_error("%sWARNING:%s %s\n", yellow_bold, yellow, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
case ERR_SCRIPT:
os_log_error(OS_LOG_DEFAULT,
"SCRIPT ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
err_details, p_function, p_file, p_line);
logf_error("\E[1;35mSCRIPT ERROR:\E[0;95m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
logf_error("%sSCRIPT ERROR:%s %s\n", magenta_bold, magenta, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
case ERR_SHADER:
os_log_error(OS_LOG_DEFAULT,
"SHADER ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
err_details, p_function, p_file, p_line);
logf_error("\E[1;36mSHADER ERROR:\E[0;96m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
logf_error("%sSHADER ERROR:%s %s\n", cyan_bold, cyan, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
case ERR_ERROR:
default:
os_log_error(OS_LOG_DEFAULT,
"ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
err_details, p_function, p_file, p_line);
logf_error("\E[1;31mERROR:\E[0;91m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
logf_error("%sERROR:%s %s\n", red_bold, red, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
}
}
Expand Down
113 changes: 37 additions & 76 deletions platform/windows/windows_terminal_logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@

#include "windows_terminal_logger.h"

#include "core/os/os.h"

#ifdef WINDOWS_ENABLED

#include "core/os/os.h"

#include <stdio.h>

#define WIN32_LEAN_AND_MEAN
Expand Down Expand Up @@ -79,80 +79,41 @@ void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file
return;
}

HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
if (OS::get_singleton()->get_stdout_type() != OS::STD_HANDLE_CONSOLE || !hCon || hCon == INVALID_HANDLE_VALUE) {
StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
} else {
CONSOLE_SCREEN_BUFFER_INFO sbi; //original
GetConsoleScreenBufferInfo(hCon, &sbi);

WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);

uint32_t basecol = 0;
switch (p_type) {
case ERR_ERROR:
basecol = FOREGROUND_RED;
break;
case ERR_WARNING:
basecol = FOREGROUND_RED | FOREGROUND_GREEN;
break;
case ERR_SCRIPT:
basecol = FOREGROUND_RED | FOREGROUND_BLUE;
break;
case ERR_SHADER:
basecol = FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
}

basecol |= current_bg;

SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR:
logf_error("ERROR:");
break;
case ERR_WARNING:
logf_error("WARNING:");
break;
case ERR_SCRIPT:
logf_error("SCRIPT ERROR:");
break;
case ERR_SHADER:
logf_error("SHADER ERROR:");
break;
}

SetConsoleTextAttribute(hCon, basecol);
if (p_rationale && p_rationale[0]) {
logf_error(" %s\n", p_rationale);
} else {
logf_error(" %s\n", p_code);
}

// `FOREGROUND_INTENSITY` alone results in gray text.
SetConsoleTextAttribute(hCon, FOREGROUND_INTENSITY);
switch (p_type) {
case ERR_ERROR:
logf_error(" at: ");
break;
case ERR_WARNING:
logf_error(" at: ");
break;
case ERR_SCRIPT:
logf_error(" at: ");
break;
case ERR_SHADER:
logf_error(" at: ");
break;
}

if (p_rationale && p_rationale[0]) {
logf_error("(%s:%i)\n", p_file, p_line);
} else {
logf_error("%s (%s:%i)\n", p_function, p_file, p_line);
}

SetConsoleTextAttribute(hCon, sbi.wAttributes);
const char *err_details = p_rationale && p_rationale[0] ? p_rationale : p_code;

// Disable color codes if stdout is not a TTY or CI.
// This prevents Godot from writing ANSI escape codes when redirecting
// stdout and stderr to a file.
const bool color = OS::get_singleton()->has_environment("CI") || OS::get_singleton()->get_stdout_type() == OS::STD_HANDLE_CONSOLE;
const char *gray = color ? "\u001b[0;90m" : "";
const char *red = color ? "\u001b[0;31m" : "";
const char *red_bold = color ? "\u001b[1;31m" : "";
const char *yellow = color ? "\u001b[0;33m" : "";
const char *yellow_bold = color ? "\u001b[1;33m" : "";
const char *magenta = color ? "\u001b[0;35m" : "";
const char *magenta_bold = color ? "\u001b[1;35m" : "";
const char *cyan = color ? "\u001b[0;36m" : "";
const char *cyan_bold = color ? "\u001b[1;36m" : "";
const char *reset = color ? "\u001b[0m" : "";

switch (p_type) {
case ERR_WARNING:
logf_error("%sWARNING:%s %s\n", yellow_bold, yellow, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
case ERR_SCRIPT:
logf_error("%sSCRIPT ERROR:%s %s\n", magenta_bold, magenta, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
case ERR_SHADER:
logf_error("%sSHADER ERROR:%s %s\n", cyan_bold, cyan, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
case ERR_ERROR:
default:
logf_error("%sERROR:%s %s\n", red_bold, red, err_details);
logf_error("%s at: %s (%s:%i)%s\n", gray, p_function, p_file, p_line, reset);
break;
}
}

Expand Down

0 comments on commit 643187d

Please sign in to comment.