Skip to content

Commit 2053bd7

Browse files
committed
Add logging documentation
This also covers how to create custom loggers. - Remove notice on Windows 10 requirement for `print_rich()` in Output panel, since Godot requires Windows 10 as of 4.5.
1 parent 4404daf commit 2053bd7

File tree

5 files changed

+289
-43
lines changed

5 files changed

+289
-43
lines changed

tutorials/io/data_paths.rst

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -114,44 +114,9 @@ through the :ref:`JavaScriptBridge <class_JavaScriptBridge>` singleton.)
114114
File logging
115115
------------
116116

117-
By default, Godot writes log files in ``user://logs/godot.log`` on desktop
118-
platforms. You can change this location by modifying the
119-
``debug/file_logging/log_path`` project setting. Logs are rotated to keep older
120-
files available for inspection. Each session creates a new log file, with the
121-
old file renamed to contain the date at which it was rotated. Up to 5 log files
122-
are kept by default, which can be adjusted using the
123-
``debug/file_logging/max_log_files`` project setting.
124-
125-
File logging can also be disabled completely using the
126-
``debug/file_logging/enable_file_logging`` project setting.
127-
128-
When the project crashes, crash logs are written to the same file as the log
129-
file. The crash log will only contain a usable backtrace if the binary that was
130-
run contains debugging symbols, or if it can find a debug symbols file that
131-
matches the binary. Official binaries don't provide debugging symbols, so this
132-
requires a custom build to work. See
133-
:ref:`Debugging symbols <doc_introduction_to_the_buildsystem_debugging_symbols>`.
134-
for guidance on compiling binaries with debugging symbols enabled.
117+
.. seealso::
135118

136-
.. note::
137-
138-
Log files for :ref:`print<class_@GlobalScope_method_print>`
139-
statements are updated when standard output is *flushed* by the engine.
140-
Standard output is flushed on every print in debug builds only. In projects that
141-
are exported in release mode, standard output is only flushed when the project exits
142-
or crashes to improve performance, especially if the project is often printing
143-
text to standard output.
144-
145-
On the other hand, the standard error stream
146-
(used by :ref:`printerr<class_@GlobalScope_method_printerr>`,
147-
:ref:`push_error<class_@GlobalScope_method_push_error>` and
148-
:ref:`push_warning<class_@GlobalScope_method_push_warning>`) is always
149-
flushed on every print, even in projects exported in release mode.
150-
151-
For some use cases like dedicated servers, it can be preferred to have release
152-
builds always flush stdout on print, so that logging services like journald can
153-
collect logs while the process is running. This can be done by enabling
154-
``application/run/flush_stdout_on_print`` in the Project Settings.
119+
Documentation on file logging has been moved to :ref:`doc_logging`.
155120

156121
Converting paths to absolute paths or "local" paths
157122
---------------------------------------------------

tutorials/scripting/debug/debugger_panel.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ and how that effects performance.
120120
A detailed explanation of how to use the profiler can be found in the
121121
dedicated :ref:`doc_the_profiler` page.
122122

123+
.. _doc_debugger_panel_visual_profiler:
124+
123125
Visual Profiler
124126
---------------
125127

tutorials/scripting/debug/output_panel.rst

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ is controlled by the **Run > Output > Always Clear Output on Play** editor setti
4747
Additionally, you can manually clear messages by clicking the "cleaning brush" icon
4848
in the top-right corner of the Output panel.
4949

50+
.. _doc_output_panel_printing_messages:
51+
5052
Printing messages
5153
-----------------
5254

5355
Several methods are available to print messages:
5456

