@@ -32,6 +32,7 @@ static func _static_init() -> void:
32
32
_ensure_setting_exists (settings .LOG_MESSAGE_FORMAT_KEY , settings .LOG_MESSAGE_FORMAT_DEFAULT_VALUE )
33
33
_ensure_setting_exists (settings .USE_UTC_TIME_FORMAT_KEY , settings .USE_UTC_TIME_FORMAT_DEFAULT_VALUE )
34
34
_ensure_setting_exists (settings .BREAK_ON_ERROR_KEY , settings .BREAK_ON_ERROR_DEFAULT_VALUE )
35
+ _ensure_setting_exists (settings .PRINT_TREE_ON_ERROR_KEY , settings .PRINT_TREE_ON_ERROR_DEFAULT_VALUE )
35
36
36
37
func _init (log_name :String , min_log_level := LogLevel .DEFAULT , crash_behavior :Callable = default_crash_behavior ):
37
38
_log_name = log_name
@@ -42,6 +43,10 @@ func _init(log_name:String, min_log_level:=LogLevel.DEFAULT, crash_behavior:Call
42
43
func debug (message , values = {}):
43
44
call_thread_safe ("_internal_log" , message , values , LogLevel .DEBUG )
44
45
46
+ ## Shorthand for debug
47
+ func dbg (message :String ,values = {}):
48
+ call_thread_safe ("_internal_log" , message , values , LogLevel .DEBUG )
49
+
45
50
## prints a message to the log at the info level.
46
51
func info (message :String ,values = {}):
47
52
call_thread_safe ("_internal_log" , message , values )
@@ -54,19 +59,15 @@ func warn(message:String,values={}):
54
59
func error (message :String ,values = {}):
55
60
call_thread_safe ("_internal_log" , message , values , LogLevel .ERROR )
56
61
62
+ ## Shorthand for error
63
+ func err (message :String ,values = {}):
64
+ call_thread_safe ("_internal_log" , message , values , LogLevel .ERROR )
65
+
57
66
## Prints a message to the log at the fatal level, exits the application
58
67
## since there has been a fatal error.
59
68
func fatal (message :String ,values = {}):
60
69
call_thread_safe ("_internal_log" , message , values , LogLevel .FATAL )
61
70
62
- ## Shorthand for debug
63
- func dbg (message :String ,values = {}):
64
- call_thread_safe ("_internal_log" , message , values , LogLevel .DEBUG )
65
-
66
- ## Shorthand for error
67
- func err (message :String ,values = {}):
68
- call_thread_safe ("_internal_log" , message , values , LogLevel .ERROR )
69
-
70
71
## Throws an error if err_code is not of value "OK" and appends the error code string.
71
72
func err_cond_not_ok (err_code :Error , message :String , fatal := true , other_values_to_be_printed = {}):
72
73
if err_code != OK :
@@ -88,11 +89,66 @@ func err_cond_not_equal(arg1, arg2, message:String, fatal:=true, other_values_to
88
89
if (arg1 is Color && arg2 is Color && ! arg1 .is_equal_approx (arg2 )) || arg1 != arg2 :
89
90
call_thread_safe ("_internal_log" , str (arg1 ) + " != " + str (arg2 ) + ", not allowed. " + message , other_values_to_be_printed , LogLevel .FATAL if fatal else LogLevel .ERROR )
90
91
91
- ## Main internal logging method, please use the logger() instead since this is not thread safe.
92
+ ## Main internal logging method, please use the methods above instead, since this is not thread safe.
92
93
func _internal_log (message :String , values , log_level := LogLevel .INFO ):
93
94
if current_log_level > log_level :
94
95
return
96
+ if log_level == LogLevel .DEFAULT :
97
+ err ("Can't log at 'default' level, this level is only used as filter" )
98
+ ## Format message string
99
+ var format_str :String = ProjectSettings .get_setting (settings .LOG_MESSAGE_FORMAT_KEY , settings .LOG_MESSAGE_FORMAT_DEFAULT_VALUE )
100
+ message = format_str .format (_get_format_data (message , log_level ))
101
+ ## Tac on passed values
102
+ message += _stringify_values (values )
95
103
104
+ var stack = get_stack ()
105
+ emit_signal ("log_message" , log_level , message )
106
+ if stack .is_empty ():# Aka is connected to debug server -> print to the editor console in addition to pushing the warning.
107
+ _log_mode_console (message , log_level )
108
+ else :
109
+ _log_mode_editor (message , log_level , stack )
110
+ ## AKA, level is error or fatal, the main tree is accessible and we want to print it.
111
+ if log_level > 3 && Log .is_inside_tree () && ProjectSettings .get_setting (settings .PRINT_TREE_ON_ERROR_KEY , settings .PRINT_TREE_ON_ERROR_DEFAULT_VALUE ):
112
+ # We want to access the main scene tree since this may be a custom logger that isn't in the main tree.
113
+ print ("Main tree: " )
114
+ Log .get_tree ().root .print_tree_pretty ()
115
+ print ("" )# Print empty line to mark new message
116
+
117
+ if log_level == LogLevel .FATAL :
118
+ _crash_behavior .call ()
119
+
120
+ func _log_mode_editor (msg :String , lvl :LogLevel , stack :Array ):
121
+ match lvl :
122
+ LogLevel .DEBUG :
123
+ print_rich ("[color=gray]" + msg + "[/color]" )
124
+ LogLevel .INFO :
125
+ print_rich (msg )
126
+ LogLevel .WARN :
127
+ print_rich ("[color=yellow]" + msg + "[/color]" )
128
+ push_warning (msg )
129
+ print (_get_reduced_stack (stack ) + "\n " )
130
+ _ :# AKA error or fatal
131
+ push_error (msg )
132
+ msg = msg .replace ("[lb]" , "[" ).replace ("[rb]" , "]" )
133
+ printerr (msg )
134
+ # Mimic the native godot behavior of halting execution upon error.
135
+ if ProjectSettings .get_setting (settings .BREAK_ON_ERROR_KEY , settings .BREAK_ON_ERROR_DEFAULT_VALUE ):
136
+ ## Please go a few steps down the stack to find the errorous code, since you are currently inside the error handler.
137
+ breakpoint
138
+ print (_get_reduced_stack (stack ))
139
+
140
+
141
+ func _log_mode_console (msg :String , lvl :LogLevel ):
142
+ ## remove any BBCodes
143
+ msg = msg .replace ("[lb]" , "[" ).replace ("[rb]" , "]" )
144
+ if lvl < 3 :
145
+ print (msg )
146
+ elif lvl == LogLevel .WARN :
147
+ push_warning (msg )
148
+ else :
149
+ push_error (msg )
150
+
151
+ func _get_format_data (msg :String , lvl :LogLevel )-> Dictionary :
96
152
var now = Time .get_datetime_dict_from_system (ProjectSettings .get_setting (settings .USE_UTC_TIME_FORMAT_KEY , settings .USE_UTC_TIME_FORMAT_DEFAULT_VALUE ))
97
153
now ["second" ] = "%02d " % now ["second" ]
98
154
now ["minute" ] = "%02d " % now ["minute" ]
@@ -102,78 +158,35 @@ func _internal_log(message:String, values, log_level := LogLevel.INFO):
102
158
103
159
var format_data := {
104
160
"log_name" :_log_name ,
105
- "message" :message ,
106
- "level" :LogLevel .keys ()[log_level ]
161
+ "message" :msg ,
162
+ "level" :LogLevel .keys ()[lvl ]
107
163
}
108
164
format_data .merge (now )
109
- var msg : String = ProjectSettings . get_setting ( settings . LOG_MESSAGE_FORMAT_KEY , settings . LOG_MESSAGE_FORMAT_DEFAULT_VALUE ). format ( format_data )
110
- var stack = get_stack ()
111
-
165
+ return format_data
166
+
167
+ func _stringify_values ( values ) -> String :
112
168
match typeof (values ):
169
+ TYPE_NIL :
170
+ return ""
113
171
TYPE_ARRAY :
114
- if values .size () > 0 :
115
- msg += "["
116
- for k in values :
117
- msg += "{k} ," .format ({"k" :JSON .stringify (k )})
118
- msg = msg .left (msg .length ()- 1 )+ "]"
172
+ var msg = "["
173
+ for k in values :
174
+ msg += "{k} , " .format ({"k" :JSON .stringify (k )})
175
+ return msg + "]"
119
176
TYPE_DICTIONARY :
120
- if values .size () > 0 :
121
- msg += "{"
122
- for k in values :
123
- if typeof (values [k ]) == TYPE_OBJECT && values [k ] != null :
124
- msg += '"{k} ":{v} ,' .format ({"k" :k ,"v" :JSON .stringify (JsonData .to_dict (values [k ],false ))})
125
- else :
126
- msg += '"{k} ":{v} ,' .format ({"k" :k ,"v" :JSON .stringify (values [k ])})
127
- msg = msg .left (msg .length ()- 1 )+ "}"
177
+ var msg = "{"
178
+ for k in values :
179
+ if typeof (values [k ]) == TYPE_OBJECT && values [k ] != null :
180
+ msg += '"{k} ":{v} ,' .format ({"k" :k ,"v" :JSON .stringify (JsonData .to_dict (values [k ],false ))})
181
+ else :
182
+ msg += '"{k} ":{v} ,' .format ({"k" :k ,"v" :JSON .stringify (values [k ])})
183
+ return msg + "}"
128
184
TYPE_PACKED_BYTE_ARRAY :
129
- if values == null :
130
- msg += JSON .stringify (null )
131
- else :
132
- msg += JSON .stringify (JsonData .unmarshal_bytes_to_dict (values ))
185
+ return JSON .stringify (JsonData .unmarshal_bytes_to_dict (values ))
133
186
TYPE_OBJECT :
134
- if values == null :
135
- msg += JSON .stringify (null )
136
- else :
137
- msg += JSON .stringify (JsonData .to_dict (values ,false ))
138
- TYPE_NIL :
139
- msg += JSON .stringify (null )
187
+ return JSON .stringify (JsonData .to_dict (values ,false ))
140
188
_ :
141
- msg += JSON .stringify (values )
142
-
143
- emit_signal ("log_message" , log_level , msg )
144
- match log_level :
145
- LogLevel .DEBUG :
146
- print_rich ("[color=gray]" + msg + "[/color]" )
147
- LogLevel .INFO :
148
- print_rich (msg )
149
- LogLevel .WARN :
150
- if ! stack .is_empty ():# Aka is connected to debug server -> print to the editor console in addition to pushing the warning.
151
- print_rich ("[color=yellow]" + msg + "[/color]" )
152
-
153
- push_warning (msg )
154
- print (_get_reduced_stack (stack ) + "\n " )
155
- LogLevel .DEFAULT :
156
- err ("Can't log at 'default' level, this level is only used as filter" )
157
- _ :
158
- msg = msg .replace ("[lb]" , "[" ).replace ("[rb]" , "]" )
159
- push_error (msg )
160
- if ! stack .is_empty ():# Aka is connected to debug server -> print to the editor console in addition to pushing the warning.
161
- printerr (msg )
162
- # Mimic the native godot behavior of halting execution upon error.
163
- if ProjectSettings .get_setting (settings .BREAK_ON_ERROR_KEY , settings .BREAK_ON_ERROR_DEFAULT_VALUE ):
164
- ## Please go a few steps down the stack to find the errorous code, since you are currently inside the error handler.
165
- breakpoint
166
- print (_get_reduced_stack (stack ))
167
-
168
- # We want to access the main scene tree since this may be a custom logger that isn't in the main tree.
169
- if Log .is_inside_tree ():
170
- print ("Main tree: " )
171
- Log .get_tree ().root .print_tree_pretty ()
172
- print ("" )# Print empty line to mark new message
173
-
174
- if log_level == LogLevel .FATAL :
175
- _crash_behavior .call ()
176
-
189
+ return JSON .stringify (values )
177
190
178
191
func _get_reduced_stack (stack :Array )-> String :
179
192
var stack_trace_message := ""
0 commit comments