Voting: std.logger

Kevin Lamonte via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 3 04:39:57 PDT 2014


On Tuesday, 2 September 2014 at 10:14:27 UTC, Ola Fosheim Grøstad 
wrote:
> On Tuesday, 2 September 2014 at 06:24:45 UTC, Kevin Lamonte 
> wrote:

> I see a difference between signalling state, tracing execution 
> and logging state. I guess one roughly can say that:
>
> - signalling is for coordination of subsystems
> - logging state is for tracking effects on the database
> - tracing is for detecting logic failure after a crash

I've written my own ideas about logging vs tracing over at 
https://github.com/klamonte/log4d/docs/philosophy.md .  In a 
nutshell, "logging" means the engineered messages targeting 
non-developers that are part of the application deliverable and 
follow the narrative flow, while tracing is the automated 
messages targeting the developers that follow the structural flow.

std.logger provides an acceptable interface for logging and an 
absolute minimal interface to tracing, with just the single 
LogLevel.trace and trace/tracef functions.  Most other systems 
provide at least two (debug+trace) or three (fine/finer/finest) 
levels between INFO and everything, and some provide 
log.entering()/log.exiting() functions that could provide for 
what you are describing.

> Sounds interesting. I'll have a look at log4d later. But it is 
> not fully typesafe then? The way I see it you should log a 
> tuple of values and a reference to a type-safe formatting 
> expression, but only apply the formatting expression when you 
> need to so you don't burden the performance thread with 
> unnecessary work.

Well, sort of.  It's not CTFE-like typesafe where the compiler 
catches it, but it also isn't possible (AFAIK) to get it wrong 
either.  PatternLayout's "format" specifiers don't perform 
conversions on client-controlled input, they are straight 
substitutions of the LogEntry fields (+ some extras) into the 
final emitted string.

It sounds like what you would like is a trace function that 
doesn't feature a format string at all, but formatting would 
instead be applied at I/O time by a Logger subclass.  How about 
this?

1. Add a "fnArgs" field of type Object [] to LogEntry
2, Add something like the following:

     void traceFn(int line = __LINE__,
         string file = __FILE__, string funcName = __FUNCTION__,
         string prettyFuncName = __PRETTY_FUNCTION__,
         string moduleName = __MODULE__)(lazy Object [] fnArgs)
         @trusted
     {
         static if (isLoggingActive!LogLevel.trace)
         {
             if (isLoggingEnabled(LogLevel.trace)
                     && ll >= stdlog.logLevel
                     && stdlog.logLevel >= globalLogLevel
                     && globalLogLevel != LogLevel.off
                     && stdlog.logLevel != LogLevel.off)
             {
                     auto entry = LogEntry(file, line, funcName, 
prettyFuncName,
                         moduleName, LogLevel.trace, thisTid, 
Clock.currTime, null, this, fnArgs);
                     this.writeLogMsg(entry);
             }
         }
     }

This could also be split into traceFnEnter, traceFnExitSuccess, 
and traceFnExitFailure with LogEntry.args set to indicate which 
one (">", "<", "!<" for example) and a mixin provided so that 
client code could get it all in a one-liner.

If this would meet your needs, I wouldn't mind it myself.  Save 
log.trace() for generic messages the developer want to see 
between the traceFnEnter/traceFnExitX messages.


More information about the Digitalmars-d mailing list