2
0

logging.rst 13 KB

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