Major refactor

- A lot of clean up
This commit is contained in:
Tristan B. Velloza Kildaire 2024-04-09 17:26:55 +02:00
parent 2f8b61fcf2
commit 59ddf53efa
7 changed files with 331 additions and 807 deletions

View File

@ -1,6 +1,6 @@
module dlog.nu.basic;
module dlog.basic;
import dlog.nu.core;
import dlog.core;
public class BasicMessage : Message
{
@ -64,11 +64,29 @@ public class FileHandler : Handler
}
}
/**
* Logging level
*/
public enum Level
{
/**
* Error message
*/
ERROR,
WARNING,
/**
* Informative message
*/
INFO,
/**
* Warning message
*/
WARN,
/**
* Debugging message
*/
DEBUG
}

View File

@ -1,161 +0,0 @@
/**
* Context for logging
*/
module dlog.context;
import std.conv : to;
/**
* Debugging trace level
*/
public enum Level
{
/**
* Informative message
*/
INFO,
/**
* Warning message
*/
WARN,
/**
* Error message
*/
ERROR,
/**
* Debugging message
*/
DEBUG
}
/**
* Context that is passed in with the call to log
*/
public class Context
{
private CompilationInfo lineInfo;
private Level level;
/**
* Constructs a new Context
*/
this()
{
}
/**
* Set the line information
*
* Params:
* lineInfo = the CompilationInfo struct to use
*/
public final void setLineInfo(CompilationInfo lineInfo)
{
this.lineInfo = lineInfo;
}
/**
* Obtain the line information generated at compilation
* time
*
* Returns: the CompilationInfo struct
*/
public final CompilationInfo getLineInfo()
{
return lineInfo;
}
/**
* Returns the current tarce level
*
* Returns: the Level
*/
public final Level getLevel()
{
return level;
}
/**
* Set the trace level
*
* Params:
* level = the Level to use
*/
public final void setLevel(Level level)
{
this.level = level;
}
}
/**
* Information obtained during compilation time (if any)
*/
public struct CompilationInfo
{
/**
* compile time usage file
*/
public string fullFilePath;
/**
* compile time usage file (relative)
*/
public string file;
/**
* compile time usage line number
*/
public ulong line;
/**
* compile time usage module
*/
public string moduleName;
/**
* compile time usage function
*/
public string functionName;
/**
* compile time usage function (pretty)
*/
public string prettyFunctionName;
/**
* Constructs the compilation information with the provided
* parameters
*
* Params:
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
this(string fullFilePath, string file, ulong line, string moduleName, string functionName, string prettyFunctionName)
{
this.fullFilePath = fullFilePath;
this.file = file;
this.line = line;
this.moduleName = moduleName;
this.functionName = functionName;
this.prettyFunctionName = prettyFunctionName;
}
/**
* Flattens the known compile-time information into a string array
*
* Returns: a string[]
*/
public string[] toArray()
{
return [fullFilePath, file, to!(string)(line), moduleName, functionName, prettyFunctionName];
}
}

View File

