2024-02-12 19:47:28 +01:00
|
|
|
# CORE FRAMEWORK SOURCE FILE
|
|
|
|
# Copyright (c) 2024 The StarOpenSource Project & Contributors
|
2024-03-03 18:53:09 +01:00
|
|
|
# Licensed under the GNU Affero General Public License v3
|
2024-02-12 19:47:28 +01:00
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
2024-03-03 18:53:09 +01:00
|
|
|
# it under the terms of the GNU Affero General Public License as
|
|
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
|
|
# License, or (at your option) any later version.
|
2024-02-12 19:47:28 +01:00
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2024-03-03 18:53:09 +01:00
|
|
|
# GNU Affero General Public License for more details.
|
2024-02-12 19:47:28 +01:00
|
|
|
#
|
2024-03-03 18:53:09 +01:00
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
2024-02-12 19:47:28 +01:00
|
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
## Your usual basic logger implementation, with some extra features.
|
|
|
|
##
|
|
|
|
## Allows for colored output, better newlines, multiple logger levels and a
|
|
|
|
## large variety of placeholders usable in [param config_format].
|
2024-02-04 21:36:30 +01:00
|
|
|
extends CoreBaseModule
|
|
|
|
|
|
|
|
# Signals
|
|
|
|
signal log_event
|
|
|
|
|
|
|
|
# Configuration
|
|
|
|
var config_level: CoreTypes.LoggerLevel
|
|
|
|
var config_colored: bool
|
|
|
|
var config_format: String
|
|
|
|
var config_newlines_override: bool
|
|
|
|
var config_newlines_sizelimit: int
|
|
|
|
|
|
|
|
# Update configuration
|
|
|
|
func _pull_config() -> void:
|
|
|
|
config_level = core.config.logger_level
|
|
|
|
config_colored = core.config.logger_colored
|
|
|
|
config_format = core.config.logger_format
|
|
|
|
config_newlines_override = core.config.logger_newlines_override
|
|
|
|
config_newlines_sizelimit = core.config.logger_newlines_sizelimit
|
|
|
|
|
|
|
|
# Creates log messages
|
2024-03-05 21:32:13 +01:00
|
|
|
func _log(level: CoreTypes.LoggerLevel, origin: String, message: String) -> void:
|
2024-02-04 21:36:30 +01:00
|
|
|
if !is_level_allowed(level):
|
|
|
|
emit_signal("log_event", false, level, origin, message, "")
|
|
|
|
return
|
|
|
|
var format: String = config_format
|
|
|
|
format = format.replace("%time_ms%", str(Time.get_ticks_msec()))
|
|
|
|
format = format.replace("%time%", Time.get_time_string_from_system(true))
|
2024-03-05 21:32:13 +01:00
|
|
|
format = format.replace("%origin%", origin)
|
2024-02-04 21:36:30 +01:00
|
|
|
var format_newline: String = format.replace("%color%", "").replace("%message%", "")
|
|
|
|
if !config_colored: format = format.replace("%color%", "")
|
|
|
|
match(level):
|
|
|
|
CoreTypes.LoggerLevel.DIAG:
|
|
|
|
format = format.replace("%level%", "DIAG")
|
|
|
|
format_newline = format_newline.replace("%level%", "DIAG")
|
2024-02-10 17:26:03 +01:00
|
|
|
format = format.replace("%color%", "[color=dark_gray]")
|
2024-02-04 21:36:30 +01:00
|
|
|
CoreTypes.LoggerLevel.VERB:
|
|
|
|
format = format.replace("%level%", "VERB")
|
|
|
|
format_newline = format_newline.replace("%level%", "VERB")
|
|
|
|
format = format.replace("%color%", "[color=gray]")
|
|
|
|
CoreTypes.LoggerLevel.INFO:
|
|
|
|
format = format.replace("%level%", "INFO")
|
|
|
|
format_newline = format_newline.replace("%level%", "INFO")
|
|
|
|
format = format.replace("%color%", "[color=white]")
|
|
|
|
CoreTypes.LoggerLevel.WARN:
|
|
|
|
format = format.replace("%level%", "WARN")
|
|
|
|
format_newline = format_newline.replace("%level%", "WARN")
|
|
|
|
format = format.replace("%color%", "[color=yellow]")
|
|
|
|
CoreTypes.LoggerLevel.ERROR:
|
|
|
|
format = format.replace("%level%", "ERR!")
|
|
|
|
format_newline = format_newline.replace("%level%", "ERR!")
|
|
|
|
format = format.replace("%color%", "[color=red]")
|
|
|
|
CoreTypes.LoggerLevel.NONE:
|
2024-02-09 15:28:42 +01:00
|
|
|
format = format.replace("%level%", "CRSH")
|
|
|
|
format_newline = format_newline.replace("%level%", "CRSH")
|
|
|
|
format = format.replace("%color%", "[b][color=red]")
|
2024-02-04 21:36:30 +01:00
|
|
|
# Replace %message%
|
|
|
|
if config_newlines_override and config_newlines_sizelimit <= -1 or format_newline.length() <= config_newlines_sizelimit: message = message.replace("\n", "\n" + " ".repeat(format_newline.length()))
|
|
|
|
format = format.replace("%message%", message)
|
|
|
|
emit_signal("log_event", true, level, origin, message, format)
|
|
|
|
if config_colored: print_rich(format)
|
|
|
|
else: print(format)
|
|
|
|
|
|
|
|
# Check if level is allowed
|
|
|
|
func is_level_allowed(level: CoreTypes.LoggerLevel) -> bool:
|
|
|
|
if level <= config_level: return true
|
|
|
|
else: return false
|
|
|
|
|
|
|
|
# Self explanitory
|
2024-03-05 21:32:13 +01:00
|
|
|
func diag(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.DIAG, origin, message)
|
|
|
|
func verb(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.VERB, origin, message)
|
|
|
|
func info(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.INFO, origin, message)
|
|
|
|
func warn(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.WARN, origin, message)
|
|
|
|
func error(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.ERROR, origin, message)
|
2024-02-09 15:28:42 +01:00
|
|
|
|
|
|
|
# Built-in crash handler for CORE and applications using it
|
2024-03-05 21:32:13 +01:00
|
|
|
func crash(origin: String, message: String, framework_crash: bool = false) -> void:
|
2024-02-09 15:28:42 +01:00
|
|
|
# Collect information
|
|
|
|
var stack: Array[Dictionary] = get_stack()
|
|
|
|
var mem_info: Dictionary = OS.get_memory_info()
|
|
|
|
var crash_message: String = """Generating crash report...
|
|
|
|
######################################
|
|
|
|
### CORE CRASH HANDLER ###
|
|
|
|
######################################
|
|
|
|
%causer% inflicted a crash!
|
2024-03-05 21:32:13 +01:00
|
|
|
%origin% says:
|
2024-02-09 15:28:42 +01:00
|
|
|
%message%
|
|
|
|
|
|
|
|
+++ CORE INFORMATION +++
|
|
|
|
VERSION
|
|
|
|
-> Release %version_release%
|
|
|
|
-> Type %version_type%
|
|
|
|
-> Typerelease %version_typerelease%
|
|
|
|
-> Full %version_full%
|
|
|
|
-> SemVer %version_semantic%
|
|
|
|
MODES
|
|
|
|
-> Development %devmode%
|
|
|
|
-> Headless %headless%
|
|
|
|
|
|
|
|
+++ SYSTEM INFORMATION +++
|
|
|
|
OPERATING SYSTEM
|
|
|
|
-> Operating System %os%
|
|
|
|
-> Version %os_version%
|
|
|
|
-> Distribution %os_distribution%
|
|
|
|
LOCALE
|
|
|
|
-> Locale %locale%
|
|
|
|
-> Language %locale_lang%
|
|
|
|
MEMORY
|
|
|
|
-> Free %mem_free%
|
|
|
|
-> Available %mem_avail%
|
|
|
|
-> Used (by engine) %mem_used%
|
|
|
|
-> Total (physical) %mem_total%
|
|
|
|
-> Peak %mem_peak%
|
|
|
|
PROCESSOR
|
|
|
|
-> Name %processor_name%
|
|
|
|
-> Count %processor_count%
|
|
|
|
VIDEO
|
|
|
|
-> Adapter Information %video_adapter%
|
|
|
|
|
|
|
|
+++ GODOT ENGINE INFORMATION +++
|
|
|
|
BUILD
|
|
|
|
-> Debug build %godot_debug%
|
|
|
|
-> Sandboxed %godot_sandboxed%
|
|
|
|
USERDATA
|
|
|
|
-> Persistent %godot_persistance%
|
|
|
|
STACKTRACE
|
|
|
|
%godot_stacktrace%
|
|
|
|
######################################
|
|
|
|
### CORE CRASH HANDLER ###
|
|
|
|
######################################"""
|
|
|
|
# Replace placeholders
|
|
|
|
if framework_crash: crash_message = crash_message.replace("%causer%", "The CORE Framework")
|
|
|
|
else: crash_message = crash_message.replace("%causer%", "The running application")
|
2024-03-05 21:32:13 +01:00
|
|
|
crash_message = crash_message.replace("%origin%", origin)
|
|
|
|
crash_message = crash_message.replace("%message%", message)
|
2024-02-09 15:28:42 +01:00
|
|
|
crash_message = crash_message.replace("%version_release%", str(core.version_release))
|
|
|
|
crash_message = crash_message.replace("%version_type%", await core.get_formatted_string("%type%"))
|
|
|
|
crash_message = crash_message.replace("%version_typerelease%", str(core.version_typerelease))
|
|
|
|
crash_message = crash_message.replace("%version_full%", str(core.version_release) + await core.get_formatted_string("-%type_technical%") + str(core.version_typerelease))
|
|
|
|
crash_message = crash_message.replace("%version_semantic%", await core.get_formatted_string("%release_semantic%"))
|
|
|
|
crash_message = crash_message.replace("%devmode%", str(core.is_devmode()))
|
|
|
|
crash_message = crash_message.replace("%headless%", str(core.config.headless))
|
|
|
|
crash_message = crash_message.replace("%os%", OS.get_name())
|
|
|
|
crash_message = crash_message.replace("%os_version%", OS.get_version())
|
|
|
|
crash_message = crash_message.replace("%os_distribution%", OS.get_distribution_name())
|
|
|
|
crash_message = crash_message.replace("%locale%", OS.get_locale())
|
|
|
|
crash_message = crash_message.replace("%locale_lang%", OS.get_locale_language())
|
|
|
|
crash_message = crash_message.replace("%mem_free%", str(core.misc.mib2gib(core.misc.byte2mib(mem_info["free"], false))) + " GiB")
|
|
|
|
crash_message = crash_message.replace("%mem_avail%", str(core.misc.mib2gib(core.misc.byte2mib(mem_info["available"], false))) + " GiB")
|
|
|
|
crash_message = crash_message.replace("%mem_used%", str(core.misc.byte2mib(OS.get_static_memory_usage())) + " MiB")
|
|
|
|
crash_message = crash_message.replace("%mem_total%", str(core.misc.mib2gib(core.misc.byte2mib(mem_info["physical"], false))) + " GiB")
|
|
|
|
crash_message = crash_message.replace("%mem_peak%", str(core.misc.byte2mib(OS.get_static_memory_peak_usage())) + " MiB")
|
|
|
|
crash_message = crash_message.replace("%processor_name%", OS.get_processor_name())
|
|
|
|
crash_message = crash_message.replace("%processor_count%", str(OS.get_processor_count()))
|
|
|
|
crash_message = crash_message.replace("%video_adapter%", str(OS.get_video_adapter_driver_info()))
|
|
|
|
crash_message = crash_message.replace("%godot_debug%", str(OS.is_debug_build()))
|
|
|
|
crash_message = crash_message.replace("%godot_sandboxed%", str(OS.is_sandboxed()))
|
|
|
|
crash_message = crash_message.replace("%godot_persistance%", str(OS.is_userfs_persistent()))
|
|
|
|
crash_message = crash_message.replace("%godot_stacktrace%", str(stack))
|
|
|
|
# Enable newline overrides
|
|
|
|
config_newlines_override = true
|
|
|
|
config_newlines_sizelimit = -1
|
|
|
|
# Print crash message
|
2024-03-05 21:32:13 +01:00
|
|
|
_log(CoreTypes.LoggerLevel.NONE, origin, crash_message)
|
2024-02-09 15:28:42 +01:00
|
|
|
# Shutdown
|
|
|
|
await core.misc.quit_safely(69)
|
2024-03-05 21:32:13 +01:00
|
|
|
|
|
|
|
# Makes CORE development easier
|
|
|
|
func diagf(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.DIAG, core.basepath.replace("res://", "") + "src/" + origin, message)
|
|
|
|
func verbf(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.VERB, core.basepath.replace("res://", "") + "src/" + origin, message)
|
|
|
|
func infof(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.INFO, core.basepath.replace("res://", "") + "src/" + origin, message)
|
|
|
|
func warnf(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.WARN, core.basepath.replace("res://", "") + "src/" + origin, message)
|
|
|
|
func errorf(origin: String, message: String) -> void: _log(CoreTypes.LoggerLevel.ERROR, core.basepath.replace("res://", "") + "src/" + origin, message)
|
|
|
|
func crashf(origin: String, message: String) -> void: crash(core.basepath.replace("res://", "") + "src/" + origin, message)
|
2024-03-17 22:32:14 +01:00
|
|
|
|
|
|
|
# Returns a logger instance
|
|
|
|
func get_instance(origin: String) -> CoreLoggerInstance: return CoreLoggerInstance.new(logger, origin)
|