refactor(launcher): Use new core thread and log modules
Keep this a separate commit because this also removes launcher's own logging engine (which was a copy-paste from inject's) and replaces it with the streamlined core API. The core API provides all the features of launcher's own logging engine which also performed horribly. The entire logging operation was locked which included expensive operations that formatted the log messages and required memory allocations and copying around data. This also resulted in switching to AVS's logging engine to perform badly which likely is the/one root cause for reports of game's stuttering and even de-syncing.
This commit is contained in:
@@ -11,6 +11,7 @@ deplibs_launcher := \
|
||||
|
||||
libs_launcher := \
|
||||
avs-util \
|
||||
core \
|
||||
hook \
|
||||
util \
|
||||
dwarfstack \
|
||||
@@ -28,7 +29,6 @@ src_launcher := \
|
||||
hook.c \
|
||||
launcher-config.c \
|
||||
launcher.c \
|
||||
logger.c \
|
||||
main.c \
|
||||
module.c \
|
||||
options.c \
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
|
||||
#include "avs-util/error.h"
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/avs-config.h"
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
#define AVS_CONFIG_ROOT_NODE "/config"
|
||||
@@ -254,26 +255,30 @@ void avs_config_log_count_set(struct property_node *node, uint16_t count)
|
||||
}
|
||||
|
||||
void avs_config_set_log_level(
|
||||
struct property_node *node, enum log_level loglevel)
|
||||
struct property_node *node, enum core_log_bt_log_level loglevel)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
log_assert(node);
|
||||
|
||||
switch (loglevel) {
|
||||
case LOG_LEVEL_FATAL:
|
||||
case CORE_LOG_BT_LOG_LEVEL_OFF:
|
||||
str = "disable";
|
||||
break;
|
||||
|
||||
case CORE_LOG_BT_LOG_LEVEL_FATAL:
|
||||
str = "fatal";
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_WARNING:
|
||||
case CORE_LOG_BT_LOG_LEVEL_WARNING:
|
||||
str = "warn";
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_INFO:
|
||||
case CORE_LOG_BT_LOG_LEVEL_INFO:
|
||||
str = "info";
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_MISC:
|
||||
case CORE_LOG_BT_LOG_LEVEL_MISC:
|
||||
str = "misc";
|
||||
break;
|
||||
|
||||
|
||||
+17
-3
@@ -6,16 +6,17 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-bt.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/avs-config.h"
|
||||
#include "launcher/avs.h"
|
||||
#include "launcher/logger.h"
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/codepage.h"
|
||||
#include "util/fs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
@@ -84,7 +85,7 @@ static AVS_LOG_WRITER(_avs_context_log_writer, chars, nchars, ctx)
|
||||
utf8[utf8_len] = '\0';
|
||||
|
||||
// Write to launcher's dedicated logging backend
|
||||
logger_log_avs_log_message(utf8, utf8_len);
|
||||
core_log_bt_direct_sink_write(utf8, utf8_len);
|
||||
|
||||
/* Clean up */
|
||||
|
||||
@@ -92,6 +93,17 @@ static AVS_LOG_WRITER(_avs_context_log_writer, chars, nchars, ctx)
|
||||
free(utf16);
|
||||
}
|
||||
|
||||
static void _avs_switch_log_engine()
|
||||
{
|
||||
// Switch the logging backend now that AVS is booted to use a single logging
|
||||
// engine which avoids concurrency issues as AVS runs it's own async logger
|
||||
// thread
|
||||
core_log_impl_set(
|
||||
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
|
||||
|
||||
log_misc("Switched logging engine to AVS");
|
||||
}
|
||||
|
||||
void avs_fs_assert_root_device_exists(struct property_node *node)
|
||||
{
|
||||
char root_device_path[PATH_MAX];
|
||||
@@ -242,6 +254,8 @@ void avs_init(
|
||||
node, avs_heap, avs_heap_size, NULL, _avs_context_log_writer, NULL);
|
||||
#endif
|
||||
|
||||
_avs_switch_log_engine();
|
||||
|
||||
log_misc("init done");
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/avs-config.h"
|
||||
@@ -10,7 +12,6 @@
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/hex.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
// clang-format off
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
#define LOG_MODULE "bootstrap"
|
||||
|
||||
#include "core/log-bt.h"
|
||||
#include "core/log-sink-file.h"
|
||||
#include "core/log-sink-list.h"
|
||||
#include "core/log-sink-null.h"
|
||||
#include "core/log-sink-std.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "launcher/avs-config.h"
|
||||
#include "launcher/avs.h"
|
||||
#include "launcher/bootstrap-config.h"
|
||||
@@ -7,11 +14,9 @@
|
||||
#include "launcher/eamuse-config.h"
|
||||
#include "launcher/eamuse.h"
|
||||
#include "launcher/launcher-config.h"
|
||||
#include "launcher/logger.h"
|
||||
#include "launcher/module.h"
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static bool _bootstrap_log_property_configs;
|
||||
@@ -61,22 +66,22 @@ static void _bootstrap_avs_config_log_overrides_apply(
|
||||
avs_config_log_count_set(node, log_config->count);
|
||||
}
|
||||
|
||||
static enum logger_level _bootstrap_log_map_level(const char *level)
|
||||
static enum core_log_bt_log_level _bootstrap_log_map_level(const char *level)
|
||||
{
|
||||
if (str_eq(level, "fatal")) {
|
||||
return LOGGER_LEVEL_FATAL;
|
||||
return CORE_LOG_BT_LOG_LEVEL_FATAL;
|
||||
} else if (str_eq(level, "warning")) {
|
||||
return LOGGER_LEVEL_WARNING;
|
||||
return CORE_LOG_BT_LOG_LEVEL_WARNING;
|
||||
} else if (str_eq(level, "info")) {
|
||||
return LOGGER_LEVEL_INFO;
|
||||
return CORE_LOG_BT_LOG_LEVEL_INFO;
|
||||
} else if (str_eq(level, "misc")) {
|
||||
return LOGGER_LEVEL_MISC;
|
||||
return CORE_LOG_BT_LOG_LEVEL_MISC;
|
||||
} else if (str_eq(level, "all")) {
|
||||
return LOGGER_LEVEL_ALL;
|
||||
return CORE_LOG_BT_LOG_LEVEL_MISC;
|
||||
} else if (str_eq(level, "disable")) {
|
||||
return LOGGER_LEVEL_OFF;
|
||||
return CORE_LOG_BT_LOG_LEVEL_OFF;
|
||||
} else if (str_eq(level, "default")) {
|
||||
return LOGGER_LEVEL_DEFAULT;
|
||||
return CORE_LOG_BT_LOG_LEVEL_WARNING;
|
||||
} else {
|
||||
log_fatal("Unknown log level string %s", level);
|
||||
}
|
||||
@@ -93,22 +98,44 @@ void bootstrap_init(bool log_property_configs)
|
||||
|
||||
void bootstrap_log_init(const struct bootstrap_log_config *config)
|
||||
{
|
||||
enum logger_level level;
|
||||
struct core_log_sink sinks[2];
|
||||
struct core_log_sink sink_composed;
|
||||
enum core_log_bt_log_level level;
|
||||
|
||||
log_assert(config);
|
||||
|
||||
log_info("log init");
|
||||
|
||||
logger_init(
|
||||
config->file,
|
||||
config->enable_console,
|
||||
config->enable_file,
|
||||
config->rotate,
|
||||
config->append,
|
||||
config->count);
|
||||
// Shutdown old setup
|
||||
core_log_bt_fini();
|
||||
|
||||
if (config->enable_file && strlen(config->file) > 0 &&
|
||||
config->enable_console) {
|
||||
core_log_sink_std_out_open(true, &sinks[0]);
|
||||
core_log_sink_file_open(
|
||||
config->file,
|
||||
config->append,
|
||||
config->rotate,
|
||||
config->count,
|
||||
&sinks[1]);
|
||||
core_log_sink_list_open(sinks, 2, &sink_composed);
|
||||
} else if (config->enable_file && strlen(config->file) > 0) {
|
||||
core_log_sink_file_open(
|
||||
config->file,
|
||||
config->append,
|
||||
config->rotate,
|
||||
config->count,
|
||||
&sink_composed);
|
||||
} else if (config->enable_console) {
|
||||
core_log_sink_std_out_open(true, &sink_composed);
|
||||
} else {
|
||||
core_log_sink_null_open(&sink_composed);
|
||||
}
|
||||
|
||||
core_log_bt_init(&sink_composed);
|
||||
|
||||
level = _bootstrap_log_map_level(config->level);
|
||||
logger_level_set(level);
|
||||
core_log_bt_level_set(level);
|
||||
|
||||
log_misc("log init done");
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <stdbool.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "launcher/debug.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "launcher/debug.h"
|
||||
|
||||
void debug_remote_debugger_trap()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/ea3-ident-config.h"
|
||||
@@ -9,7 +11,6 @@
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/hex.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
#define ROOT_NODE "/ea3_conf"
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/ea3-ident-config.h"
|
||||
#include "launcher/eamuse-config.h"
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define EAMUSE_CONFIG_ROOT_NODE "/ea3"
|
||||
|
||||
struct property *eamuse_config_avs_load(const char *path)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#define LOG_MODULE "eamuse"
|
||||
|
||||
#include "imports/avs-ea3.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "imports/avs-ea3.h"
|
||||
|
||||
void eamuse_init(struct property_node *node)
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "launcher/hook.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "launcher/hook.h"
|
||||
|
||||
void hook_load_dll(const char *path)
|
||||
{
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/launcher-config.h"
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "core/log-bt-ext.h"
|
||||
#include "core/log-bt.h"
|
||||
#include "core/log-sink-file.h"
|
||||
#include "core/log-sink-list.h"
|
||||
#include "core/log-sink-std.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs-ea3.h"
|
||||
#include "imports/avs.h"
|
||||
|
||||
@@ -20,40 +27,63 @@
|
||||
#include "launcher/eamuse.h"
|
||||
#include "launcher/hook.h"
|
||||
#include "launcher/launcher-config.h"
|
||||
#include "launcher/logger.h"
|
||||
#include "launcher/module.h"
|
||||
#include "launcher/options.h"
|
||||
#include "launcher/property-util.h"
|
||||
#include "launcher/stubs.h"
|
||||
#include "launcher/version.h"
|
||||
|
||||
#include "procmon-lib/procmon.h"
|
||||
|
||||
#include "util/debug.h"
|
||||
#include "util/defs.h"
|
||||
#include "util/fs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/os.h"
|
||||
#include "util/proc.h"
|
||||
#include "util/signal.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static void _launcher_signal_shutdown_handler()
|
||||
static void _launcher_log_header()
|
||||
{
|
||||
logger_finit();
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
log_info(
|
||||
"\n"
|
||||
" .__ .__ \n"
|
||||
" | | _____ __ __ ____ ____ | |__ ___________ \n"
|
||||
" | | \\__ \\ | | \\/ \\_/ ___\\| | \\_/ __ \\_ __ \\ \n"
|
||||
" | |__/ __ \\| | / | \\ \\___| Y \\ ___/| | \\/ \n"
|
||||
" |____(____ /____/|___| /\\___ >___| /\\___ >__| \n"
|
||||
" \\/ \\/ \\/ \\/ \\/ ");
|
||||
|
||||
log_info(
|
||||
"launcher build date %s, gitrev %s",
|
||||
launcher_build_date,
|
||||
launcher_gitrev);
|
||||
}
|
||||
|
||||
static void _launcher_logger_early_init(const struct options_log *options)
|
||||
void _launcher_log_init(
|
||||
const char *log_file_path, enum core_log_bt_log_level level)
|
||||
{
|
||||
log_assert(options);
|
||||
struct core_log_sink sinks[2];
|
||||
struct core_log_sink sink_composed;
|
||||
|
||||
// Early logging pre AVS setup depend entirely on command args
|
||||
// We don't even have the bootstrap configuration loaded at this point
|
||||
logger_early_init(options->file_path);
|
||||
core_log_bt_ext_impl_set();
|
||||
|
||||
if (options->level) {
|
||||
log_set_level(*(options->level));
|
||||
if (log_file_path) {
|
||||
core_log_sink_std_out_open(true, &sinks[0]);
|
||||
core_log_sink_file_open(log_file_path, false, true, 10, &sinks[1]);
|
||||
core_log_sink_list_open(sinks, 2, &sink_composed);
|
||||
} else {
|
||||
core_log_sink_std_out_open(true, &sink_composed);
|
||||
}
|
||||
|
||||
core_log_bt_init(&sink_composed);
|
||||
core_log_bt_level_set(level);
|
||||
}
|
||||
|
||||
static void _launcher_signal_shutdown_handler()
|
||||
{
|
||||
core_log_bt_fini();
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void _launcher_env_game_dir_verify()
|
||||
@@ -243,7 +273,7 @@ static void _launcher_procmon_init(
|
||||
if (procmon_available()) {
|
||||
procmon_load(procmon);
|
||||
|
||||
procmon->set_loggers(log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
core_log_impl_assign(procmon->set_loggers);
|
||||
procmon->init();
|
||||
|
||||
if (config->procmon_file) {
|
||||
@@ -283,19 +313,23 @@ static void _launcher_bootstrap_log_config_options_override(
|
||||
"Command line override bootstrap log level: %d", *(options->level));
|
||||
|
||||
switch (*(options->level)) {
|
||||
case LOG_LEVEL_FATAL:
|
||||
case CORE_LOG_BT_LOG_LEVEL_OFF:
|
||||
str_cpy(config->level, sizeof(config->level), "disable");
|
||||
break;
|
||||
|
||||
case CORE_LOG_BT_LOG_LEVEL_FATAL:
|
||||
str_cpy(config->level, sizeof(config->level), "fatal");
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_WARNING:
|
||||
case CORE_LOG_BT_LOG_LEVEL_WARNING:
|
||||
str_cpy(config->level, sizeof(config->level), "warn");
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_INFO:
|
||||
case CORE_LOG_BT_LOG_LEVEL_INFO:
|
||||
str_cpy(config->level, sizeof(config->level), "info");
|
||||
break;
|
||||
|
||||
case LOG_LEVEL_MISC:
|
||||
case CORE_LOG_BT_LOG_LEVEL_MISC:
|
||||
str_cpy(config->level, sizeof(config->level), "misc");
|
||||
break;
|
||||
|
||||
@@ -421,6 +455,11 @@ static void _launcher_debugger_break()
|
||||
}
|
||||
}
|
||||
|
||||
void _launcher_log_reinit()
|
||||
{
|
||||
core_log_bt_ext_impl_set();
|
||||
}
|
||||
|
||||
void _launcher_init(
|
||||
const struct options *options,
|
||||
struct launcher_config *launcher_config,
|
||||
@@ -435,9 +474,12 @@ void _launcher_init(
|
||||
log_assert(bootstrap_config);
|
||||
log_assert(ea3_ident_config);
|
||||
|
||||
_launcher_logger_early_init(&options->log);
|
||||
// Early logging pre AVS setup depend entirely on command args
|
||||
// We don't even have the bootstrap configuration loaded at this point
|
||||
_launcher_log_init(options->log.file_path, *(options->log.level));
|
||||
_launcher_log_header();
|
||||
|
||||
debug_init();
|
||||
debug_init(core_log_fatal_impl_get());
|
||||
signal_exception_handler_init(_launcher_signal_shutdown_handler);
|
||||
signal_register_shutdown_handler(&_launcher_signal_shutdown_handler);
|
||||
|
||||
@@ -453,7 +495,9 @@ void _launcher_init(
|
||||
launcher_config_init(launcher_config);
|
||||
|
||||
if (options->launcher.config_path) {
|
||||
log_info("Loading launcher configuration from file: %s", options->launcher.config_path);
|
||||
log_info(
|
||||
"Loading launcher configuration from file: %s",
|
||||
options->launcher.config_path);
|
||||
|
||||
launcher_property = property_util_load(options->launcher.config_path);
|
||||
launcher_config_load(launcher_property, launcher_config);
|
||||
@@ -550,6 +594,8 @@ void _launcher_fini(
|
||||
|
||||
bootstrap_avs_fini();
|
||||
|
||||
_launcher_log_reinit();
|
||||
|
||||
bootstrap_module_game_fini();
|
||||
|
||||
if (procmon->module != NULL) {
|
||||
@@ -560,7 +606,7 @@ void _launcher_fini(
|
||||
|
||||
log_info("Shutdown complete");
|
||||
|
||||
logger_finit();
|
||||
core_log_bt_fini();
|
||||
}
|
||||
|
||||
void launcher_main(const struct options *options)
|
||||
|
||||
@@ -1,365 +0,0 @@
|
||||
#define LOG_MODULE "launcher-logger"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "launcher/logger.h"
|
||||
#include "launcher/version.h"
|
||||
|
||||
#include "util/fs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
static FILE *log_file;
|
||||
static HANDLE log_mutex;
|
||||
|
||||
static const char *logger_get_formatted_timestamp(void)
|
||||
{
|
||||
static char buffer[64];
|
||||
time_t cur = 0;
|
||||
struct tm *tm = NULL;
|
||||
|
||||
cur = time(NULL);
|
||||
tm = localtime(&cur);
|
||||
|
||||
strftime(buffer, sizeof(buffer), "[%Y/%m/%d %H:%M:%S] ", tm);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char logger_console_determine_color(const char *str)
|
||||
{
|
||||
log_assert(str);
|
||||
|
||||
/* Add some color to make spotting warnings/errors easier.
|
||||
Based on debug output level identifier. */
|
||||
|
||||
/* Avoids colored output on strings like "Windows" */
|
||||
if (str[1] != ':') {
|
||||
return 15;
|
||||
}
|
||||
|
||||
switch (str[0]) {
|
||||
/* green */
|
||||
case 'M':
|
||||
return 10;
|
||||
/* blue */
|
||||
case 'I':
|
||||
return 9;
|
||||
/* yellow */
|
||||
case 'W':
|
||||
return 14;
|
||||
/* red */
|
||||
case 'F':
|
||||
return 12;
|
||||
/* default console color */
|
||||
default:
|
||||
return 15;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t logger_msg_coloring_len(const char *str)
|
||||
{
|
||||
// Expected format example: "I:boot: my log message"
|
||||
|
||||
const char *ptr;
|
||||
size_t len;
|
||||
int colon_count;
|
||||
|
||||
ptr = str;
|
||||
len = 0;
|
||||
colon_count = 0;
|
||||
|
||||
while (true) {
|
||||
// End of string = invalid log format
|
||||
if (*ptr == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*ptr == ':') {
|
||||
colon_count++;
|
||||
}
|
||||
|
||||
if (colon_count == 2) {
|
||||
// Skip current colon, next char is a space
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
len++;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void logger_console(
|
||||
void *ctx, const char *chars, size_t nchars, const char *timestamp_str)
|
||||
{
|
||||
char color;
|
||||
size_t color_len;
|
||||
// See "util/log.c", has to align
|
||||
char buffer[65536];
|
||||
char tmp;
|
||||
|
||||
color_len = logger_msg_coloring_len(chars);
|
||||
|
||||
// Check if we could detect which part to color, otherwise just write the
|
||||
// whole log message without any coloring logic
|
||||
if (color_len > 0) {
|
||||
color = logger_console_determine_color(chars);
|
||||
|
||||
strcpy(buffer, chars);
|
||||
|
||||
// Mask start of log message for coloring
|
||||
tmp = buffer[color_len];
|
||||
buffer[color_len] = '\0';
|
||||
|
||||
printf("%s", timestamp_str);
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
|
||||
printf("%s", buffer);
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
|
||||
|
||||
// Write actual message non colored
|
||||
buffer[color_len] = tmp;
|
||||
printf("%s", buffer + color_len);
|
||||
} else {
|
||||
printf("%s", chars);
|
||||
}
|
||||
}
|
||||
|
||||
static void logger_console_avs(const char *chars)
|
||||
{
|
||||
char color;
|
||||
size_t color_len;
|
||||
// See "util/log.c", has to align
|
||||
char buffer[65536];
|
||||
char tmp;
|
||||
const char *timestamp;
|
||||
const char *msg;
|
||||
|
||||
static const size_t timestamp_len = strlen("[----/--/-- --:--:--]");
|
||||
|
||||
timestamp = chars;
|
||||
msg = timestamp + timestamp_len + 1; // +1 is the space
|
||||
|
||||
color_len = logger_msg_coloring_len(msg);
|
||||
|
||||
// Check if we could detect which part to color, otherwise just write the
|
||||
// whole log message without any coloring logic
|
||||
if (color_len > 0) {
|
||||
color = logger_console_determine_color(msg);
|
||||
|
||||
strcpy(buffer, msg);
|
||||
|
||||
// Mask start of log message for coloring
|
||||
tmp = buffer[color_len];
|
||||
buffer[color_len] = '\0';
|
||||
|
||||
printf("%.21s ", timestamp);
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
|
||||
printf("%s", buffer);
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
|
||||
|
||||
// Write actual message non colored
|
||||
buffer[color_len] = tmp;
|
||||
printf("%s\n", buffer + color_len);
|
||||
} else {
|
||||
printf("%s\n", chars);
|
||||
}
|
||||
}
|
||||
|
||||
static void logger_file(
|
||||
void *ctx, const char *chars, size_t nchars, const char *timestamp_str)
|
||||
{
|
||||
if (ctx) {
|
||||
fwrite(timestamp_str, 1, strlen(timestamp_str), (FILE *) ctx);
|
||||
fwrite(chars, 1, nchars, (FILE *) ctx);
|
||||
fflush((FILE *) ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void logger_file_avs(const char *chars, size_t len)
|
||||
{
|
||||
if (log_file) {
|
||||
fwrite(chars, 1, len, log_file);
|
||||
fflush(log_file);
|
||||
}
|
||||
}
|
||||
|
||||
static void logger_writer(void *ctx, const char *chars, size_t nchars)
|
||||
{
|
||||
const char *timestamp_str;
|
||||
|
||||
// Different threads logging the same destination, e.g. debugger thread,
|
||||
// main thread
|
||||
|
||||
WaitForSingleObject(log_mutex, INFINITE);
|
||||
|
||||
timestamp_str = logger_get_formatted_timestamp();
|
||||
|
||||
logger_console(ctx, chars, nchars, timestamp_str);
|
||||
logger_file(ctx, chars, nchars, timestamp_str);
|
||||
|
||||
ReleaseMutex(log_mutex);
|
||||
}
|
||||
|
||||
static void logger_log_header()
|
||||
{
|
||||
log_info(
|
||||
"\n"
|
||||
" .__ .__ \n"
|
||||
" | | _____ __ __ ____ ____ | |__ ___________ \n"
|
||||
" | | \\__ \\ | | \\/ \\_/ ___\\| | \\_/ __ \\_ __ \\ \n"
|
||||
" | |__/ __ \\| | / | \\ \\___| Y \\ ___/| | \\/ \n"
|
||||
" |____(____ /____/|___| /\\___ >___| /\\___ >__| \n"
|
||||
" \\/ \\/ \\/ \\/ \\/ ");
|
||||
|
||||
log_info(
|
||||
"launcher build date %s, gitrev %s",
|
||||
launcher_build_date,
|
||||
launcher_gitrev);
|
||||
}
|
||||
|
||||
void logger_early_init(const char *log_file_path)
|
||||
{
|
||||
if (log_file_path) {
|
||||
log_file = fopen(log_file_path, "w+");
|
||||
} else {
|
||||
log_file = NULL;
|
||||
}
|
||||
|
||||
log_to_writer(logger_writer, log_file);
|
||||
|
||||
logger_log_header();
|
||||
|
||||
if (log_file_path) {
|
||||
log_info("Log file: %s", log_file_path);
|
||||
|
||||
if (!log_file) {
|
||||
log_fatal(
|
||||
"ERROR: Opening log file %s failed: %s",
|
||||
log_file_path,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
log_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
void logger_init(
|
||||
const char *filename,
|
||||
bool enable_console,
|
||||
bool enable_file,
|
||||
bool rotate_file,
|
||||
bool append_file,
|
||||
uint16_t count_file)
|
||||
{
|
||||
// Remark: very basic implementation for now, logger needs a proper cleanup
|
||||
// anyway before implementing more features such as rotation
|
||||
|
||||
if (enable_file) {
|
||||
if (log_file) {
|
||||
// Log file stitching of early log output
|
||||
fseek(log_file, 0, SEEK_END);
|
||||
size_t file_size = ftell(log_file);
|
||||
fseek(log_file, 0, SEEK_SET);
|
||||
|
||||
void *buffer = xmalloc(file_size);
|
||||
|
||||
fread(buffer, file_size, 1, log_file);
|
||||
|
||||
fclose(log_file);
|
||||
|
||||
log_file = fopen(filename, "w+");
|
||||
|
||||
fwrite(buffer, file_size, 1, log_file);
|
||||
fflush(log_file);
|
||||
free(buffer);
|
||||
}
|
||||
} else {
|
||||
if (log_file) {
|
||||
fclose(log_file);
|
||||
log_file = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void logger_level_set(enum logger_level level)
|
||||
{
|
||||
enum log_level internal_level;
|
||||
|
||||
switch (level) {
|
||||
case LOGGER_LEVEL_OFF:
|
||||
case LOGGER_LEVEL_FATAL:
|
||||
internal_level = LOG_LEVEL_FATAL;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_WARNING:
|
||||
internal_level = LOG_LEVEL_WARNING;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_DEFAULT:
|
||||
case LOGGER_LEVEL_INFO:
|
||||
internal_level = LOG_LEVEL_INFO;
|
||||
break;
|
||||
|
||||
case LOGGER_LEVEL_MISC:
|
||||
case LOGGER_LEVEL_ALL:
|
||||
internal_level = LOG_LEVEL_MISC;
|
||||
break;
|
||||
|
||||
default:
|
||||
internal_level = LOG_LEVEL_FATAL;
|
||||
log_assert(false);
|
||||
}
|
||||
|
||||
log_set_level(internal_level);
|
||||
}
|
||||
|
||||
void logger_log_avs_log_message(char *str, size_t len)
|
||||
{
|
||||
bool use_crlf;
|
||||
|
||||
#if AVS_VERSION >= 1500
|
||||
use_crlf = true;
|
||||
#else
|
||||
use_crlf = false;
|
||||
#endif
|
||||
|
||||
// Different threads logging the same destination, e.g. debugger thread,
|
||||
// main thread
|
||||
|
||||
WaitForSingleObject(log_mutex, INFINITE);
|
||||
|
||||
// Write to file first, tokenizing trashes the string
|
||||
logger_file_avs(str, len);
|
||||
|
||||
// The character stream provided here can contain multiple lines as AVS
|
||||
// manages buffered writes to the logger backend. We need to split them
|
||||
// up for the logging backend to allow for further enhancements
|
||||
|
||||
char *line = strtok(str, use_crlf ? "\r\n" : "\n");
|
||||
|
||||
while (line) {
|
||||
logger_console_avs(line);
|
||||
line = strtok(NULL, use_crlf ? "\r\n" : "\n");
|
||||
}
|
||||
|
||||
ReleaseMutex(log_mutex);
|
||||
}
|
||||
|
||||
void logger_finit()
|
||||
{
|
||||
log_misc("Logger finit");
|
||||
|
||||
if (log_file) {
|
||||
fflush(log_file);
|
||||
fclose(log_file);
|
||||
}
|
||||
|
||||
CloseHandle(log_mutex);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#ifndef LAUNCHER_LOGGER_H
|
||||
#define LAUNCHER_LOGGER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum logger_level {
|
||||
LOGGER_LEVEL_OFF = 0,
|
||||
LOGGER_LEVEL_FATAL = 1,
|
||||
LOGGER_LEVEL_WARNING = 2,
|
||||
LOGGER_LEVEL_INFO = 3,
|
||||
LOGGER_LEVEL_MISC = 4,
|
||||
LOGGER_LEVEL_ALL = 5,
|
||||
LOGGER_LEVEL_DEFAULT = 6
|
||||
};
|
||||
|
||||
void logger_early_init(const char *log_file_path);
|
||||
|
||||
void logger_init(
|
||||
const char *filename,
|
||||
bool enable_console,
|
||||
bool enable_file,
|
||||
bool rotate_file,
|
||||
bool append_file,
|
||||
uint16_t count_file);
|
||||
|
||||
void logger_level_set(enum logger_level level);
|
||||
|
||||
/**
|
||||
* Write a log message from AVS to the logging backend.
|
||||
*
|
||||
* @param str String to log
|
||||
* @param len Total length of the log string
|
||||
*/
|
||||
void logger_log_avs_log_message(char *str, size_t len);
|
||||
|
||||
/**
|
||||
* Shutdown and cleanup the logging backend.
|
||||
*/
|
||||
void logger_finit();
|
||||
|
||||
#endif
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "hook/pe.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
@@ -10,7 +12,6 @@
|
||||
#include "launcher/module.h"
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
|
||||
#define MM_ALLOCATION_GRANULARITY 0x10000
|
||||
|
||||
@@ -107,12 +107,14 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
|
||||
long tmp = strtol(argv[++i], NULL, 0);
|
||||
|
||||
if (tmp < LOG_LEVEL_FATAL || tmp > LOG_LEVEL_MISC) {
|
||||
if (tmp < CORE_LOG_BT_LOG_LEVEL_OFF ||
|
||||
tmp > CORE_LOG_BT_LOG_LEVEL_MISC) {
|
||||
return false;
|
||||
}
|
||||
|
||||
options->log.level = xmalloc(sizeof(enum log_level));
|
||||
*(options->log.level) = (enum log_level) tmp;
|
||||
options->log.level =
|
||||
xmalloc(sizeof(enum core_log_bt_log_level));
|
||||
*(options->log.level) = (enum core_log_bt_log_level) tmp;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/log.h"
|
||||
#include "core/log-bt.h"
|
||||
#include "core/log.h"
|
||||
|
||||
#include "launcher/bootstrap-config.h"
|
||||
|
||||
#include "util/array.h"
|
||||
|
||||
// Launcher options (cmd params) are limited to:
|
||||
// - Options to run a (vanilla) game without additional launcher features, e.g.
|
||||
// hooking
|
||||
@@ -28,7 +30,7 @@ struct options {
|
||||
} bootstrap;
|
||||
|
||||
struct options_log {
|
||||
enum log_level *level;
|
||||
enum core_log_bt_log_level *level;
|
||||
const char *file_path;
|
||||
} log;
|
||||
|
||||
|
||||
@@ -9,11 +9,12 @@
|
||||
|
||||
#include "avs-util/error.h"
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
#include "launcher/property-util.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "core/log.h"
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "launcher/stubs.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
|
||||
struct ikey_status {
|
||||
uint32_t field_0;
|
||||
|
||||
Reference in New Issue
Block a user