@ -1,441 +1,150 @@
/**
* Core logging services
*/
module dlog.core;
import std.conv : to;
import std.range : join;
import dlog.transform : MessageTransform;
import dlog.defaults;
import dlog.context : Context, CompilationInfo, Level;
import dlog.utilities : flatten;
/**
* Logger
*
* Represents a logger instance
*/
public class Logger
public class Message
{
/* Starting transformation */
private MessageTransform messageTransform;
/**
* The multiple argument joiner
*/
protected string multiArgJoiner;
/**
* Constructs a new Logger with the default
* MessageTransform
*
* Params:
* multiArgJoiner = optional joiner for segmented prints (default is " ")
*/
this(string multiArgJoiner = " ")
{
this(new DefaultTransform(), multiArgJoiner);
}
/**
* Constructs a new Logger with the provided
* custom message transform
* Params:
* messageTransform = the message transform to use
* multiArgJoiner = optional joiner for segmented prints (default is " ")
*/
this(MessageTransform messageTransform, string multiArgJoiner = " ")
{
this.messageTransform = messageTransform;
this.multiArgJoiner = multiArgJoiner;
}
/**
* Given an arbitrary amount of arguments, convert each to a string
* and return it as an array joined by the joiner
*
* Params:
* segments = alias sequence
* Returns: a string of the argumnets
*/
public string args(TextType...)(TextType segments)
{
/* The flattened components */
string[] components = flatten(segments);
/* Join all `components` into a single string */
string joined = join(components, multiArgJoiner);
return joined;
}
/**
* Logs the given string using the default context
*
* Params:
* text = the string to log
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public final void log(string text, string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/* Use the default context `Context` */
Context defaultContext = new Context();
/* Build up the line information */
CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6);
/* Set the line information in the context */
defaultContext.setLineInfo(compilationInfo);
/* Call the log */
logc(defaultContext, text, c1, c2, c3, c4, c5, c6);
}
/**
* Logs using the default context an arbitrary amount of arguments
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public final void log(TextType...)(TextType segments, string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/**
* Grab at compile-time all arguments and generate runtime code to add them to `components`
*/
string[] components = flatten(segments);
/* Join all `components` into a single string */
string messageOut = join(components, multiArgJoiner);
/* Call the log (with text and default context) */
log(messageOut, c1, c2, c3, c4, c5, c6);
}
/**
* Logs the given string using the provided context
*
* Params:
* context = the custom context to use
* text = the string to log
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public final void logc(Context context, string text, string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/* Build up the line information */
CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6);
/* Set the line information in the context */
context.setLineInfo(compilationInfo);
/* Apply the transformation on the message */
string transformedMesage = messageTransform.execute(text, context);
/* Call the underlying logger implementation */
logImpl(transformedMesage);
}
/**
* Logs using the default context an arbitrary amount of arguments
* specifically setting the context's level to ERROR
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public void error(TextType...)(TextType segments,
string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/* Use the default context `Context` */
Context defaultContext = new Context();
/* Build up the line information */
CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6);
/* Set the line information in the context */
defaultContext.setLineInfo(compilationInfo);
/* Set the level to ERROR */
defaultContext.setLevel(Level.ERROR);
/**
* Grab at compile-time all arguments and generate runtime code to add them to `components`
*/
string[] components = flatten(segments);
/* Join all `components` into a single string */
string messageOut = join(components, multiArgJoiner);
/* Call the log */
logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6);
}
/**
* Logs using the default context an arbitrary amount of arguments
* specifically setting the context's level to INFO
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public void info(TextType...)(TextType segments,
string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/* Use the default context `Context` */
Context defaultContext = new Context();
/* Build up the line information */
CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6);
/* Set the line information in the context */
defaultContext.setLineInfo(compilationInfo);
/* Set the level to INFO */
defaultContext.setLevel(Level.INFO);
/**
* Grab at compile-time all arguments and generate runtime code to add them to `components`
*/
string[] components = flatten(segments);
/* Join all `components` into a single string */
string messageOut = join(components, multiArgJoiner);
/* Call the log */
logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6);
}
/**
* Logs using the default context an arbitrary amount of arguments
* specifically setting the context's level to WARN
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public void warn(TextType...)(TextType segments,
string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/* Use the default context `Context` */
Context defaultContext = new Context();
/* Build up the line information */
CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6);
/* Set the line information in the context */
defaultContext.setLineInfo(compilationInfo);
/* Set the level to WARN */
defaultContext.setLevel(Level.WARN);
/**
* Grab at compile-time all arguments and generate runtime code to add them to `components`
*/
string[] components = flatten(segments);
/* Join all `components` into a single string */
string messageOut = join(components, multiArgJoiner);
/* Call the log */
logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6);
}
/**
* Logs using the default context an arbitrary amount of arguments
* specifically setting the context's level to DEBUG
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
* __FILE_FULL_PATH__ = compile time usage file
* __FILE__ = compile time usage file (relative)
* __LINE__ = compile time usage line number
* __MODULE__ = compile time usage module
* __FUNCTION__ = compile time usage function
* __PRETTY_FUNCTION__ = compile time usage function (pretty)
*/
public void debug_(TextType...)(TextType segments,
string c1 = __FILE_FULL_PATH__,
string c2 = __FILE__, ulong c3 = __LINE__,
string c4 = __MODULE__, string c5 = __FUNCTION__,
string c6 = __PRETTY_FUNCTION__)
{
/* Use the default context `Context` */
Context defaultContext = new Context();
/* Build up the line information */
CompilationInfo compilationInfo = CompilationInfo(c1, c2, c3, c4, c5, c6);
/* Set the line information in the context */
defaultContext.setLineInfo(compilationInfo);
/* Set the level to DEBUG */
defaultContext.setLevel(Level.DEBUG);
/**
* Grab at compile-time all arguments and generate runtime code to add them to `components`
*/
string[] components = flatten(segments);
/* Join all `components` into a single string */
string messageOut = join(components, multiArgJoiner);
/* Call the log */
logc(defaultContext, messageOut, c1, c2, c3, c4, c5, c6);
}
/**
* Alias for debug_
*/
public alias dbg = debug_;
/**
* Logging implementation, this is where the final
* transformed text will be transferred to and finally
* logged
*
* Params:
* message = the message to log
*/
protected abstract void logImpl(string message);
}
version(unittest)
public interface Filter
{
import std.meta : AliasSeq;
import std.stdio : writeln;
public bool filter(Message message);
}
/**
* Tests the DefaultLogger
*/
unittest
public interface Transform
{
Logger logger = new DefaultLogger();
alias testParameters = AliasSeq!("This is a log message", 1.1, true, [1,2,3], 'f', logger);
// Test various types one-by-one
static foreach(testParameter; testParameters)
{
logger.log(testParameter);
}
// Test various parameters (of various types) all at once
logger.log(testParameters);
// Same as above but with a custom joiner set
logger = new DefaultLogger("(-)");
logger.log(testParameters);
writeln();
public Message transform(Message message);
}
/**
* Printing out some mixed data-types, also using a DEFAULT context
*/
unittest
public interface Handler
{
Logger logger = new DefaultLogger();
// Create a default logger with the default joiner
logger = new DefaultLogger();
logger.log(["a", "b", "c", "d"], [1, 2], true);
writeln();
public void handle(Message message);
}
/**
* Printing out some mixed data-types, also using a CUSTOM context
*/
unittest
import std.container.slist : SList;
// import std.range : in;
import core.sync.mutex : Mutex;
public abstract class Logger
{
Logger logger = new DefaultLogger();
private SList!(Transform) transforms;
private SList!(Filter) filters;
private SList!(Handler) handlers;
private Mutex lock; // Lock for attached handlers, filters and transforms
// Create a default logger with the default joiner
logger = new DefaultLogger();
this()
{
this.lock = new Mutex();
}
// Create a custom context
Context customContext = new Context();
// TODO: Handle duplicate?
public final void addTransform(Transform transform)
{
scope(exit)
{
this.lock.unlock();
}
// Log with the custom context
logger.logc(customContext, logger.args(["an", "array"], 1, "hello", true));
this.lock.lock();
writeln();
}
this.transforms.insertAfter(this.transforms[], transform);
}
/**
* Printing out some mixed data-types, also using a DEFAULT context
* but also testing out the `error()`, `warn()`, `info()` and `debug()`
*/
unittest
{
Logger logger = new DefaultLogger();
// TODO: Hanmdle not found explicitly?
public final void removeTransform(Transform transform)
{
scope(exit)
{
this.lock.unlock();
}
// Create a default logger with the default joiner
logger = new DefaultLogger();
this.lock.lock();
// Test out `error()`
logger.error(["woah", "LEVELS!"], 69.420);
this.transforms.linearRemoveElement(transform);
}
// Test out `info()`
logger.info(["woah", "LEVELS!"], 69.420);
// TODO: Handle duplicate?
public final void addFilter(Filter filter)
{
scope(exit)
{
this.lock.unlock();
}
// Test out `warn()`
logger.warn(["woah", "LEVELS!"], 69.420);
this.lock.lock();
// Test out `debug_()`
logger.debug_(["woah", "LEVELS!"], 69.420);
this.filters.insertAfter(this.filters[], filter);
}
writeln();
// TODO: Hanmdle not found explicitly?
public final void removeFilter(Filter filter)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.filters.linearRemoveElement(filter);
}
// TODO: Handle duplicate?
public final void addHandler(Handler handler)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.handlers.insertAfter(this.handlers[], handler);
}
// TODO: Hanmdle not found explicitly?
public final void removeHandler(Handler handler)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.handlers.linearRemoveElement(handler);
}
// Logs an actual message
//
// This first passes it over all filters
// then to a transform and then copies
// to each handler
public final void log(Message message)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
foreach(Filter filter; this.filters)
{
if(!filter.filter(message))
{
return;
}
}
Message curMessage = message;
foreach(Transform transform; this.transforms)
{
curMessage = transform.transform(curMessage);
}
foreach(Handler handler; this.handlers)
{
handler.handle(curMessage);
}
}
}

