diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index e0d41ab90afc..cbd797273c1e 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -433,16 +433,18 @@ If canvas item redraw debugging is active, this will be the time the flash will last each time they redraw. - If [code]true[/code], logs all output to files. + If [code]true[/code], logs all output and error messages to files. See also [member debug/file_logging/log_path], [member debug/file_logging/max_log_files], and [member application/run/flush_stdout_on_print]. Desktop override for [member debug/file_logging/enable_file_logging], as log files are not readily accessible on mobile/Web platforms. Path at which to store log files for the project. Using a path under [code]user://[/code] is recommended. + This can be specified manually on the command line using the [code]--log-file <file>[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url]. If this command line argument is specified, log rotation is automatically disabled (see [member debug/file_logging/max_log_files]). - Specifies the maximum number of log files allowed (used for rotation). + Specifies the maximum number of log files allowed (used for rotation). Set to [code]1[/code] to disable log file rotation. + If the [code]--log-file <file>[/code] [url=$DOCS_URL/tutorials/editor/command_line_tutorial.html]command line argument[/url] is used, log rotation is always disabled. When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when an [code]assert[/code] call always evaluates to false. diff --git a/main/main.cpp b/main/main.cpp index dbe186d63ab9..1e0869e7f548 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -172,6 +172,7 @@ static bool editor = false; static bool project_manager = false; static bool cmdline_tool = false; static String locale; +static String log_file; static bool show_help = false; static uint64_t quit_after = 0; static OS::ProcessID editor_pid = 0; @@ -450,7 +451,9 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --text-driver Text driver (Fonts, BiDi, shaping).\n"); OS::get_singleton()->print(" --tablet-driver Pen tablet input driver.\n"); OS::get_singleton()->print(" --headless Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script.\n"); - OS::get_singleton()->print(" --write-movie Writes a video to the specified path (usually with .avi or .png extension).\n"); + OS::get_singleton()->print(" --log-file Write output/error log to the specified path instead of the default location defined by the project.\n"); + OS::get_singleton()->print(" path should be absolute or relative to the project directory.\n"); + OS::get_singleton()->print(" --write-movie Write a video to the specified path (usually with .avi or .png extension).\n"); OS::get_singleton()->print(" --fixed-fps is forced when enabled, but it can be used to change movie FPS.\n"); OS::get_singleton()->print(" --disable-vsync can speed up movie writing but makes interaction more difficult.\n"); OS::get_singleton()->print(" --quit-after can be used to specify the number of frames to write.\n"); @@ -1165,6 +1168,15 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph audio_driver = NULL_AUDIO_DRIVER; display_driver = NULL_DISPLAY_DRIVER; + } else if (I->get() == "--log-file") { // write to log file + + if (I->next()) { + log_file = I->next()->get(); + N = I->next()->next(); + } else { + OS::get_singleton()->print("Missing log file path argument, aborting.\n"); + goto error; + } } else if (I->get() == "--profiling") { // enable profiling use_debug_profiler = true; @@ -1689,12 +1701,24 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph GLOBAL_DEF("debug/file_logging/log_path", "user://logs/godot.log"); GLOBAL_DEF(PropertyInfo(Variant::INT, "debug/file_logging/max_log_files", PROPERTY_HINT_RANGE, "0,20,1,or_greater"), 5); - if (!project_manager && !editor && FileAccess::get_create_func(FileAccess::ACCESS_USERDATA) && - GLOBAL_GET("debug/file_logging/enable_file_logging")) { + // If `--log-file` is used to override the log path, allow creating logs for the project manager or editor + // and even if file logging is disabled in the Project Settings. + // `--log-file` can be used with any path (including absolute paths outside the project folder), + // so check for filesystem access if it's used. + if (FileAccess::get_create_func(!log_file.is_empty() ? FileAccess::ACCESS_FILESYSTEM : FileAccess::ACCESS_USERDATA) && + (!log_file.is_empty() || (!project_manager && !editor && GLOBAL_GET("debug/file_logging/enable_file_logging")))) { // Don't create logs for the project manager as they would be written to // the current working directory, which is inconvenient. - String base_path = GLOBAL_GET("debug/file_logging/log_path"); - int max_files = GLOBAL_GET("debug/file_logging/max_log_files"); + String base_path; + int max_files; + if (!log_file.is_empty()) { + base_path = log_file; + // Ensure log file name respects the specified override by disabling log rotation. + max_files = 1; + } else { + base_path = GLOBAL_GET("debug/file_logging/log_path"); + max_files = GLOBAL_GET("debug/file_logging/max_log_files"); + } OS::get_singleton()->add_logger(memnew(RotatedFileLogger(base_path, max_files))); } diff --git a/misc/dist/shell/_godot.zsh-completion b/misc/dist/shell/_godot.zsh-completion index 490af0a8a5a0..f65cf3787050 100644 --- a/misc/dist/shell/_godot.zsh-completion +++ b/misc/dist/shell/_godot.zsh-completion @@ -51,7 +51,8 @@ _arguments \ '--text-driver[set the text driver]:text driver name' \ '--tablet-driver[set the pen tablet input driver]:tablet driver name' \ '--headless[enable headless mode (--display-driver headless --audio-driver Dummy), useful for servers and with --script]' \ - '--write-movie[writes a video to the specified path (usually with .avi or .png extension)]:path to output video file' \ + '--log-file[write output/error log to the specified path instead of the default location defined by the project]:path to output log file' \ + '--write-movie[write a video to the specified path (usually with .avi or .png extension)]:path to output video file' \ '(-f --fullscreen)'{-f,--fullscreen}'[request fullscreen mode]' \ '(-m --maximized)'{-m,--maximized}'[request a maximized window]' \ '(-w --windowed)'{-w,--windowed}'[request windowed mode]' \ diff --git a/misc/dist/shell/godot.bash-completion b/misc/dist/shell/godot.bash-completion index c78f0a1f336e..63efa95c10d3 100644 --- a/misc/dist/shell/godot.bash-completion +++ b/misc/dist/shell/godot.bash-completion @@ -54,6 +54,7 @@ _complete_godot_options() { --text-driver --tablet-driver --headless +--log-file --write-movie --fullscreen --maximized diff --git a/misc/dist/shell/godot.fish b/misc/dist/shell/godot.fish index fbfa7344f11f..3f0675fcb2bc 100644 --- a/misc/dist/shell/godot.fish +++ b/misc/dist/shell/godot.fish @@ -67,7 +67,8 @@ complete -c godot -l gpu-index -d "Use a specific GPU (run with --verbose to get complete -c godot -l text-driver -d "Set the text driver" -x complete -c godot -l tablet-driver -d "Set the pen tablet input driver" -x complete -c godot -l headless -d "Enable headless mode (--display-driver headless --audio-driver Dummy). Useful for servers and with --script" -complete -c godot -l write-movie -d "Writes a video to the specified path (usually with .avi or .png extension). --fixed-fps is forced when enabled" -x +complete -c godot -l log-file -d "Write output/error log to the specified path instead of the default location defined by the project" -x +complete -c godot -l write-movie -d "Write a video to the specified path (usually with .avi or .png extension). --fixed-fps is forced when enabled" -x # Display options: complete -c godot -s f -l fullscreen -d "Request fullscreen mode"