On Tuesday, 28 October 2014 at 22:03:18 UTC, Martin Nowak wrote:
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
That can actually be added to the current state of std.logger
without breaking any api. The string mixin, version string
matching isn't really pretty, but it gets the job done. Anyway
IMO your approach presented here and my approach can go hand in
hang. Yours should be propagated as the idiomatic way and if you
really need the crowbar, which you need sometimes, use
StdLoggerDisableXXXXX.