godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.08k stars 69 forks source link

Logging to have a signal for any logging #7328

Open RadiantUwU opened 12 months ago

RadiantUwU commented 12 months ago

Describe the project you are working on

In-game debug console plugin

Describe the problem or limitation you are having in your project

The problem is that any external plugins not made for this plugin will not be logged and will remain over to the external console.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

This feature would allow a script to connect to the signal and be able to show the log on screen, making it easier to see things on non-debug builds, to make it easier for users to report bugs.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

defines:

const LOG_INFO=0
const LOG_WARN=1
const LOG_ERROR=2
signal on_log_event(log_type: int,message: String ,traceback: String)
func _on_log(log_type:int,message:String,traceback:String):
    # do whatever
    pass
func _ready():
    on_log_event.connect(_on_log)

traceback is an empty string if its running in a release build

If this enhancement will not be used often, can it be worked around with a few lines of script?

No, due to extended modification of existing code to work with the logging plugin.

Is there a reason why this should be core and not an add-on in the asset library?

Yes, since i dont remember any GDExtension plugin be able to know whenever print(), push_warning() or push_error() is called.

Calinou commented 12 months ago
zinnschlag commented 12 months ago

Sounds like an infinite recursion waiting to happen. One would have to pay a lot of attention, not accidentally calling any function that does any logging.

RadiantUwU commented 12 months ago

Sounds like an infinite recursion waiting to happen. One would have to pay a lot of attention, not accidentally calling any function that does any logging.

Indeed.

theraot commented 9 months ago

If you are getting a call on every log, aside from the mentioned recursion problem, it might require consideration for threading too. The next logical option is to make it a deferred callback, but then again, the callback would not arrive right away, and we want to avoid out of order issues anyway...

Thus: make it a callback, that you'd need to register (from EditorPlugin?), which would be called every frame with the list of messages from the last time it was called, if there has been any (i.e. if there wasn't messages, it does not get called that frame).

Separate callbacks for error and regular output (stderr and stdout) would make sense.

I'm thinking the callbacks would only give an array with texts... Rich text given print_rich.

Does this make sense and sound useful?

RadiantUwU commented 9 months ago

Yeah!

theraot commented 9 months ago

Looking into how to implement this, I found this API that seems useful: https://github.com/godotengine/godot/blob/a2f90d565ad29edcb3bdab77bc7df51cdde8514a/core/string/print_string.h#L38-L57

Of course, I don't want to expose that. The idea I posted before would not be exposing it anyway, as the plan was to accumulate the print lines, and then pass them to a callback. That way the code that handles the prints can return fast, and the callback won't introduce errors, recursion, etc.

Now, we get a bool flag indicating if it is rich text. That suggest that accumulating an array of strings is not enough. Presumably having "struct"s (https://github.com/godotengine/godot-proposals/issues/7329) would help, or we could use an array of dictionaries. Alternatively, we could call the callback once per line (it would still be accumulated behind the scenes, and dispatched on process). I do not know which approach is better.

theraot commented 1 month ago

See aslo: