summaryrefslogtreecommitdiff
path: root/addons/escoria-core/tools/logging
diff options
context:
space:
mode:
authorRadio <radiohotline@disroot.org>2026-06-04 15:15:11 +0300
committerRadio <radiohotline@disroot.org>2026-06-04 15:15:11 +0300
commit9d74b49ab62908d4acf53dde444413886b8b28e5 (patch)
tree0cb785267ea7e239b19d88684c0d64b9bd5d52f0 /addons/escoria-core/tools/logging
parent2c85d452ad02a5f89cd43bad7f9de31d0e4fa0c1 (diff)
escoria setup and old branch archives
Diffstat (limited to 'addons/escoria-core/tools/logging')
-rw-r--r--addons/escoria-core/tools/logging/esc_log_level.gd35
-rw-r--r--addons/escoria-core/tools/logging/esc_log_level.gd.uid1
-rw-r--r--addons/escoria-core/tools/logging/esc_logger.gd462
-rw-r--r--addons/escoria-core/tools/logging/esc_logger.gd.uid1
-rw-r--r--addons/escoria-core/tools/logging/esc_safe_logging.gd60
-rw-r--r--addons/escoria-core/tools/logging/esc_safe_logging.gd.uid1
6 files changed, 560 insertions, 0 deletions
diff --git a/addons/escoria-core/tools/logging/esc_log_level.gd b/addons/escoria-core/tools/logging/esc_log_level.gd
new file mode 100644
index 0000000..517cbf5
--- /dev/null
+++ b/addons/escoria-core/tools/logging/esc_log_level.gd
@@ -0,0 +1,35 @@
+class_name ESCLogLevel
+## Log levels for ESCLogger.
+
+## Valid log levels by order of granularity (E, W, I, D, T)
+enum {
+ LOG_ERROR,
+ LOG_WARNING,
+ LOG_INFO,
+ LOG_DEBUG,
+ LOG_TRACE
+}
+
+
+## A map of log level names to log level ints
+const LEVEL_MAP: Dictionary = {
+ "ERROR": LOG_ERROR,
+ "WARNING": LOG_WARNING,
+ "INFO": LOG_INFO,
+ "DEBUG": LOG_DEBUG,
+ "TRACE": LOG_TRACE,
+}
+
+## Static function to determine the int log level value defined in Project Settings (Escoria>Debug>Log Level)[br]
+## [br]
+## #### Parameters[br]
+## [br]
+## None.
+## [br]
+## #### Returns[br]
+## [br]
+## Returns a `int` value. (`int`)
+static func determine_escoria_log_level() -> int:
+ return LEVEL_MAP[ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.LOG_LEVEL
+ ).to_upper()]
diff --git a/addons/escoria-core/tools/logging/esc_log_level.gd.uid b/addons/escoria-core/tools/logging/esc_log_level.gd.uid
new file mode 100644
index 0000000..d3fee64
--- /dev/null
+++ b/addons/escoria-core/tools/logging/esc_log_level.gd.uid
@@ -0,0 +1 @@
+uid://cfnhsqcchmqbd
diff --git a/addons/escoria-core/tools/logging/esc_logger.gd b/addons/escoria-core/tools/logging/esc_logger.gd
new file mode 100644
index 0000000..26d8d86
--- /dev/null
+++ b/addons/escoria-core/tools/logging/esc_logger.gd
@@ -0,0 +1,462 @@
+## Base class of all logger types.
+class ESCLoggerBase:
+ ## Signal sent when Escoria requires performing an emergency savegame.[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## None.
+ ## [br]
+ signal perform_emergency_savegame
+
+ ## Signal sent when an error or warning happened.[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |message|`Variant`|Error or warning message emitted through the logger.|yes|[br]
+ ## [br]
+ signal error_message_signal(message)
+
+ ## Log filename format
+ const LOG_FILE_FORMAT: String = "log_%s_%s.log"
+
+ # Configured log level
+ var _log_level: int
+
+ ## If true, assert() functions will not be called, thus the program won't
+ ## exit or error. Resets to false after an assert() call was ignored once.
+ ## Useful for console calls.
+ var dont_assert: bool = false
+
+
+ # Constructor
+ func _init():
+ _log_level = ESCLogLevel.determine_escoria_log_level()
+
+ ## Formats a message depending on context, message and letter, then returns it. The formatted string[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |context|`String`|usually, the escoria file that sent the message.|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## |letter|`String`|letter to add to the formatted log (I for Info, W for Warning...)|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns a `String` value. (`String`)
+ func formatted_message(context: String, msg: String, letter: String) -> String:
+ return "ESC ({0}) {1} {2}: {3}".format([_formatted_date(), letter, context, msg])
+
+ ## Trace log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func trace(owner: Object, msg: String):
+ var context: String = owner.get_script().resource_path.get_file()
+ _trace_message(context, msg)
+
+ # Direct message trace log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _trace_message(context: String, msg: String):
+ print(formatted_message(context, msg, "T"))
+
+ ## Debug log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func debug(owner: Object, msg: String):
+ var context: String = owner.get_script().resource_path.get_file()
+ _debug_message(context, msg)
+
+ # Static debug log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _debug_message(context: String, msg: String):
+ print(formatted_message(context, msg, "D"))
+
+ ## Info log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func info(owner: Object, msg: String):
+ var context: String = owner.get_script().resource_path.get_file()
+ _info_message(context, msg)
+
+ # Static info log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _info_message(context: String, msg: String):
+ print(formatted_message(context, msg, "I"))
+
+ ## Warning log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func warn(owner: Object, msg: String):
+ var context: String = owner.get_script().resource_path.get_file()
+ _warn_message(context, msg)
+
+ # Static warning log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _warn_message(context: String, msg: String):
+ print(formatted_message(context, msg, "W"))
+ push_warning(formatted_message(context, msg, "W"))
+ if ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.TERMINATE_ON_WARNINGS
+ ):
+ if not dont_assert:
+ assert(false)
+ escoria.get_tree().quit()
+ dont_assert = false
+ error_message_signal.emit(msg)
+
+ ## Error log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func error(owner: Object, msg: String):
+ var context = owner.get_script().resource_path.get_file()
+ _error_message(context, msg)
+
+ # Static error log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _error_message(context: String, msg: String):
+ printerr(formatted_message(context, msg, "E"))
+ push_error(formatted_message(context, msg, "E"))
+ if ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.TERMINATE_ON_ERRORS
+ ):
+ if not dont_assert:
+ assert(false)
+ escoria.get_tree().quit()
+ dont_assert = false
+ error_message_signal.emit(msg)
+
+ # Formats the current system's datetime as 'YYYY-mm-ddTHH:MM:SS'.
+ func _formatted_date() -> String:
+ var info = Time.get_datetime_dict_from_system()
+ info["year"] = "%04d" % info["year"]
+ info["month"] = "%02d" % info["month"]
+ info["day"] = "%02d" % info["day"]
+ info["hour"] = "%02d" % info["hour"]
+ info["minute"] = "%02d" % info["minute"]
+ info["second"] = "%02d" % info["second"]
+ return "{year}-{month}-{day}T{hour}:{minute}:{second}".format(info)
+
+
+## A logger that logs to the terminal and to a log file.
+class ESCLoggerFile extends ESCLoggerBase:
+ ## Log file handler
+ var log_file: FileAccess
+
+ # Constructor
+ func _init():
+ super()
+ # This is left alone as this constructor is called from escoria.gd's own
+ # constructor
+ var log_file_path = ProjectSettings.get_setting(
+ ESCProjectSettingsManager.LOG_FILE_PATH
+ )
+ var date = Time.get_datetime_dict_from_system()
+ log_file_path = log_file_path.path_join(LOG_FILE_FORMAT % [
+ str(date["year"]) + str(date["month"]) + str(date["day"]),
+ str(date["hour"]) + str(date["minute"]) + str(date["second"])
+ ])
+ log_file = FileAccess.open(
+ log_file_path,
+ FileAccess.WRITE
+ )
+
+ ## Trace log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func trace(owner: Object, msg: String):
+ if _log_level >= ESCLogLevel.LOG_TRACE:
+ _log_to_file(owner, msg, "T")
+ super.trace(owner, msg)
+
+ # Direct message trace log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _trace_message(context: String, msg: String):
+ if _log_level >= ESCLogLevel.LOG_TRACE:
+ _log_to_file_message(context, msg, "T")
+ super._trace_message(context, msg)
+
+ ## Debug log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func debug(owner: Object, msg: String):
+ if _log_level >= ESCLogLevel.LOG_DEBUG:
+ _log_to_file(owner, msg, "D")
+ super.debug(owner, msg)
+
+ # Static debug log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _debug_message(context: String, msg: String):
+ if _log_level >= ESCLogLevel.LOG_DEBUG:
+ _log_to_file_message(context, msg, "D")
+ super._debug_message(context, msg)
+
+ ## Info log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func info(owner: Object, msg: String):
+ if _log_level >= ESCLogLevel.LOG_INFO:
+ _log_to_file(owner, msg, "I")
+ super.info(owner, msg)
+
+ # Static info log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _info_message(context: String, msg: String):
+ if _log_level >= ESCLogLevel.LOG_INFO:
+ _log_to_file_message(context, msg, "I")
+ super._info_message(context, msg)
+
+ ## Warning log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func warn(owner: Object, msg: String):
+ if _log_level >= ESCLogLevel.LOG_WARNING:
+ _log_to_file(owner, msg, "W")
+ if ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.TERMINATE_ON_WARNINGS
+ ):
+ _log_stack_trace_to_file()
+ print_stack()
+ close_logs()
+ super.warn(owner, msg)
+
+ # Static warning log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _warn_message(context: String, msg: String):
+ if _log_level >= ESCLogLevel.LOG_WARNING:
+ _log_to_file_message(context, msg, "W")
+ if ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.TERMINATE_ON_WARNINGS
+ ):
+ _log_stack_trace_to_file()
+ print_stack()
+ close_logs()
+ super._warn_message(context, msg)
+
+ ## Error log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func error(owner: Object, msg: String):
+ if _log_level >= ESCLogLevel.LOG_ERROR:
+ _log_to_file(owner, msg, "E")
+ if ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.TERMINATE_ON_ERRORS
+ ):
+ _log_stack_trace_to_file()
+ print_stack()
+ close_logs()
+ super.error(owner, msg)
+
+ # Static error log (requiring a string for the context)
+ #
+ # #### PARAMETERS
+ #
+ # - owner: caller as a string value
+ # - msg: logged message.
+ func _error_message(context: String, msg: String):
+ if _log_level >= ESCLogLevel.LOG_ERROR:
+ _log_to_file_message(context, msg, "E")
+ if ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.TERMINATE_ON_ERRORS
+ ):
+ _log_stack_trace_to_file()
+ print_stack()
+ close_logs()
+ super._error_message(context, msg)
+
+
+ ## Close the log file cleanly[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## None.
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func close_logs():
+ print("Closing logs peacefully.")
+ _log_line_to_file("Closing logs peacefully.")
+ log_file.close()
+
+ # Log the log message and context to file
+ func _log_to_file(owner: Object, msg: String, letter: String):
+ var context: String
+ if owner != null:
+ context = owner.get_script().resource_path.get_file()
+ _log_to_file_message(context, msg, letter)
+
+ # Log the log message and context as string to file
+ func _log_to_file_message(context: String, msg: String, letter: String):
+ if log_file.is_open():
+ log_file.store_string(formatted_message(context, msg, letter) + "\n")
+
+ # Log the message line to file
+ func _log_line_to_file(msg: String):
+ if log_file.is_open():
+ log_file.store_string(msg + "\n")
+
+ # Log the stack trace to file
+ func _log_stack_trace_to_file():
+ var frame_number = 0
+ for stack in get_stack().slice(2, get_stack().size()):
+ _log_line_to_file(
+ "Frame %s - %s:%s in function '%s'" % [
+ str(frame_number),
+ stack["source"],
+ stack["line"],
+ stack["function"],
+ ]
+ )
+ frame_number += 1
+
+
+## A simple logger that logs to terminal using debug() function
+class ESCLoggerVerbose extends ESCLoggerBase:
+ # Constructor
+ func _init():
+ pass
+
+ ## Debug log[br]
+ ## [br]
+ ## #### Parameters[br]
+ ## [br]
+ ## | Name | Type | Description | Required? |[br]
+ ## |:-----|:-----|:------------|:----------|[br]
+ ## |owner|`Object`|caller object (usually, `self`)|yes|[br]
+ ## |msg|`String`|logged message.|yes|[br]
+ ## [br]
+ ## #### Returns[br]
+ ## [br]
+ ## Returns nothing.
+ func debug(owner: Object, msg: String):
+ var context = owner.get_script().resource_path.get_file()
+ print(context, ": ", msg)
diff --git a/addons/escoria-core/tools/logging/esc_logger.gd.uid b/addons/escoria-core/tools/logging/esc_logger.gd.uid
new file mode 100644
index 0000000..be8df74
--- /dev/null
+++ b/addons/escoria-core/tools/logging/esc_logger.gd.uid
@@ -0,0 +1 @@
+uid://3rkr84aiwrdt
diff --git a/addons/escoria-core/tools/logging/esc_safe_logging.gd b/addons/escoria-core/tools/logging/esc_safe_logging.gd
new file mode 100644
index 0000000..392d71b
--- /dev/null
+++ b/addons/escoria-core/tools/logging/esc_safe_logging.gd
@@ -0,0 +1,60 @@
+# This static class is primarily for situations where there's a possibility that logging to the
+# console may be done by a tool script, and so won't have access to the autoloader/singleton that is
+# `escoria`.
+class_name ESCSafeLogging
+
+
+const COLOUR_RED = "red"
+const COLOUR_GREEN = "green"
+const COLOUR_YELLOW = "yellow"
+
+
+static func log_level() -> String:
+ return ESCProjectSettingsManager.get_setting(
+ ESCProjectSettingsManager.LOG_LEVEL
+ ).to_upper()
+
+
+static func log_error(owner: Object, message: String) -> void:
+ if Engine.is_editor_hint():
+ print_rich("[color=%s]%s[/color]" % [COLOUR_RED, message])
+ else:
+ escoria.logger.error(owner, message)
+
+
+static func log_warn(owner: Object, message: String) -> void:
+ if Engine.is_editor_hint():
+ print_rich("[color=%s]%s[/color]" % [COLOUR_YELLOW, message])
+ else:
+ escoria.logger.warn(owner, message)
+
+
+static func log_info(owner: Object, message: String) -> void:
+ if Engine.is_editor_hint():
+ print(message)
+ else:
+ escoria.logger.info(owner, message)
+
+
+static func log_debug(owner: Object, message: String) -> void:
+ if Engine.is_editor_hint():
+ print(message)
+ else:
+ escoria.logger.debug(owner, message)
+
+
+static func log_trace(owner: Object, message: String) -> void:
+ if Engine.is_editor_hint():
+ print(message)
+ else:
+ escoria.logger.trace(owner, message)
+
+
+# Doesn't correpond to a logging level for offline logging; meant more for messages conveying a result
+static func log_result(owner: Object, message: String, is_successful_result: bool) -> void:
+ var colour: String = COLOUR_GREEN if is_successful_result else COLOUR_RED
+
+ if Engine.is_editor_hint():
+ print_rich("[color=%s]%s[/color]" % [colour, message])
+ else:
+ escoria.logger.info(owner, message)
diff --git a/addons/escoria-core/tools/logging/esc_safe_logging.gd.uid b/addons/escoria-core/tools/logging/esc_safe_logging.gd.uid
new file mode 100644
index 0000000..4e08a9a
--- /dev/null
+++ b/addons/escoria-core/tools/logging/esc_safe_logging.gd.uid
@@ -0,0 +1 @@
+uid://cqexq6xpcccac