std.experimental.logger formal review round 3

Martin Nowak via Digitalmars-d digitalmars-d at puremagic.com
Tue Oct 28 15:03:06 PDT 2014


On 10/28/2014 07:22 PM, Martin Nowak wrote:
> On Tuesday, 28 October 2014 at 12:02:16 UTC, Robert burner Schadek wrote:
>> It is a design goal to disable certain LogLevel at CT of a compile
>> unit (CU).
>> e.g. make all logs to trace function template do nothing
>
> One idea to make this working is to use prefixed version identifiers.
> Obviously this is all boilerplate so it could be done in a mixin
> template in std.log.

2nd iteration of that idea.

cat > main.d << CODE
import std_logger;

LoggerCT!"MyApp" appLogger = new StdoutLogger(LogLevel.info);
LoggerCT!"MyLib" libLogger = new StdoutLogger(LogLevel.trace);

void main()
{
     appLogger.log!(LogLevel.info)("app");
     appLogger.log!(LogLevel.warning)("app");
     libLogger.log!(LogLevel.info)("lib");
     libLogger.log!(LogLevel.warning)("lib");

     Logger rtLogger = appLogger;
     rtLogger.log!(LogLevel.info)("rt");
     rtLogger.log!(LogLevel.warning)("rt");
}
CODE

cat > std_logger.d << CODE
enum LogLevel { all, info, trace, warning, error, none }

template minLogLevel(string prefix)
{
     mixin("
     version ("~prefix~"LogAll)
         enum minLogLevel = LogLevel.all;
     else version ("~prefix~"LogInfo)
         enum minLogLevel = LogLevel.info;
     else version ("~prefix~"LogTrace)
         enum minLogLevel = LogLevel.trace;
     else version ("~prefix~"LogWarning)
         enum minLogLevel = LogLevel.warning;
     else version ("~prefix~"LogError)
         enum minLogLevel = LogLevel.error;
     else version ("~prefix~"LogNone)
         enum minLogLevel = LogLevel.none;
     else
         enum minLogLevel = LogLevel.all;
     ");
}

interface Logger
{
     @property LogLevel logLevel();
     void write(LogLevel ll, string msg);
}

class StdoutLogger : Logger
{
     this(LogLevel l) { _logLevel = l; }
     LogLevel _logLevel;
     @property LogLevel logLevel() { return _logLevel; }
     void write(LogLevel ll, string msg) { import std.stdio; writeln(ll, 
": ", msg); }
}

/// used for library/app specific version prefixes
struct LoggerCT(string prefix)
{
     this(Logger logger) { impl = logger; }
     enum versionPrefix = prefix;
     Logger impl;
     alias impl this;
}

void log(LogLevel ll)(Logger logger, string msg)
{
     if (ll >= logger.logLevel) // runtime check
         logger.write(ll, msg);
}

/// when using a logger with prefix
void log(LogLevel ll, L:LoggerCT!pfx, string pfx)(auto ref L logger, 
string msg)
     if (ll < minLogLevel!pfx)
{
}

void log(LogLevel ll, L:LoggerCT!pfx, string pfx)(auto ref L logger, 
string msg)
     if (ll >= minLogLevel!pfx)
{
     if (ll >= logger.logLevel) // additional runtime check, because 
logger might require a higher log level
         logger.write(ll, msg);
}
CODE

dmd std_logger -run main

dmd -version=MyAppLogWarning std_logger.d -run main
dmd -version=MyAppLogError -version=MyLibLogNone std_logger.d -run main


More information about the Digitalmars-d mailing list