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.

Reply via email to