Suggestion/proposal regarding std.logger candidate

Robert BuRnEr Schadek via Digitalmars-d digitalmars-d at puremagic.com
Sat May 24 23:03:17 PDT 2014


On 05/24/2014 02:57 AM, David Osborne via Digitalmars-d wrote:
> Yesterday, in the livestream chat, there was some discussion about
> the current std.logger proposal.  The consensus seemed to be that
> it's probably fine for most use cases and it's the best proposal
> we've had so far, it doesn't look suitable for heavy duty,
> enterprise-grade logging.  In an ideal world, the std.logger module
> in phobos would be flexible enough to build an enterprise-grade
> logging library on top of, but it seems the current proposal isn't
> there yet.  I got to thinking about how to make the logging system
> more flexible, and this is what I came up with.
Why is that?
>
> I identified three key parts to a logger: the filter, the format,
> and the sink.
>
>     log.trace(...) ----> Filter ----> Format ----> Sink
>
> The filter determines which log messages to act on, and which to
> ignore.  Usually this is done based on the log level, but one use
> case that was brought up was automatically sending an email to the
> developers only when a particular exception occurred (i.e. filter
> based on Exception type).  Currently, std.logger implements the
> filtering for you, based on the global log level, and the log level
> of that particular logger.
and on a condition you can pass
>
> The format determines what the output of the log message looks like.
> Usually, this winds up being some sort of call to formattedWrite,
> though there is no need to assume that the output must be a string,
> or even human-readable.  Currently, formatting tends to be
> implemented as part of Logger.writeLogMsg, and is specific to each
> Logger implementation.
>
> The sink is where the log message goes.  Popular destinations
> include stderr, /dev/null, some text file somewhere, or a central
> logging facility provided by your OS.  Currently, the sink is
> specified when implementing Logger.writeLogMsg.
That is the idea
>
> Based on these three parameters, I came up with the following proof
> of concept implementation, built on top of the current proposal:
>
> public class Clogger(alias format, alias filter, Sink) : Logger
>     if( isLogFilter!filter && isLogFormat!format && isLogSink!(Sink,
> format) )
> {
>
>     public this(Sink sink, string newName, LogLevel lv) {
>         super(newName, lv);
>         this.sink = sink;
>     }
>
>     override
>     public void writeLogMsg(ref LoggerPayload payload) {
>         import std.algorithm : copy;
>
>         if( this.filterFun(payload) ) {
>             sink = formatFun(payload).copy(sink);
>         }
>     }
>
>     private:
>     Sink sink;
>     alias formatFun = unaryFun!format;
>     alias filterFun = unaryFun!filter;
>
> }
>
> The full code is at https://github.com/krendil/clogger.
>
> As you can see, there are three template parameters, that correspond
> to the three components identified above.
>
> - filter is a predicate that takes a LoggerPayload and returns true
>     if that log message should be logged.
>
> - format takes a LoggerPayload and converts it to something
>     suitable for output, in the form of a Range.
>
> - Sink is an OutputRange that has the same element type as the
>     the output of format.
>
> I think there are a few benefits to this setup:
>   - Separation of format from sink
>   - Custom, arbitrary filtering
>   - Simpler to implement new Loggers
>
> With this setup, multiplexing can either be done at the Logger
> level, as it is currently, or at the Sink level. Log messages can
> still be converted to any sort of output. Aliases or convenience
> functions could be created for common Logger types (I currently have
> convenience functions for a multiplexer, a stdout logger and a
> generic dchar range logger).
>
> Destroy :)
Thank you, for showing how easy it is to use std.logger for your purposes



More information about the Digitalmars-d mailing list