Доработка. Улучшение документации.

This commit is contained in:
lepshiy
2024-07-25 16:10:22 +03:00
parent bae7a949e4
commit d826f8745c
47 changed files with 3607 additions and 3507 deletions

View File

@@ -33,7 +33,7 @@ Log.fatal(text)
const CUSTOM = Log.MAX << 1 # Bitwise left shift the MAX value for a custom level.
func _ready() -> void:
Log.add_level(CUSTOM, "Level Name")
Log.add_level(CUSTOM, "Level Name")
```
## Calling the custom level:

View File

@@ -14,36 +14,36 @@ const LOGGER_OUTPUT_ICON = "res://addons/godot-logger/icons/logger.svg"
func _def_settings(pname: String, default: Variant) -> void:
if not ProjectSettings.has_setting(pname):
ProjectSettings.set_setting(pname, default)
if not ProjectSettings.has_setting(pname):
ProjectSettings.set_setting(pname, default)
ProjectSettings.set_initial_value(pname, default)
ProjectSettings.set_initial_value(pname, default)
func _enter_tree() -> void:
_def_settings("plugins/logger/log_enabled", true)
_def_settings("plugins/logger/default_output", false)
_def_settings("plugins/logger/log_enabled", true)
_def_settings("plugins/logger/default_output", false)
_def_settings("plugins/logger/level", 31) # The magic number is - INFO | DEBUG | WARNING | ERROR | FATAL
ProjectSettings.add_property_info(
{
"name": "plugins/logger/level",
"type": TYPE_INT,
"hint": PROPERTY_HINT_FLAGS,
"hint_string": "Info,Debug,Warning,Error,Fatal",
}
)
_def_settings("plugins/logger/level", 31) # The magic number is - INFO | DEBUG | WARNING | ERROR | FATAL
ProjectSettings.add_property_info(
{
"name": "plugins/logger/level",
"type": TYPE_INT,
"hint": PROPERTY_HINT_FLAGS,
"hint_string": "Info,Debug,Warning,Error,Fatal",
}
)
_def_settings("plugins/logger/file/file_path", "user://uarep-ctl.log")
_def_settings("plugins/logger/file/log_file_write", true)
_def_settings("plugins/logger/file/file_path", "user://uarep-ctl.log")
_def_settings("plugins/logger/file/log_file_write", true)
_def_settings("plugins/logger/default_output_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
_def_settings("plugins/logger/file_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
_def_settings("plugins/logger/default_output_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
_def_settings("plugins/logger/file_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
add_autoload_singleton(AUTOLOAD_NAME, AUTOLOAD_PATH)
add_custom_type(LOGGER_OUTPUT, "RichTextLabel", load(LOGGER_OUTPUT_SCRIPT), load(LOGGER_OUTPUT_ICON))
add_autoload_singleton(AUTOLOAD_NAME, AUTOLOAD_PATH)
add_custom_type(LOGGER_OUTPUT, "RichTextLabel", load(LOGGER_OUTPUT_SCRIPT), load(LOGGER_OUTPUT_ICON))
func _exit_tree() -> void:
remove_custom_type(LOGGER_OUTPUT)
remove_autoload_singleton(AUTOLOAD_NAME)
remove_custom_type(LOGGER_OUTPUT)
remove_autoload_singleton(AUTOLOAD_NAME)

View File

@@ -1,21 +1,20 @@
# 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
## Класс журнал событий.
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.
INFO = 1, ## Информационный уровень.
DEBUG = 1<<1, ## Уровень предупреждения.
WARNING = 1<<2, ## Уровень отладки.
ERROR = 1<<3, ## Уровень ошибок.
FATAL = 1<<4, ## Критический уровень.
MAX = FATAL, ## Побитовый сдвиг влево для пользовательских уровней.
}
@@ -32,235 +31,235 @@ var _format_default_output : String
var _format_file : String
var _names = {
INFO: "ИНФО",
DEBUG: "ОТЛАДКА",
WARNING: "ВНИМАНИЕ",
ERROR: "ОШИБКА",
FATAL: "АВАРИЯ"
INFO: "ИНФО",
DEBUG: "ОТЛАДКА",
WARNING: "ВНИМАНИЕ",
ERROR: "ОШИБКА",
FATAL: "АВАРИЯ"
}
var _msg_array: Array
var _filters: Array
# 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))
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)
_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))
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", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
_format_file = ProjectSettings.get_setting("plugins/logger/file_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
_format_default_output = ProjectSettings.get_setting("plugins/logger/default_output_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
_format_file = ProjectSettings.get_setting("plugins/logger/file_format", "[{year}-{month}-{day} {hour}:{minute}:{second}][{level}]{text}")
func _exit_tree() -> void:
_close_file()
_close_file()
## Return [param true] if logger has level.
## Возвращает [param true], если у журнала события есть уровень.
func has_level(level: int) -> bool:
return _names.has(level)
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
assert(has_level(level), "Invalid level.")
if not has_level(level):
return
if enabled:
_level |= level
else:
_level &= ~level
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.
## Добавить пользовательский уровень журнала. Значение уровня должно быть уникальным и превышать [member MAX].
## Для вызова пользовательского уровня используйте метод - [method message].
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.")
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] = nm
set_level(level, true)
if not has_level(level) and level > MAX and not level % MAX and not name.is_empty():
_names[level] = nm
set_level(level, true)
## Return the level name.
## Возвращает имя уровня.
func get_level_name(level: int) -> String:
return _names[level]
return _names[level]
## Set Log enabled. Disable ALL messages.
## Установить включенный журнал. Отключить ВСЕ сообщения.
func set_log_enabled(enabled: bool) -> void:
_log_enabled = enabled
_log_enabled = enabled
## Return [param true] if Log enabled.
## Возвращает [param true], если журнал включен.
func is_log_enabled() -> bool:
return _log_enabled
return _log_enabled
## Set default output enabled.
## Установка выхода по умолчанию включена.
func set_default_output_enabled(enabled: bool) -> void:
_default_output_enabled = enabled
_default_output_enabled = enabled
## Returns [param true] if default output is enabled.
## Возвращает [param true], если вывод по умолчанию включен.
func is_default_output_enabled() -> bool:
return _default_output_enabled
return _default_output_enabled
## Set file write enabled.
## Установить разрешение на запись файла.
func set_file_write_enabled(enabled: bool) -> void:
if _file_write_enabled == enabled:
return
if _file_write_enabled == enabled:
return
_file_write_enabled = enabled
_file_write_enabled = enabled
if enabled:
_open_file()
else:
_close_file()
if enabled:
_open_file()
else:
_close_file()
## Returns [param true] if write to a file is enabled.
## Возвращает [param true], если запись в файл разрешена.
func is_file_write_enabled() -> bool:
return _file_write_enabled
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
assert(path.is_absolute_path(), "Invalid path.")
if not path.is_absolute_path() or _file_path == path:
return
_file_path = path
_file_path = path
if is_file_write_enabled():
_open_file()
if is_file_write_enabled():
_open_file()
## Return path to log file.
## Возвращает путь к файлу журнала.
func get_file_path() -> String:
return _file_path
return _file_path
## Create an info message.
## Создать информационное сообщение.
func info(text: String) -> void:
message(INFO, text)
message(INFO, text)
## Create a debug message. Debug build only.
## Создать отладочное сообщение. Только для отладочной сборки.
func debug(text: String) -> void:
if OS.is_debug_build():
message(DEBUG, text)
if OS.is_debug_build():
message(DEBUG, text)
## Create a warning message.
## Создать предупреждающее сообщение.
func warning(text: String) -> void:
message(WARNING, text)
message(WARNING, text)
## Create an error message.
## Создать сообщение об ошибке.
func error(text: String) -> void:
message(ERROR, text)
message(ERROR, text)
## Create a fatal error message.
## Создать сообщение о критической ошибке.
func fatal(text: String) -> void:
message(FATAL, text)
message(FATAL, text)
## Format string for log file.
## Форматировать строку для файла.
func format_file(msg: Dictionary) -> String:
return _format_file.format(
{
"year": "%02d" % msg["year"],
"month": "%02d" % msg["month"],
"day": "%02d" % msg["day"],
"hour": "%02d" % msg["hour"],
"minute":"%02d" % msg["minute"],
"second":"%02d" % msg["second"],
"level": _names[msg["level"]],
"text": msg["text"],
}
)
return _format_file.format(
{
"year": "%02d" % msg["year"],
"month": "%02d" % msg["month"],
"day": "%02d" % msg["day"],
"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(
{
"year": "%02d" % msg["year"],
"month": "%02d" % msg["month"],
"day": "%02d" % msg["day"],
"hour": "%02d" % msg["hour"],
"minute":"%02d" % msg["minute"],
"second":"%02d" % msg["second"],
"level": _names[msg["level"]],
"text": msg["text"],
}
)
return _format_default_output.format(
{
"year": "%02d" % msg["year"],
"month": "%02d" % msg["month"],
"day": "%02d" % msg["day"],
"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.")
assert(has_level(level), "Has not level.")
assert(text, "Invalid message text.")
if _log_enabled and _level & level:
var msg : Dictionary = Time.get_datetime_dict_from_system()
msg["level"] = level
msg["level_name"] = _names[level]
msg["text"] = " " + text
if _log_enabled and _level & level:
var msg : Dictionary = Time.get_datetime_dict_from_system()
msg["level"] = level
msg["level_name"] = _names[level]
msg["text"] = " " + text
_msg_array.append(msg)
if (_flt_msg(msg)):
logged.emit(msg)
_msg_array.append(msg)
if (_flt_msg(msg)):
logged.emit(msg)
if _file_write_enabled:
_file.store_line(format_file(msg))
_file.call_deferred('flush')
if _file_write_enabled:
_file.store_line(format_file(msg))
_file.call_deferred('flush')
if _default_output_enabled:
print(format_stdout(msg))
if _default_output_enabled:
print(format_stdout(msg))
func _open_file() -> void:
if is_instance_valid(_file) and _file.is_open():
_file.close()
if is_instance_valid(_file) and _file.is_open():
_file.close()
_file = FileAccess.open(get_file_path(), FileAccess.READ_WRITE)
_file = FileAccess.open(get_file_path(), FileAccess.READ_WRITE)
var err := FileAccess.get_open_error()
if err:
_file = FileAccess.open(get_file_path(), FileAccess.WRITE)
_file.close()
_file = FileAccess.open(get_file_path(), FileAccess.READ_WRITE)
return print_debug(error_string(err))
var err := FileAccess.get_open_error()
if err:
_file = FileAccess.open(get_file_path(), FileAccess.WRITE)
_file.close()
_file = FileAccess.open(get_file_path(), FileAccess.READ_WRITE)
return print_debug(error_string(err))
err = _file.get_error()
if err:
return print_debug(error_string(err))
_file.seek_end(0)
err = _file.get_error()
if err:
return print_debug(error_string(err))
_file.seek_end(0)
func _close_file() -> void:
if is_instance_valid(_file) and _file.is_open():
_file = null
if is_instance_valid(_file) and _file.is_open():
_file = null
func save_file(path):
var f = FileAccess.open(path, FileAccess.WRITE)
var err := FileAccess.get_open_error()
if err:
print_debug(error_string(err))
var log_text = _file.get_as_text()
f.store_line(log_text)
f.close()
var f = FileAccess.open(path, FileAccess.WRITE)
var err := FileAccess.get_open_error()
if err:
print_debug(error_string(err))
var log_text = _file.get_as_text()
f.store_line(log_text)
f.close()
func set_filtrs(flt_array: Array):
_filters = flt_array
_filters = flt_array
func _flt_msg(msg):
var flt_arr: Array = []
for item in _filters:
if item.button_pressed:
flt_arr.append(item.get_meta('filter'))
if msg['text'].find(item.get_meta('filter')) != -1:
return true
if msg['level_name'] in flt_arr:
return true
return false
var flt_arr: Array = []
for item in _filters:
if item.button_pressed:
flt_arr.append(item.get_meta('filter'))
if msg['text'].find(item.get_meta('filter')) != -1:
return true
if msg['level_name'] in flt_arr:
return true
return false
func add_msgs():
for msg in _msg_array:
if (_flt_msg(msg)):
logged.emit(msg)
for msg in _msg_array:
if (_flt_msg(msg)):
logged.emit(msg)

View File

@@ -2,21 +2,20 @@
# See `LICENSE.md` included in the source distribution for details.
@tool
## LoggerOutput class.
class_name LoggerOutput
extends RichTextLabel
## Класс вывода журнала событий.
class_name LoggerOutput extends RichTextLabel
## Emited when handle [signal Logger.logged] signal.
## Выдаётся при ошибке сигнала - [signal Logger.logged].
signal handled()
@export var format_text : String = "[{year}-{month}-{day} {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,
Logger.INFO: Color.WHITE,
Logger.DEBUG: Color.GRAY,
Logger.WARNING: Color.YELLOW,
Logger.ERROR: Color.RED,
Logger.FATAL: Color.RED,
}
@@ -24,55 +23,55 @@ 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)
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)
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].
## Вернуть цвет уровня или [member Color.WHITE].
func get_color(level: int) -> Color:
return colors.get(level, Color.WHITE)
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
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 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)
if not logger.logged.is_connected(handle_message):
logger.logged.connect(handle_message)
_logger = logger
_logger = logger
## Return the logger.
## Вернуть журнал событий.
func get_logger() -> Logger:
return _logger
return _logger
## Return formatted string from message.
## Вернуть строку после форматирования из сообщения.
func format(message: Dictionary) -> String:
return format_text.format(
{
"year": "%02d" % message["year"],
"month": "%02d" % message["month"],
"day": "%02d" % message["day"],
"hour": "%02d" % message["hour"],
"minute": "%02d" % message["minute"],
"second": "%02d" % message["second"],
"level": message["level_name"],
"text": message["text"],
}
)
return format_text.format(
{
"year": "%02d" % message["year"],
"month": "%02d" % message["month"],
"day": "%02d" % message["day"],
"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()
push_color(get_color(message["level"]))
append_text(format(message) + "\n")
pop()
handled.emit()