5557
- :ref:`print() <class_@GlobalScope_method_print>`: Prints a message.
5658
This method accepts multiple arguments which are concatenated together upon printing.
59+
This method has variants that separate arguments with tabs and spaces respectively:
60+
:ref:`prints() <class_@GlobalScope_method_prints>` and :ref:`printt() <class_@GlobalScope_method_printt>`.
5761
- :ref:`print_rich() <class_@GlobalScope_method_print_rich>`: Same as ``print()``,
5862
but BBCode can be used to format the text that is printed (see below).
5963
- :ref:`push_error() <class_@GlobalScope_method_push_error>`: Prints an error message.
@@ -63,9 +67,36 @@ Several methods are available to print messages:
6367
When a warning is printed in a running project, it's displayed in the **Debugger > Errors**
6468
tab instead.
6569

70+
For more complex use cases, these can be used:
71+
72+
- :ref:`print_verbose() <class_@GlobalScope_method_print_verbose>`: Same as ``print()``,
73+
but only prints when verbose mode is enabled in the Project Settings.
74+
- :ref:`printerr() <class_@GlobalScope_method_printerr>`: Same as ``print()``,
75+
but prints to the standard error stream instead of the standard output string.
76+
``push_error()`` should be preferred in most cases.
77+
- :ref:`printraw() <class_@GlobalScope_method_printraw>`: Same as ``print()``,
78+
but prints without a blank line at the end. This is the only method
79+
that does **not** print to the editor Output panel.
80+
It prints to the standard output stream *only*, which means it's still included
81+
in file logging.
82+
- :ref:`print_stack() <class_@GlobalScope_method_print_stack>`: Print a stack trace
83+
from the current location. Only supported when running from the editor,
84+
or when the project is exported in debug mode.
85+
- :ref:`print_tree() <class_@GlobalScope_method_print_tree>`: Prints the scene tree
86+
relative to the current node. Useful for debugging node structures created at runtime.
87+
- :ref:`print_tree_pretty() <class_@GlobalScope_method_print_tree_pretty>`: Same as
88+
``print_tree()``, but with Unicode characters for a more tree-like appearance. This relies on
89+
`box-drawing characters <https://en.wikipedia.org/wiki/Box-drawing_characters>`__,
90+
so it may not render correctly with all fonts.
91+
6692
To get more advanced formatting capabilities, consider using
6793
:ref:`doc_gdscript_printf` along with the above printing functions.
6894

95+
.. seealso::
96+
97+
The engine's logging facilities are covered in the :ref:`logging <doc_logging>`
98+
documentation.
99+
69100
.. _doc_output_panel_printing_rich_text:
70101

71102
Printing rich text
@@ -85,9 +116,5 @@ same colors as they would in the project.
85116

86117
.. note::
87118

88-
ANSI escape code support varies across terminal emulators. On Windows, only
89-
Windows 10 and later can display ANSI escape codes in its default terminal
90-
application.
91-
92-
The exact colors displayed in terminal output also depend on the terminal
93-
theme chosen by the user.
119+
ANSI escape code support varies across terminal emulators. The exact colors
120+
displayed in terminal output also depend on the terminal theme chosen by the user.

tutorials/scripting/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ below will help you make the most of Godot.
5757
singletons_autoload
5858
scene_tree
5959
scene_unique_nodes
60+
logging

