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

Reply via email to