BuckeyeSoftware / rex

rex engine and game
MIT License
15 stars 0 forks source link

Logger feature requests #47

Open DethRaid opened 4 years ago

DethRaid commented 4 years ago

User-configurable colors for the log levels

Logger support for colored log text and background text

Log filters

Runtime-configurable log message queue length

Stream interface able to report support for colors

User-definable tag names

DethRaid commented 4 years ago

I'd also love to be able to attach streams to individual loggers. Use case is that I could make a logger for my scripting system and hook up a stream that writes to a "scripting log" output window that wouldn't have all the logging messages from the engine

This may or may not be the kind of thing you meant with "log filters". I didn't really get what you meant by that but it seemed important

graphitemaster commented 4 years ago

The on_write and on_queue for a log instance can already do that. You could just filter out "scripting" stuff then in the compiled log (log of all logs)

graphitemaster commented 4 years ago

The filtering system should allow for filtering out log instances and log levels.

DethRaid commented 4 years ago

Oh nice. That'll serve my needs just fine

graphitemaster commented 4 years ago

So looking at it a bit more I've come to this design:

Tags

By changing the constructor around we can support user-defined tags:

template<Size E>
Log::Log(const char* _name, const Array<Tag[E]>& _tags);

Where Tag will be defined like:

struct Tag {
  const char* name;
  Uint32 fg_color;
  Uint32 bg_color = 0; // Optional, zero means don't change bg color
};

What this means in practice is you can define a log with user-defined tags like:

Log("name", Array{Tag{"rtag", 0xFF0000}, Tag{"btag", 0x00FF00}, Tag{"gtag", 0x0000FF}});

Which would give you [name/{r,g,b}tag] entries in the compiled log which are colored based on the tag.

Since Log instances must be done at compile-time via the RX_LOG macro, which produces the appropriate Global<Log>. These tags will be extended into that interface like so:

RX_LOG(logger, "name", Tag{"rtag", 0xFF0000}, Tag{"gtag", 0x00FF00}, Tag{"btag", 0x0000F});

Which I think looks pretty cool. This does however mean the usual "info", "warning", "error" and "verbose" tags and helper functions will not exist, all logs will have to define all their tags.

The logging interface will then be based entirely on which string-literal tag you pass for a given log, so invoking the logger as:

logger("rtag", ...); // prints to rtag
logger("gtag", ...); // prints to gtag

Filtering

We'll introduce a filter and unfilter method to Log which is given a tag name to filter out logs of that given tag, e.g:

[[nodiscard]] bool Log::filter(const char* _tag_name);
[[nodiscard]] bool Log::unfilter(const char* _tag_name);

Thoughts?

DethRaid commented 4 years ago

Tags

I generally like your design for user-defined tags. I don't really want to have to define error/warning/info/verbose tags for every logger, though

Maybe invoking the log could either take a tag name or a full Tag struct as its first argument? Then I could have some defines for the error/warning/info/verbose tags that I can pass in however

#define ERROR Tag{"error", 0xFF0000}

logger(ERROR, "Everything broke");

Filtering

Filtering based on tag seems reasonable, as long as I can also filter based on logger name

graphitemaster commented 4 years ago

There's no easy way to provide logger->tag_name() without hackery as you can imagine. Issue with leaving default error/warning/info/verbose is then there is no way to override their colors on a per-log basis