View File

@ -3,10 +3,12 @@
*/
module dlog.defaults;
import dlog.core : Logger;
import dlog.transform : MessageTransform;
import dlog.context : Context, CompilationInfo;
import dlog.core;
import dlog.basic : BasicMessage, FileHandler, Level;
import std.stdio : stdout;
import std.conv : to;
import dlog.utilities : flatten;
import std.array :join;
/**
* DefaultLogger
@ -15,6 +17,12 @@ import std.conv : to;
*/
public final class DefaultLogger : Logger
{
/**
* The joiner for multi-argument
* log messages
*/
private string multiArgJoiner;
/**
* Constructs a new default logger
*
@ -23,18 +31,93 @@ public final class DefaultLogger : Logger
*/
this(string multiArgJoiner = " ")
{
/* Use the DefaultTransform */
super(multiArgJoiner);
this.multiArgJoiner = multiArgJoiner;
addTransform(new DefaultTransform());
addHandler(new FileHandler(stdout));
}
/**
* Our logging implementation
* Logs the given message of an arbitrary amount of
* arguments and specifically sets the level to ERROR
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
*/
protected override void logImpl(string message)
public void error(TextType...)(TextType segments)
{
import std.stdio : write;
write(message);
doLog(segments, Level.ERROR);
}
/**
* Logs the given message of an arbitrary amount of
* arguments and specifically sets the level to INFO
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
*/
public void info(TextType...)(TextType segments)
{
doLog(segments, Level.INFO);
}
/**
* Logs the given message of an arbitrary amount of
* arguments and specifically sets the level to WARN
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
*/
public void warn(TextType...)(TextType segments)
{
doLog(segments, Level.WARN);
}
/**
* Logs the given message of an arbitrary amount of
* arguments and specifically sets the level to DEBUG
*
* Params:
* segments = the arbitrary argumnets (alias sequence)
*/
public void debug_(TextType...)(TextType segments)
{
doLog(segments, Level.DEBUG);
}
/**
* Performs the actual logging
* by packing up everything before
* sending it to the `log(Message)`
* method
*
* Params:
* segments = the compile-time segments
* level = the log level to use
*/
private void doLog(TextType...)(TextType segments, Level level)
{
/* Create a new basic message */
BasicMessage message = new BasicMessage();
/* Set the level */
message.setLevel(level);
/**
* Grab all compile-time arguments and make them
* into an array, then join them together and
* set that text as the message's text
*/
message.setText(join(flatten(segments), multiArgJoiner));
/* Log this message */
log(message);
}
/**
* Alias for debug_
*/
public alias dbg = debug_;
}
/**
@ -44,38 +127,115 @@ public final class DefaultLogger : Logger
*
* [date+time] (srcFile:lineNumber): message `\n`
*/
public final class DefaultTransform : MessageTransform
public final class DefaultTransform : Transform
{
/**
* Performs the default transformation
*
* Params:
* text = text input to transform
* context = the context (if any)
* Returns: the transformed text
*/
public override string transform(string text, Context ctx)
{
/* Extract the context */
string[] context = ctx.getLineInfo().toArray();
string message;
public Message transform(Message message)
{
// Only handle BasicMessage(s)
BasicMessage bmesg = cast(BasicMessage)message;
if(bmesg is null)
{
return message;
}
string text;
/* Date and time */
import std.datetime.systime : Clock, SysTime;
SysTime currTime = Clock.currTime();
import std.conv : to;
string timestamp = to!(string)(currTime);
message = "["~timestamp~"]";
text = "["~timestamp~"]";
/* Module information */
message = message ~ "\t(";
message = message ~ context[1]~":"~context[2];
message = message ~ "): "~text;
/* Level */
text = text ~ "\t(";
text = text ~ to!(string)(bmesg.getLevel());
text = text ~ "): "~bmesg.getText();
/* Add trailing newline */
message = message ~ '\n';
text = text ~ '\n';
/* Store the updated text */
bmesg.setText(text);
return message;
}
}
version(unittest)
{
import std.meta : AliasSeq;
import std.stdio : writeln;
}
/**
* Tests the DefaultLogger
*/
unittest
{
DefaultLogger logger = new DefaultLogger();
alias testParameters = AliasSeq!("This is a log message", 1.1, true, [1,2,3], 'f', logger);
// Test various types one-by-one
static foreach(testParameter; testParameters)
{
logger.info(testParameter);
}
// Test various parameters (of various types) all at once
logger.info(testParameters);
// Same as above but with a custom joiner set
logger = new DefaultLogger("(-)");
logger.info(testParameters);
writeln();
}
/**
* Printing out some mixed data-types, also using a DEFAULT context
*/
unittest
{
DefaultLogger logger = new DefaultLogger();
// Create a default logger with the default joiner
logger = new DefaultLogger();
logger.info(["a", "b", "c", "d"], [1, 2], true);
writeln();
}
/**
* Printing out some mixed data-types, also using a DEFAULT context
* but also testing out the `error()`, `warn()`, `info()` and `debug()`
*/
unittest
{
DefaultLogger logger = new DefaultLogger();
// Create a default logger with the default joiner
logger = new DefaultLogger();
// Test out `error()`
logger.error(["woah", "LEVELS!"], 69.420);
// Test out `info()`
logger.info(["woah", "LEVELS!"], 69.420);
// Test out `warn()`
logger.warn(["woah", "LEVELS!"], 69.420);
// Test out `debug_()`
logger.debug_(["woah", "LEVELS!"], 69.420);
writeln();
}

View File

@ -1,150 +0,0 @@
module dlog.nu.core;
public class Message
{
}
public interface Filter
{
public bool filter(Message message);
}
public interface Transform
{
public Message transform(Message message);
}
public interface Handler
{
public void handle(Message message);
}
import std.container.slist : SList;
// import std.range : in;
import core.sync.mutex : Mutex;
public abstract class Logger
{
private SList!(Transform) transforms;
private SList!(Filter) filters;
private SList!(Handler) handlers;
private Mutex lock; // Lock for attached handlers, filters and transforms
this()
{
this.lock = new Mutex();
}
// TODO: Handle duplicate?
public final void addTransform(Transform transform)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.transforms.insertAfter(this.transforms[], transform);
}
// TODO: Hanmdle not found explicitly?
public final void removeTransform(Transform transform)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.transforms.linearRemoveElement(transform);
}
// TODO: Handle duplicate?
public final void addFilter(Filter filter)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.filters.insertAfter(this.filters[], filter);
}
// TODO: Hanmdle not found explicitly?
public final void removeFilter(Filter filter)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.filters.linearRemoveElement(filter);
}
// TODO: Handle duplicate?
public final void addHandler(Handler handler)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.handlers.insertAfter(this.handlers[], handler);
}
// TODO: Hanmdle not found explicitly?
public final void removeHandler(Handler handler)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
this.handlers.linearRemoveElement(handler);
}
// Logs an actual message
//
// This first passes it over all filters
// then to a transform and then copies
// to each handler
public final void log(Message message)
{
scope(exit)
{
this.lock.unlock();
}
this.lock.lock();
foreach(Filter filter; this.filters)
{
if(!filter.filter(message))
{
return;
}
}
Message curMessage = message;
foreach(Transform transform; this.transforms)
{
curMessage = transform.transform(curMessage);
}
foreach(Handler handler; this.handlers)
{
handler.handle(curMessage);
}
}
}

View File

@ -11,12 +11,12 @@ public import dlog.core;
/**
* Transformations
*/
public import dlog.transform;
// public import dlog.transform;
/**
* Context for logging
*/
public import dlog.context;
// public import dlog.context;
/**
* Default logger

View File

@ -1,52 +0,0 @@
/**
* Transformations
*/
module dlog.transform;
import dlog.context : Context;
/**
* MessageTransform
*
* A message transform takes in text, applies
* a transformation to it and outputs said text
*
* Transforms may be chained
*/
public abstract class MessageTransform
{
/* Next transformation (if any) */
private MessageTransform chainedTransform;
/**
* The actual textual transformation.
*
* This is to be implemented by sub-classes
*/
public abstract string transform(string text, Context context);
/**
* Chain a transform
*/
public final void chain(MessageTransform transform)
{
chainedTransform = transform;
}
/**
* Perform the transformation
*/
public final string execute(string text, Context context)
{
/* Perform the transformation */
string transformedText = transform(text, context);
/* If there is a chained transformation */
if(chainedTransform)
{
transformedText = chainedTransform.execute(transformedText, context);
}
return transformedText;
}
}