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