logger
extends Node
# 项目设置>全局>自动加载 Logger.gd添加为单例,名称为log,其他地方直接用log.info即可打印
# user:// = cat\AppData\Roaming\Godot\app_userdata\rogue_zombie_dongzhou
enum LogLevel { DEBUG, INFO, WARN, ERROR }
var PROJECT_HOME = "user://"
var LOG_DIR = "logs" # 日志存放目录
var LOG_DATE : String
var LOG_OB : FileAccess
var LOG_LEVEL = LogLevel.INFO
func _ready():
_init_log_dir()
_switch_log_date()
func _init_log_dir():
# 确保日志目录存在
var home_ob = DirAccess.open(PROJECT_HOME)
if home_ob and not home_ob.dir_exists(LOG_DIR) and home_ob.make_dir(LOG_DIR) != OK:
print("res://core/base/Logger.gd _init_dir: Failed to create logs directory: %s" % LOG_DIR)
func _switch_log_date():
var current_date = Time.get_date_string_from_system() # 只包含日期
if LOG_DATE == current_date:
return
LOG_DATE = current_date
var log_file_name = "RZD_%s.log" % LOG_DATE
var log_path = "%s%s/%s" % [PROJECT_HOME, LOG_DIR, log_file_name]
var log_ob: FileAccess
if FileAccess.file_exists(log_path):
log_ob = FileAccess.open(log_path, FileAccess.ModeFlags.READ_WRITE) # 追加,不创建
else:
log_ob = FileAccess.open(log_path, FileAccess.ModeFlags.WRITE) # 覆盖,自动创建
if not log_ob:
if LOG_OB:
warn("FileAccess.open log Failed: %s"% LOG_OB.get_path_absolute()) # 创建日志失败,则记录到昨日文件
else:
print("res://core/base/Logger.gd _switch_date: Failed to open log: %s" % LOG_OB.get_path_absolute())
else:
LOG_OB = log_ob # 切换日志文件
info("FileAccess.open log Success: %s"% LOG_OB.get_path_absolute())
func _log(level: LogLevel, message: String):
if level < LOG_LEVEL:
return
# 初始化默认值
var file_path = "UnknownPath"
var file_name = "UnknownFile"
var func_name = "UnknownFunction"
# 获取调用栈并解析
var stacks:Array = get_stack()
if stacks:
var caller: Dictionary = stacks[2] # 获取调用者信息行
if caller:
file_path = caller['source']
file_name = file_path.split("/")[-1]
func_name = "%s(%s)"%[caller['function'], caller['line']]
var level_str
match level:
LogLevel.DEBUG:
level_str = "DEBUG"
LogLevel.INFO:
level_str = "INFO"
LogLevel.WARN:
level_str = "WARN"
LogLevel.ERROR:
level_str = "ERROR"
_:
level_str = "UNKNOWN"
var timestamp = Time.get_datetime_string_from_system(false) # 服务器实际时间
var log_entry = "%s %s %s %s: %s" % [timestamp, level_str, file_name, func_name, message]
# 控制台
print(log_entry)
# 日志文件
_switch_log_date()
if LOG_OB:
LOG_OB.seek_end()
LOG_OB.store_line(log_entry)
func debug(arg1, arg2="", arg3="", arg4=""):
_log(LogLevel.DEBUG, _combine_args([arg1, arg2, arg3, arg4]))
func info(arg1, arg2="", arg3="", arg4=""):
_log(LogLevel.INFO, _combine_args([arg1, arg2, arg3, arg4]))
func warning(arg1, arg2="", arg3="", arg4=""): warn(arg1, arg2, arg3, arg4)
func warn(arg1, arg2="", arg3="", arg4=""):
_log(LogLevel.WARN, _combine_args([arg1, arg2, arg3, arg4]))
func error(arg1, arg2="", arg3="", arg4=""):
_log(LogLevel.ERROR, _combine_args([arg1, arg2, arg3, arg4]))
# 私有方法:将可变参数组合为字符串
func _combine_args(args: Array) -> String:
return " ".join(args)
func set_level(level: LogLevel):
# 从枚举里获得名称
info("%s --> %s" % [LogLevel.find_key(LOG_LEVEL), LogLevel.find_key(level)])
LOG_LEVEL = level
func _exit_tree():
if LOG_OB:
LOG_OB.close()