tutorials/scripting/logging.rst

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
.. _doc_logging:
2+
3+
Logging
4+
=======
5+
6+
Godot comes with several ways to organize and collect log messages.
7+
8+
Printing messages
9+
-----------------
10+
11+
.. seealso::
12+
13+
See :ref:`doc_output_panel_printing_messages` for instructions on printing
14+
messages. The printed output is generally identical to the logged output.
15+
16+
When running a project from the editor, the editor will display logged text
17+
in the :ref:`doc_output_panel`.
18+
19+
Project settings
20+
----------------
21+
22+
There are several project settings to control logging behavior in Godot:
23+
24+
- **Application > Run > Disable stdout:** Disables logging to standard output entirely.
25+
This also affects what custom loggers receive. This can be controlled at runtime
26+
by setting :ref:`Engine.print_to_stdout <class_Engine_property_print_to_stdout>`.
27+
- **Application > Run > Disable stderr:** Disables logging to standard error entirely.
28+
This also affects what custom loggers receive. This can be controlled at runtime
29+
by setting :ref:`Engine.print_error_messages <class_Engine_property_print_error_messages>`.
30+
- **Debug > Settings > stdout > Verbose stdout:** Enables verbose logging to standard output.
31+
Prints from :ref:`print_verbose() <class_@GlobalScope_method_print_verbose>` are only
32+
visible if verbose mode is enabled.
33+
- **Debug > Settings > stdout > Print FPS:** Prints the frames per second every second,
34+
as well as the V-Sync status on startup (as it can effectively cap the maximum framerate).
35+
- **Debug > Settings > stdout > Print GPU Profile:** Prints a report of GPU utilization
36+
every second, using the same data source as the :ref:`doc_debugger_panel_visual_profiler`.
37+
38+
Some of these project settings can also be overridden using
39+
:ref:`command line arguments <doc_command_line_tutorial>` such as ``--quiet``,
40+
``--verbose`` and ``--print-fps``.
41+
42+
The engine's own file logging is also configurable, as described in the section below.
43+
44+
Built-in file logging
45+
---------------------
46+
47+
By default, Godot writes log files in ``user://logs/godot.log`` on desktop
48+
platforms. You can change this location by modifying the
49+
``debug/file_logging/log_path`` project setting. Logs are rotated to keep older
50+
files available for inspection. Each session creates a new log file, with the
51+
old file renamed to contain the date at which it was rotated. Up to 5 log files
52+
are kept by default, which can be adjusted using the
53+
``debug/file_logging/max_log_files`` project setting.
54+
55+
File logging can also be disabled completely using the
56+
``debug/file_logging/enable_file_logging`` project setting.
57+
58+
When the project crashes, crash logs are written to the same file as the log
59+
file. The crash log will only contain a usable backtrace if the binary that was
60+
run contains debugging symbols, or if it can find a debug symbols file that
61+
matches the binary. Official binaries don't provide debugging symbols, so this
62+
requires a custom build to work. See
63+
:ref:`Debugging symbols <doc_introduction_to_the_buildsystem_debugging_symbols>`.
64+
for guidance on compiling binaries with debugging symbols enabled.
65+
66+
.. note::
67+
68+
Log files for :ref:`print() <class_@GlobalScope_method_print>`
69+
statements are updated when standard output is *flushed* by the engine.
70+
Standard output is flushed on every print in debug builds only. In projects that
71+
are exported in release mode, standard output is only flushed when the project exits
72+
or crashes to improve performance, especially if the project is often printing
73+
text to standard output.
74+
75+
On the other hand, the standard error stream
76+
(used by :ref:`printerr() <class_@GlobalScope_method_printerr>`,
77+
:ref:`push_error() <class_@GlobalScope_method_push_error>` and
78+
:ref:`push_warning() <class_@GlobalScope_method_push_warning>`) is always
79+
flushed on every print, even in projects exported in release mode.
80+
81+
For some use cases like dedicated servers, it can be preferred to have release
82+
builds always flush stdout on print, so that logging services like journald can
83+
collect logs while the process is running. This can be done by enabling
84+
``application/run/flush_stdout_on_print`` in the Project Settings.
85+
86+
Script backtraces
87+
-----------------
88+
89+
Since Godot 4.5, when GDScript code encounters an error, it will log a backtrace that points
90+
to the origin of the error, while also containing the call stack leading to it. This behavior
91+
is always enabled when running in the editor, or when the project is exported in debug mode.
92+
93+
In projects exported in release mode, backtraces are disabled by default for performance reasons.
94+
You can enable them by checking **Debug > Settings > GDScript > Always Track Call Stacks** in
95+
the Project Settings. If you use a custom logging system that reports exceptions to a remote
96+
service, it's recommended to enable this to make reported errors more actionable.
97+
98+
Crash backtraces
99+
----------------
100+
101+
.. warning::
102+
103+
Crash backtraces are only useful if they were recorded in a build that
104+
contains :ref:`debugging symbols <doc_introduction_to_the_buildsystem_debugging_symbols>`.
105+
Official Godot binaries do not contain debugging symbols, so you must compile a
106+
custom editor or export template binary to get useful crash backtraces.
107+
108+
When the project crashes, a crash backtrace is printed to the standard error stream. This is what
109+
it can look like in a build with debug symbols:
110+
111+
::
112+
113+
================================================================
114+
handle_crash: Program crashed with signal 4
115+
Engine version: Godot Engine v4.5.beta.custom_build (6c9aa4c7d3b9b91cd50714c40eeb234874df7075)
116+
Dumping the backtrace. Please include this when reporting the bug to the project developer.
117+
[1] /lib64/libc.so.6(+0x1a070) [0x7f6e5e277070] (??:0)
118+
[2] godot() [0x4da3358] (/path/to/godot/core/core_bind.cpp:336 (discriminator 2))
119+
[3] godot() [0xdf5f2f] (/path/to/godot/modules/gdscript/gdscript.h:591)
120+
[4] godot() [0xbffd46] (/path/to/godot/modules/gdscript/gdscript.cpp:2065 (discriminator 1))
121+
[5] godot() [0x30f2ea4] (/path/to/godot/core/variant/variant.h:870)
122+
[6] godot() [0x550d4e1] (/path/to/godot/core/object/object.cpp:933)
123+
[7] godot() [0x30d996a] (/path/to/godot/scene/main/node.cpp:318 (discriminator 1))
124+
[8] godot() [0x3131a7f] (/path/to/godot/core/templates/hash_map.h:465)
125+
[9] godot() [0x424589] (/path/to/godot/platform/linuxbsd/os_linuxbsd.cpp:970)
126+
[10] /lib64/libc.so.6(+0x3575) [0x7f6e5e260575] (??:0)
127+
[11] /lib64/libc.so.6(__libc_start_main+0x88) [0x7f6e5e260628] (??:0)
128+
[12] godot() [0x464df5] (??:?)
129+
-- END OF C++ BACKTRACE --
130+
================================================================
131+
GDScript backtrace (most recent call first):
132+
[0] _ready (res://test.gd:5)
133+
-- END OF GDSCRIPT BACKTRACE --
134+
================================================================
135+
136+
On the other hand, without debug symbols, it will look like this instead:
137+
138+
::
139+
140+
================================================================
141+
handle_crash: Program crashed with signal 4
142+
Engine version: Godot Engine v4.5.beta.custom_build (6c9aa4c7d3b9b91cd50714c40eeb234874df7075)
143+
Dumping the backtrace. Please include this when reporting the bug to the project developer.
144+
[1] /lib64/libc.so.6(+0x1a070) [0x7fdfaf666070] (??:0)
145+
[2] godot() [0x4da3358] (??:0)
146+
[3] godot() [0xdf5f2f] (??:0)
147+
[4] godot() [0xbffd46] (??:0)
148+
[5] godot() [0x30f2ea4] (??:0)
149+
[6] godot() [0x550d4e1] (??:0)
150+
[7] godot() [0x30d996a] (??:0)
151+
[8] godot() [0x3131a7f] (??:0)
152+
[9] godot() [0x424589] (??:0)
153+
[10] /lib64/libc.so.6(+0x3575) [0x7fdfaf64f575] (??:0)
154+
[11] /lib64/libc.so.6(__libc_start_main+0x88) [0x7fdfaf64f628] (??:0)
155+
[12] godot() [0x464df5] (??:0)
156+
-- END OF C++ BACKTRACE --
157+
================================================================
158+
GDScript backtrace (most recent call first):
159+
[0] _ready (res://test.gd:5)
160+
-- END OF GDSCRIPT BACKTRACE --
161+
================================================================
162+
163+
This backtrace is also logged to the file for the current session, but it is **not**
164+
visible in the editor Output panel. Since the engine's scripting system is not running
165+
anymore when the engine is crashing, it is not possible to access it from scripting in
166+
the same session. However, you can still read the crash backtrace on the next session
167+
by loading log files and searching for the crash backtrace string
168+
(``-- END OF BACKTRACE --``) using :ref:`class_FileAccess`. This allows you to access
169+
the backtrace information even after a crash, as long as the user restarts the application
170+
and file logging is enabled.
171+
172+
You can customize the message that appears at the top of the backtrace using the
173+
**Debug > Settings > Crash Handler > Message** project setting. This can be used
174+
to point to an URL or email address that users can report issues to.
175+
176+
Creating custom loggers
177+
-----------------------
178+
179+
Since Godot 4.5, it is possible to create custom loggers. This custom logging can
180+
be used for many purposes:
181+
182+
- Show an in-game console with the same messages as printed by the engine,
183+
without requiring other scripts to be modified.
184+
- Report printed errors from the player's machine to a remote server.
185+
This can make it easier for developers to fix bugs when the game is already released,
186+
or during playtesting.
187+
- Integrate a dedicated server export with monitoring platforms.
188+
189+
A custom logger can be registered by creating a class that inherits from :ref:`class_logger`,
190+
then passing an instance of this class to :ref:`OS.add_logger <class_OS_method_add_logger>`,
191+
in a script's :ref:`_init() <class_Object_private_method__init>` method. A good place to do this
192+
is an :ref:`autoload <doc_singletons_autoload>`.
193+
194+
The class must define two methods: :ref:`_log_message() <class_Logger_private_method__log_message>`
195+
and :ref:`_log_error() <class_Logger_private_method__log_error>`.
196+
197+
Here is a minimal working example of a custom logger, with the script added as an autoload:
198+
199+
.. code-block:: gdscript
200+
201+
extends Node
202+
203+
class CustomLogger extends Logger:
204+
# Note that this method is not called for messages that use
205+
# `push_error()` and `push_warning()`, even though these are printed to stderr.
206+
func _log_message(message: String, error: bool) -> void:
207+
# Do something with `message`.
208+
# `error` is `true` for messages printed to the standard error stream (stderr) with `print_error()`.
209+
pass
210+
211+
func _log_error(
212+
function: String,
213+
file: String,
214+
line: int,
215+
code: String,
216+
rationale: String,
217+
editor_notify: bool,
218+
error_type: int,
219+
script_backtraces: Array[ScriptBacktrace]
220+
) -> void:
221+
# Do something with the error. The error text is in `rationale`.
222+
# See the Logger class reference for details on other parameters.
223+
pass
224+
225+
# Use `_init()` to initialize the logger as early as possible, which ensures that messages
226+
# printed early are taken into account. However, even when using `_init()`, the engine's own
227+
# initialization messages are not accessible.
228+
func _init() -> void:
229+
OS.add_logger(CustomLogger.new())
230+
231+
Note that to avoid infinite recursion, you cannot effectively use
232+
:ref:`print() <class_@GlobalScope_method_print>` and its related methods in
233+
``_log_message()``. You also can't effectively use
234+
:ref:`push_error() <class_@GlobalScope_method_push_error>`
235+
or :ref:`push_warning() <class_@GlobalScope_method_push_warning>` in
236+
``_log_error()``. Attempting to do so will print a message to the same stream
237+
as the original message. This message is not available in the custom logger,
238+
which is what prevents infinite recursion from occurring:
239+
240+
::
241+
242+
While attempting to print a message, another message was printed:
243+
...
244+
245+
While attempting to print an error, another error was printed:
246+
...
247+
248+
.. seealso::
249+
250+
You can find an example of an in-game console built with a custom logger in the
251+
`Custom Logging demo project <https://github.com/godotengine/godot-demo-projects/tree/master/misc/custom_logging>`__.

0 commit comments

Comments
 (0)