Рефактор
This commit is contained in:
218
addons/godot-logger/scripts/logger.gd
Normal file
218
addons/godot-logger/scripts/logger.gd
Normal file
@@ -0,0 +1,218 @@
|
||||
# Copyright (c) 2020-2023 Mansur Isaev and contributors - MIT License
|
||||
# See `LICENSE.md` included in the source distribution for details.
|
||||
|
||||
## Logger class.
|
||||
class_name Logger
|
||||
extends Node
|
||||
|
||||
## Emitted when the logger create a message.
|
||||
signal logged(message: Dictionary)
|
||||
|
||||
|
||||
enum {
|
||||
INFO = 1, ## Info level.
|
||||
DEBUG = 1<<1, ## Warning level.
|
||||
WARNING = 1<<2, ## Debug level.
|
||||
ERROR = 1<<3, ## Error level.
|
||||
FATAL = 1<<4, ## Fatal level.
|
||||
MAX = FATAL, ## Bitwise left shift for custom levels.
|
||||
}
|
||||
|
||||
|
||||
var _level : int
|
||||
|
||||
var _log_enabled : bool
|
||||
var _default_output_enabled : bool
|
||||
var _file_write_enabled : bool
|
||||
|
||||
var _file : FileAccess
|
||||
var _file_path : String
|
||||
|
||||
var _format_default_output : String
|
||||
var _format_file : String
|
||||
|
||||
var _names = {
|
||||
INFO: "INFO",
|
||||
DEBUG: "DEBUG",
|
||||
WARNING: "WARNING",
|
||||
ERROR: "ERROR",
|
||||
FATAL: "FATAL"
|
||||
}
|
||||
|
||||
# Can be overridden to define custom default values.
|
||||
func _enter_tree() -> void:
|
||||
set_log_enabled(ProjectSettings.get_setting("plugins/logger/log_enabled", true))
|
||||
set_default_output_enabled(ProjectSettings.get_setting("plugins/logger/default_output", false))
|
||||
|
||||
_level = ProjectSettings.get_setting("plugins/logger/level", INFO | DEBUG | WARNING | ERROR | FATAL)
|
||||
|
||||
set_file_path(ProjectSettings.get_setting("plugins/logger/file/file_path", "user://uarep-ctl.log"))
|
||||
set_file_write_enabled(ProjectSettings.get_setting("plugins/logger/file/log_file_write", true))
|
||||
|
||||
_format_default_output = ProjectSettings.get_setting("plugins/logger/default_output_format", "[{hour}:{minute}:{second}][{level}]{text}")
|
||||
_format_file = ProjectSettings.get_setting("plugins/logger/file_format", "[{hour}:{minute}:{second}][{level}]{text}")
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
_close_file()
|
||||
|
||||
## Return [param true] if logger has level.
|
||||
func has_level(level: int) -> bool:
|
||||
return _names.has(level)
|
||||
|
||||
## Set the level enabled.
|
||||
func set_level(level: int, enabled: bool) -> void:
|
||||
assert(has_level(level), "Invalid level.")
|
||||
if not has_level(level):
|
||||
return
|
||||
|
||||
if enabled:
|
||||
_level |= level
|
||||
else:
|
||||
_level &= ~level
|
||||
|
||||
## Add a custom log level. The level value must be unique and be greater than [member MAX].
|
||||
## To call the custom level use [method message] method.
|
||||
func add_level(level: int, nm: String) -> void:
|
||||
assert(not has_level(level), "Has level.")
|
||||
assert(level > MAX and not level % 2, "Invalid level.")
|
||||
assert(name, "Invalid name.")
|
||||
|
||||
if not has_level(level) and level > MAX and not level % MAX and not name.is_empty():
|
||||
_names[level] = name
|
||||
set_level(level, true)
|
||||
|
||||
## Return the level name.
|
||||
func get_level_name(level: int) -> String:
|
||||
return _names[level]
|
||||
|
||||
## Set Log enabled. Disable ALL messages.
|
||||
func set_log_enabled(enabled: bool) -> void:
|
||||
_log_enabled = enabled
|
||||
|
||||
## Return [param true] if Log enabled.
|
||||
func is_log_enabled() -> bool:
|
||||
return _log_enabled
|
||||
|
||||
## Set default output enabled.
|
||||
func set_default_output_enabled(enabled: bool) -> void:
|
||||
_default_output_enabled = enabled
|
||||
|
||||
## Returns [param true] if default output is enabled.
|
||||
func is_default_output_enabled() -> bool:
|
||||
return _default_output_enabled
|
||||
|
||||
## Set file write enabled.
|
||||
func set_file_write_enabled(enabled: bool) -> void:
|
||||
if _file_write_enabled == enabled:
|
||||
return
|
||||
|
||||
_file_write_enabled = enabled
|
||||
|
||||
if enabled:
|
||||
_open_file()
|
||||
else:
|
||||
_close_file()
|
||||
|
||||
## Returns [param true] if write to a file is enabled.
|
||||
func is_file_write_enabled() -> bool:
|
||||
return _file_write_enabled
|
||||
|
||||
## Set the path to the log file.
|
||||
func set_file_path(path: String) -> void:
|
||||
assert(path.is_absolute_path(), "Invalid path.")
|
||||
if not path.is_absolute_path() or _file_path == path:
|
||||
return
|
||||
|
||||
_file_path = path
|
||||
|
||||
if is_file_write_enabled():
|
||||
_open_file()
|
||||
|
||||
## Return path to log file.
|
||||
func get_file_path() -> String:
|
||||
return _file_path
|
||||
|
||||
## Create an info message.
|
||||
func info(text: String) -> void:
|
||||
message(INFO, text)
|
||||
|
||||
## Create a debug message. Debug build only.
|
||||
func debug(text: String) -> void:
|
||||
if OS.is_debug_build():
|
||||
message(DEBUG, text)
|
||||
|
||||
## Create a warning message.
|
||||
func warning(text: String) -> void:
|
||||
message(WARNING, text)
|
||||
|
||||
## Create an error message.
|
||||
func error(text: String) -> void:
|
||||
message(ERROR, text)
|
||||
|
||||
## Create a fatal error message.
|
||||
func fatal(text: String) -> void:
|
||||
message(FATAL, text)
|
||||
|
||||
## Format string for log file.
|
||||
func format_file(msg: Dictionary) -> String:
|
||||
return _format_file.format(
|
||||
{
|
||||
"hour": "%02d" % msg["hour"],
|
||||
"minute":"%02d" % msg["minute"],
|
||||
"second":"%02d" % msg["second"],
|
||||
"level": _names[msg["level"]],
|
||||
"text": msg["text"],
|
||||
}
|
||||
)
|
||||
|
||||
## Format string for editor output.
|
||||
func format_stdout(msg: Dictionary) -> String:
|
||||
return _format_default_output.format(
|
||||
{
|
||||
"hour": "%02d" % msg["hour"],
|
||||
"minute":"%02d" % msg["minute"],
|
||||
"second":"%02d" % msg["second"],
|
||||
"level": _names[msg["level"]],
|
||||
"text": msg["text"],
|
||||
}
|
||||
)
|
||||
|
||||
## Create a message with a custom level.
|
||||
func message(level: int, text: String) -> void:
|
||||
assert(has_level(level), "Has not level.")
|
||||
assert(text, "Invalid message text.")
|
||||
|
||||
if _log_enabled and _level & level:
|
||||
var msg : Dictionary = Time.get_time_dict_from_system()
|
||||
msg["level"] = level
|
||||
msg["level_name"] = _names[level]
|
||||
msg["text"] = text
|
||||
|
||||
logged.emit(msg)
|
||||
|
||||
if _file_write_enabled:
|
||||
_file.store_line(format_file(msg))
|
||||
|
||||
if _default_output_enabled:
|
||||
print(format_stdout(msg))
|
||||
|
||||
|
||||
func _open_file() -> void:
|
||||
if is_instance_valid(_file) and _file.is_open():
|
||||
_file.close()
|
||||
|
||||
_file = FileAccess.open(get_file_path(), FileAccess.WRITE)
|
||||
|
||||
var err := FileAccess.get_open_error()
|
||||
if err:
|
||||
return print_debug(error_string(err))
|
||||
|
||||
err = _file.get_error()
|
||||
if err:
|
||||
return print_debug(error_string(err))
|
||||
|
||||
|
||||
func _close_file() -> void:
|
||||
if is_instance_valid(_file) and _file.is_open():
|
||||
_file = null
|
||||
76
addons/godot-logger/scripts/logger_output.gd
Normal file
76
addons/godot-logger/scripts/logger_output.gd
Normal file
@@ -0,0 +1,76 @@
|
||||
# Copyright (c) 2020-2023 Mansur Isaev and contributors - MIT License
|
||||
# See `LICENSE.md` included in the source distribution for details.
|
||||
|
||||
@tool
|
||||
## LoggerOutput class.
|
||||
class_name LoggerOutput
|
||||
extends RichTextLabel
|
||||
|
||||
## Emited when handle [signal Logger.logged] signal.
|
||||
signal handled()
|
||||
|
||||
|
||||
@export var format_text : String = "[{hour}:{minute}:{second}][{level}]{text}"
|
||||
@export var colors : Dictionary = {
|
||||
Logger.INFO: Color.WHITE,
|
||||
Logger.DEBUG: Color.GRAY,
|
||||
Logger.WARNING: Color.YELLOW,
|
||||
Logger.ERROR: Color.RED,
|
||||
Logger.FATAL: Color.RED,
|
||||
}
|
||||
|
||||
|
||||
var _logger : Logger
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
var logger := get_node_or_null("/root/Log") as Logger
|
||||
if is_instance_valid(logger):
|
||||
set_logger(logger)
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if is_instance_valid(_logger) and _logger.logged.is_connected(handle_message):
|
||||
_logger.logged.disconnect(handle_message)
|
||||
|
||||
## Return the level color or [member Color.WHITE].
|
||||
func get_color(level: int) -> Color:
|
||||
return colors.get(level, Color.WHITE)
|
||||
|
||||
## Set the logger.
|
||||
func set_logger(logger: Logger) -> void:
|
||||
assert(is_instance_valid(logger), "Invalid Logger.")
|
||||
if not is_instance_valid(logger) or is_same(_logger, logger):
|
||||
return
|
||||
|
||||
if is_instance_valid(_logger) and _logger.logged.is_connected(handle_message):
|
||||
_logger.logged.disconnect(handle_message)
|
||||
|
||||
if not logger.logged.is_connected(handle_message):
|
||||
logger.logged.connect(handle_message)
|
||||
|
||||
_logger = logger
|
||||
|
||||
## Return the logger.
|
||||
func get_logger() -> Logger:
|
||||
return _logger
|
||||
|
||||
## Return formatted string from message.
|
||||
func format(message: Dictionary) -> String:
|
||||
return format_text.format(
|
||||
{
|
||||
"hour": "%02d" % message["hour"],
|
||||
"minute": "%02d" % message["minute"],
|
||||
"second": "%02d" % message["second"],
|
||||
"level": message["level_name"],
|
||||
"text": message["text"],
|
||||
}
|
||||
)
|
||||
|
||||
## Handle the message.
|
||||
func handle_message(message: Dictionary) -> void:
|
||||
push_color(get_color(message["level"]))
|
||||
append_text(format(message) + "\n")
|
||||
pop()
|
||||
|
||||
handled.emit()
|
||||
Reference in New Issue
Block a user