mirror of
https://github.com/luanti-org/luanti.git
synced 2025-10-19 11:15:18 +02:00
Make logging timestamps configurable (#16581)
This commit is contained in:
53
doc/luanti.6
53
doc/luanti.6
@@ -1,4 +1,4 @@
|
|||||||
.TH luanti 6 "2 February 2019" "" ""
|
.TH luanti 6 "2025-10-16" "" ""
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
luanti, luantiserver \- voxel game engine
|
luanti, luantiserver \- voxel game engine
|
||||||
@@ -7,12 +7,10 @@ luanti, luantiserver \- voxel game engine
|
|||||||
.B luanti
|
.B luanti
|
||||||
[\fB--server SERVER OPTIONS\fR | \fBCLIENT OPTIONS\fR]
|
[\fB--server SERVER OPTIONS\fR | \fBCLIENT OPTIONS\fR]
|
||||||
[\fBCOMMON OPTIONS\fR]
|
[\fBCOMMON OPTIONS\fR]
|
||||||
[\fBWORLD PATH\fR]
|
|
||||||
|
|
||||||
.B luantiserver
|
.B luantiserver
|
||||||
[\fBSERVER OPTIONS\fR]
|
[\fBSERVER OPTIONS\fR]
|
||||||
[\fBCOMMON OPTIONS\fR]
|
[\fBCOMMON OPTIONS\fR]
|
||||||
[\fBWORLD PATH\fR]
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B Luanti (formerly Minetest) is a voxel game engine with easy modding and game creation.
|
.B Luanti (formerly Minetest) is a voxel game engine with easy modding and game creation.
|
||||||
@@ -43,8 +41,11 @@ Print enormous amounts of information to console
|
|||||||
.B \-\-quiet
|
.B \-\-quiet
|
||||||
Print only errors to console
|
Print only errors to console
|
||||||
.TP
|
.TP
|
||||||
.B \-\-color <value>
|
.B \-\-color always | never | auto
|
||||||
Colorize the logs ('always', 'never' or 'auto'), defaults to 'auto'
|
Coloured logs, default: 'auto'
|
||||||
|
.TP
|
||||||
|
.B \-\-log-timestamp wall | relative | none
|
||||||
|
Timestamped logs, default: 'wall'
|
||||||
.TP
|
.TP
|
||||||
.B \-\-gameid <value> | list
|
.B \-\-gameid <value> | list
|
||||||
Set gameid or list available ones
|
Set gameid or list available ones
|
||||||
@@ -66,14 +67,17 @@ Set network port (UDP) to use
|
|||||||
.TP
|
.TP
|
||||||
.B \-\-run\-unittests
|
.B \-\-run\-unittests
|
||||||
Run unit tests and exit
|
Run unit tests and exit
|
||||||
|
.TP
|
||||||
|
.B \-\-run\-benchmarks
|
||||||
|
Run benchmarks and exit
|
||||||
|
|
||||||
.SH CLIENT OPTIONS
|
.SH CLIENT OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-\-address <value>
|
.B \-\-address <value>
|
||||||
Address to connect to
|
Address to connect to ('' = local game)
|
||||||
.TP
|
.TP
|
||||||
.B \-\-go
|
.B \-\-go
|
||||||
Disable main menu
|
Skip main menu, go directly in-game
|
||||||
.TP
|
.TP
|
||||||
.B \-\-name <value>
|
.B \-\-name <value>
|
||||||
Set player name
|
Set player name
|
||||||
@@ -85,48 +89,47 @@ Set password
|
|||||||
Set password from contents of file
|
Set password from contents of file
|
||||||
.TP
|
.TP
|
||||||
.B \-\-random\-input
|
.B \-\-random\-input
|
||||||
Enable random user input, for testing (client only)
|
Enable random user input (for testing)
|
||||||
.TP
|
|
||||||
.TP
|
|
||||||
.B \-\-speedtests
|
|
||||||
Run speed tests
|
|
||||||
|
|
||||||
.SH SERVER OPTIONS
|
.SH SERVER OPTIONS
|
||||||
.TP
|
.TP
|
||||||
.B \-\-migrate <value>
|
.B \-\-migrate <value>
|
||||||
Migrate from current map backend to another. Possible values are sqlite3,
|
Migrate from current map backend to another. See supported backends
|
||||||
leveldb, redis, postgresql, and dummy.
|
with \-\-help.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-migrate-auth <value>
|
.B \-\-migrate-auth <value>
|
||||||
Migrate from current auth backend to another. Possible values are sqlite3,
|
Migrate from current auth backend to another. See supported backends
|
||||||
leveldb, and files.
|
with \-\-help.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-migrate-players <value>
|
.B \-\-migrate-players <value>
|
||||||
Migrate from current players backend to another. Possible values are sqlite3,
|
Migrate from current players backend to another. See supported backends
|
||||||
leveldb, postgresql, dummy, and files.
|
with \-\-help.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-migrate-mod-storage <value>
|
.B \-\-migrate-mod-storage <value>
|
||||||
Migrate from current mod storage backend to another. Possible values are
|
Migrate from current mod storage backend to another. See supported backends
|
||||||
sqlite3, dummy, and files.
|
with \-\-help.
|
||||||
.TP
|
.TP
|
||||||
.B \-\-terminal
|
.B \-\-terminal
|
||||||
Display an interactive terminal over ncurses during execution.
|
Display an interactive terminal over ncurses during execution.
|
||||||
|
|
||||||
.SH ENVIRONMENT
|
.SH ENVIRONMENT VARIABLES
|
||||||
.TP
|
.TP
|
||||||
.B MINETEST_GAME_PATH
|
.B MINETEST_GAME_PATH
|
||||||
Colon delimited list of directories to search for games.
|
Colon delimited list of directories to search for games
|
||||||
.TP
|
.TP
|
||||||
.B MINETEST_MOD_PATH
|
.B MINETEST_MOD_PATH
|
||||||
Colon delimited list of directories to search for mods.
|
Colon delimited list of directories to search for mods
|
||||||
.TP
|
.TP
|
||||||
.B MINETEST_USER_PATH
|
.B MINETEST_USER_PATH
|
||||||
Path to Luanti user data directory.
|
Path to Luanti user data directory
|
||||||
|
.TP
|
||||||
|
.B LOG_TIMESTAMP
|
||||||
|
Equivalent to \-\-log-timestamp
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
Please report all bugs at https://github.com/luanti-org/luanti/issues.
|
Please report all bugs at https://github.com/luanti-org/luanti/issues.
|
||||||
|
|
||||||
.SH AUTHOR
|
.SH AUTHORS
|
||||||
.PP
|
.PP
|
||||||
Perttu Ahola <celeron55@gmail.com> and contributors.
|
Perttu Ahola <celeron55@gmail.com> and contributors.
|
||||||
.PP
|
.PP
|
||||||
|
24
src/log.cpp
24
src/log.cpp
@@ -220,7 +220,7 @@ const char *Logger::getLevelLabel(LogLevel lev)
|
|||||||
|
|
||||||
LogColor Logger::color_mode = LOG_COLOR_AUTO;
|
LogColor Logger::color_mode = LOG_COLOR_AUTO;
|
||||||
|
|
||||||
const std::string &Logger::getThreadName()
|
inline const std::string &Logger::getThreadName()
|
||||||
{
|
{
|
||||||
std::thread::id id = std::this_thread::get_id();
|
std::thread::id id = std::this_thread::get_id();
|
||||||
|
|
||||||
@@ -237,6 +237,22 @@ const std::string &Logger::getThreadName()
|
|||||||
return fallback_name;
|
return fallback_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogTimestamp Logger::timestamp_mode = LOG_TIMESTAMP_WALL;
|
||||||
|
|
||||||
|
inline std::string Logger::getLogTimestamp()
|
||||||
|
{
|
||||||
|
const static u64 begin_of_time = porting::getTimeMs();
|
||||||
|
if (timestamp_mode == LOG_TIMESTAMP_NONE)
|
||||||
|
return std::string();
|
||||||
|
if (timestamp_mode == LOG_TIMESTAMP_WALL)
|
||||||
|
return getTimestamp();
|
||||||
|
// LOG_TIMESTAMP_RELATIVE
|
||||||
|
float rel = (porting::getTimeMs() - begin_of_time) / 1000.0f;
|
||||||
|
char s[24];
|
||||||
|
snprintf(s, sizeof(s), "[% 8.2f]", rel);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::log(LogLevel lev, std::string_view text)
|
void Logger::log(LogLevel lev, std::string_view text)
|
||||||
{
|
{
|
||||||
if (isLevelSilenced(lev))
|
if (isLevelSilenced(lev))
|
||||||
@@ -244,10 +260,12 @@ void Logger::log(LogLevel lev, std::string_view text)
|
|||||||
|
|
||||||
const std::string &thread_name = getThreadName();
|
const std::string &thread_name = getThreadName();
|
||||||
const char *label = getLevelLabel(lev);
|
const char *label = getLevelLabel(lev);
|
||||||
const std::string timestamp = getTimestamp();
|
const std::string timestamp = getLogTimestamp();
|
||||||
|
|
||||||
std::string line = timestamp;
|
std::string line = timestamp;
|
||||||
line.append(": ").append(label).append("[").append(thread_name)
|
if (!line.empty())
|
||||||
|
line.append(": ");
|
||||||
|
line.append(label).append("[").append(thread_name)
|
||||||
.append("]: ").append(text);
|
.append("]: ").append(text);
|
||||||
|
|
||||||
logToOutputs(lev, line, timestamp, thread_name, text);
|
logToOutputs(lev, line, timestamp, thread_name, text);
|
||||||
|
@@ -28,12 +28,18 @@ enum LogLevel {
|
|||||||
LL_MAX,
|
LL_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LogColor {
|
enum LogColor : u8 {
|
||||||
LOG_COLOR_NEVER,
|
LOG_COLOR_NEVER,
|
||||||
LOG_COLOR_ALWAYS,
|
LOG_COLOR_ALWAYS,
|
||||||
LOG_COLOR_AUTO,
|
LOG_COLOR_AUTO,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum LogTimestamp : u8 {
|
||||||
|
LOG_TIMESTAMP_NONE,
|
||||||
|
LOG_TIMESTAMP_WALL,
|
||||||
|
LOG_TIMESTAMP_RELATIVE
|
||||||
|
};
|
||||||
|
|
||||||
typedef u8 LogLevelMask;
|
typedef u8 LogLevelMask;
|
||||||
#define LOGLEVEL_TO_MASKLEVEL(x) (1 << x)
|
#define LOGLEVEL_TO_MASKLEVEL(x) (1 << x)
|
||||||
|
|
||||||
@@ -65,6 +71,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static LogColor color_mode;
|
static LogColor color_mode;
|
||||||
|
static LogTimestamp timestamp_mode;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void logToOutputsRaw(LogLevel, std::string_view line);
|
void logToOutputsRaw(LogLevel, std::string_view line);
|
||||||
@@ -73,12 +80,13 @@ private:
|
|||||||
std::string_view payload_text);
|
std::string_view payload_text);
|
||||||
|
|
||||||
const std::string &getThreadName();
|
const std::string &getThreadName();
|
||||||
|
static std::string getLogTimestamp();
|
||||||
|
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
std::vector<ILogOutput *> m_outputs[LL_MAX];
|
std::vector<ILogOutput *> m_outputs[LL_MAX];
|
||||||
std::atomic<bool> m_has_outputs[LL_MAX];
|
std::atomic<bool> m_has_outputs[LL_MAX];
|
||||||
std::atomic<bool> m_silenced_levels[LL_MAX];
|
std::atomic<bool> m_silenced_levels[LL_MAX];
|
||||||
std::map<std::thread::id, std::string> m_thread_names;
|
std::map<std::thread::id, std::string> m_thread_names;
|
||||||
mutable std::mutex m_mutex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ILogOutput {
|
class ILogOutput {
|
||||||
|
38
src/main.cpp
38
src/main.cpp
@@ -71,6 +71,7 @@ extern "C" {
|
|||||||
#define ENV_NO_COLOR "NO_COLOR"
|
#define ENV_NO_COLOR "NO_COLOR"
|
||||||
#define ENV_CLICOLOR "CLICOLOR"
|
#define ENV_CLICOLOR "CLICOLOR"
|
||||||
#define ENV_CLICOLOR_FORCE "CLICOLOR_FORCE"
|
#define ENV_CLICOLOR_FORCE "CLICOLOR_FORCE"
|
||||||
|
#define ENV_LOG_TIMESTAMP "LOG_TIMESTAMP"
|
||||||
|
|
||||||
typedef std::map<std::string, ValueSpec> OptionList;
|
typedef std::map<std::string, ValueSpec> OptionList;
|
||||||
|
|
||||||
@@ -293,7 +294,7 @@ static void get_env_opts(Settings &args)
|
|||||||
// CLICOLOR != 0: ANSI colors are supported (auto-detection, this is the default)
|
// CLICOLOR != 0: ANSI colors are supported (auto-detection, this is the default)
|
||||||
// CLICOLOR == 0: ANSI colors are NOT supported
|
// CLICOLOR == 0: ANSI colors are NOT supported
|
||||||
const char *clicolor = std::getenv(ENV_CLICOLOR);
|
const char *clicolor = std::getenv(ENV_CLICOLOR);
|
||||||
if (clicolor && std::string(clicolor) == "0") {
|
if (clicolor && std::string_view(clicolor) == "0") {
|
||||||
args.set("color", "never");
|
args.set("color", "never");
|
||||||
}
|
}
|
||||||
// NO_COLOR only specifies that no color is allowed.
|
// NO_COLOR only specifies that no color is allowed.
|
||||||
@@ -304,10 +305,15 @@ static void get_env_opts(Settings &args)
|
|||||||
}
|
}
|
||||||
// CLICOLOR_FORCE is another option, which should turn on colors "no matter what".
|
// CLICOLOR_FORCE is another option, which should turn on colors "no matter what".
|
||||||
const char *clicolor_force = std::getenv(ENV_CLICOLOR_FORCE);
|
const char *clicolor_force = std::getenv(ENV_CLICOLOR_FORCE);
|
||||||
if (clicolor_force && std::string(clicolor_force) != "0") {
|
if (clicolor_force && std::string_view(clicolor_force) != "0") {
|
||||||
// should ALWAYS have colors, so we ignore tty (no "auto")
|
// should ALWAYS have colors, so we ignore tty (no "auto")
|
||||||
args.set("color", "always");
|
args.set("color", "always");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No standard, Luanti-specific
|
||||||
|
const char *log_ts = std::getenv(ENV_LOG_TIMESTAMP);
|
||||||
|
if (log_ts)
|
||||||
|
args.set("log-timestamp", log_ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_cmdline_opts(int argc, char *argv[], Settings *cmd_args)
|
static bool get_cmdline_opts(int argc, char *argv[], Settings *cmd_args)
|
||||||
@@ -355,8 +361,10 @@ static void set_allowed_options(OptionList *allowed_options)
|
|||||||
"'name' lists names, 'both' lists both)"))));
|
"'name' lists names, 'both' lists both)"))));
|
||||||
allowed_options->insert(std::make_pair("quiet", ValueSpec(VALUETYPE_FLAG,
|
allowed_options->insert(std::make_pair("quiet", ValueSpec(VALUETYPE_FLAG,
|
||||||
_("Print only errors to console"))));
|
_("Print only errors to console"))));
|
||||||
allowed_options->insert(std::make_pair("color", ValueSpec(VALUETYPE_STRING,
|
allowed_options->emplace("color", ValueSpec(VALUETYPE_STRING,
|
||||||
_("Coloured logs ('always', 'never' or 'auto'), defaults to 'auto'"))));
|
_("Coloured logs ('always', 'never' or 'auto'), default: 'auto'")));
|
||||||
|
allowed_options->emplace("log-timestamp", ValueSpec(VALUETYPE_STRING,
|
||||||
|
_("Timestamped logs ('wall', 'relative' or 'none'), default: 'wall'")));
|
||||||
allowed_options->insert(std::make_pair("info", ValueSpec(VALUETYPE_FLAG,
|
allowed_options->insert(std::make_pair("info", ValueSpec(VALUETYPE_FLAG,
|
||||||
_("Print more information to console"))));
|
_("Print more information to console"))));
|
||||||
allowed_options->insert(std::make_pair("verbose", ValueSpec(VALUETYPE_FLAG,
|
allowed_options->insert(std::make_pair("verbose", ValueSpec(VALUETYPE_FLAG,
|
||||||
@@ -524,11 +532,9 @@ static bool setup_log_params(const Settings &cmd_args)
|
|||||||
g_logger.addOutputMaxLevel(&stderr_output, LL_ERROR);
|
g_logger.addOutputMaxLevel(&stderr_output, LL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coloured log messages (see log.h)
|
// Message color
|
||||||
std::string color_mode;
|
std::string color_mode;
|
||||||
if (cmd_args.exists("color")) {
|
cmd_args.getNoEx("color", color_mode);
|
||||||
color_mode = cmd_args.get("color");
|
|
||||||
}
|
|
||||||
if (!color_mode.empty()) {
|
if (!color_mode.empty()) {
|
||||||
if (color_mode == "auto") {
|
if (color_mode == "auto") {
|
||||||
Logger::color_mode = LOG_COLOR_AUTO;
|
Logger::color_mode = LOG_COLOR_AUTO;
|
||||||
@@ -542,6 +548,22 @@ static bool setup_log_params(const Settings &cmd_args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Timestamp
|
||||||
|
std::string ts_mode;
|
||||||
|
cmd_args.getNoEx("log-timestamp", ts_mode);
|
||||||
|
if (!ts_mode.empty()) {
|
||||||
|
if (ts_mode == "wall") {
|
||||||
|
Logger::timestamp_mode = LOG_TIMESTAMP_WALL;
|
||||||
|
} else if (ts_mode == "relative") {
|
||||||
|
Logger::timestamp_mode = LOG_TIMESTAMP_RELATIVE;
|
||||||
|
} else if (ts_mode == "none") {
|
||||||
|
Logger::timestamp_mode = LOG_TIMESTAMP_NONE;
|
||||||
|
} else {
|
||||||
|
errorstream << "Invalid timestamp mode: " << ts_mode << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// In certain cases, output info level on stderr
|
// In certain cases, output info level on stderr
|
||||||
if (cmd_args.getFlag("info") || cmd_args.getFlag("verbose") ||
|
if (cmd_args.getFlag("info") || cmd_args.getFlag("verbose") ||
|
||||||
cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests"))
|
cmd_args.getFlag("trace") || cmd_args.getFlag("speedtests"))
|
||||||
|
Reference in New Issue
Block a user