// Written in the D programming language. /** This module provides logging utilities. Use Log class static methods. Synopsis: ---- import exlib.logger; // setup: // use stderror for logging setStderrLogger(); // set log level setLogLevel(LogLeve.Debug); // usage: // log debug message Log.d("mouse clicked at ", x, ",", y); // log error message Log.e("exception while reading file", e); ---- Copyright: Vadim Lopatin, 2014 License: Boost License 1.0 Authors: Vadim Lopatin, coolreader.org@gmail.com */ module exlib.logger; import std.stdio; import std.datetime; /// Log levels enum LogLevel : int { /// Fatal error, cannot resume Fatal, /// Error Error, /// Warning Warn, /// Informational message Info, /// Debug message Debug, /// Tracing message Trace } /// Returns timestamp in milliseconds since 1970 UTC similar to Java System.currentTimeMillis() long currentTimeMillis() { return std.datetime.Clock.currStdTime / 10000; } /** Logging utilities Setup example: ---- // use stderror for logging setStderrLogger(); // set log level setLogLevel(LogLeve.Debug); ---- Logging example: ---- // log debug message Log.d("mouse clicked at ", x, ",", y); // log error message Log.e("exception while reading file", e); ---- */ synchronized class Log { static: private LogLevel logLevel = LogLevel.Info; private std.stdio.File logFile; /// Redirects output to stdout void setStdoutLogger() { logFile = stdout; } /// Redirects output to stderr void setStderrLogger() { logFile = stderr; } /// Redirects output to file void setFileLogger(File file) { logFile = file; } /// Sets log level (one of LogLevel) void setLogLevel(LogLevel level) { logLevel = level; } /// Log level to name helper function string logLevelName(LogLevel level) { switch (level) { case LogLevel.Fatal: return "F"; case LogLevel.Error: return "E"; case LogLevel.Warn: return "W"; case LogLevel.Info: return "I"; case LogLevel.Debug: return "D"; case LogLevel.Trace: return "V"; default: return "?"; } } /// Log message with arbitrary log level void log(S...)(LogLevel level, S args) { if (logLevel >= level && logFile.isOpen) { SysTime ts = Clock.currTime(); logFile.writef("%04d-%02d-%02d %02d:%02d:%02d.%03d %s ", ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second, ts.fracSec.msecs, logLevelName(level)); logFile.writeln(args); logFile.flush(); } } /// Log verbose / trace message void v(S...)(S args) { if (logLevel >= LogLevel.Trace && logFile.isOpen) log(LogLevel.Trace, args); } /// Log debug message void d(S...)(S args) { if (logLevel >= LogLevel.Debug && logFile.isOpen) log(LogLevel.Debug, args); } /// Log info message void i(S...)(S args) { if (logLevel >= LogLevel.Info && logFile.isOpen) log(LogLevel.Info, args); } /// Log warn message void w(S...)(S args) { if (logLevel >= LogLevel.Warn && logFile.isOpen) log(LogLevel.Warn, args); } /// Log error message void e(S...)(S args) { if (logLevel >= LogLevel.Error && logFile.isOpen) log(LogLevel.Error, args); } /// Log fatal error message void f(S...)(S args) { if (logLevel >= LogLevel.Fatal && logFile.isOpen) log(LogLevel.Fatal, args); } }