From 5eb73a3fbcbc4ba46f8e174349b93f78873e1cc9 Mon Sep 17 00:00:00 2001 From: "Tristan B. Kildaire" Date: Thu, 23 Dec 2021 12:14:36 +0200 Subject: [PATCH] Initial commit --- README.md | 91 ++++++++++++++++++++++ dub.json | 10 +++ source/dlog/core.d | 148 ++++++++++++++++++++++++++++++++++++ source/dlog/defaults.d | 22 ++++++ source/dlog/package.d | 5 ++ source/dlog/testing/thing.d | 16 ++++ 6 files changed, 292 insertions(+) create mode 100644 README.md create mode 100644 dub.json create mode 100644 source/dlog/core.d create mode 100644 source/dlog/defaults.d create mode 100644 source/dlog/package.d create mode 100644 source/dlog/testing/thing.d diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b4be20 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +dlog +==== + +**Simple and modular logging library** + +
+`[2021-Dec-23 11:17:35.3527637] (source/dlog/testing/thing.d:12): This is a log message` +
+ +--- + +## Usage + +We recommend you use [dub](http://code.dlang.org) to add dlog to your project as follows: + +``` +dub add dlog +``` + +### Components + +dlog is formed out of two main components: + +1. `Logger` + * The logger contains the needed barebones for facilitating the actual logging of text +2. `MessageTransform` + * A MessageTransform is attached to a logger and performs manipulation on the text input into the logger for logging + * They may be chained as to perform multiple transformations in a stream-like fashion + +### Quick start + +If you want to immediately begin logging text usin the defaults and don't care about implementing your own transformations then you can +simply use the defaulkt logger as follows: + +```d +import dlog; + +Logger logger = new DefaultLogger(); + + +logger.log("This is a log message"); +logger.log(1); +logger.log(1==1); +logger.log([1,2,3]); +``` + +This will output the following: + +``` +[2021-Dec-23 11:17:35.3527637] (source/dlog/testing/thing.d:12): This is a log message +[2021-Dec-23 11:17:35.3527717] (source/dlog/testing/thing.d:13): 1 +[2021-Dec-23 11:17:35.3527789] (source/dlog/testing/thing.d:14): true +[2021-Dec-23 11:17:35.3527871] (source/dlog/testing/thing.d:15): [1, 2, 3] +``` + +As you can see file and line numbering of where the `log()` function is called appears in the log message which can be quite helpful +for debugging. + +### Custom loggers + +Perhaps the default transformation, `DefaultTransform`, may not be what you want. Maybe you want the module name included in the logged +messages or perhaps don't want the date-and-timestamp included at all. All of this can be up to you if you choose to implement your own +message transform. + +You will need to start off with a class that inherits from the `MessageTransform` class and then which overrides the `transform` method as shown below: + +```d +import dlog; + +public class CustomTranform : MessageTransform +{ + public override string transform(string text, string[] context) + { + string transformed; + + + + return transformed; + } +} +``` + +Additional information, besides the text being logged itself (this is the `string text` argument), comes in the form of a string array as `string[] context` +the contents of which are described below: + +1. `context[0]` +TODO + +## License + +LGPLv2 \ No newline at end of file diff --git a/dub.json b/dub.json new file mode 100644 index 0000000..dbe13d3 --- /dev/null +++ b/dub.json @@ -0,0 +1,10 @@ +{ + "authors": [ + "Tristan B. Kildaire" + ], + "copyright": "Copyright © 2021, Tristan B. Kildaire", + "description": "Simple and modular logging library", + "license": "LGPLv2", + "name": "dlog", + "targetType": "library", +} diff --git a/source/dlog/core.d b/source/dlog/core.d new file mode 100644 index 0000000..3d43066 --- /dev/null +++ b/source/dlog/core.d @@ -0,0 +1,148 @@ +module dlog.core; + +import std.conv : to; +import dlog.defaults; + +/** +* DefaultTransform +* +* Provides a transformation of the kind +* +* [date+time] (srcFile:lineNumber): message `\n` +*/ +public final class DefaultTransform : MessageTransform +{ + + /** + * Our transformation + */ + public override string transform(string text, string[] context) + { + string message; + + /* Date and time */ + import std.datetime.systime : Clock, SysTime; + SysTime currTime = Clock.currTime(); + import std.conv : to; + string timestamp = to!(string)(currTime); + message = "["~timestamp~"]"; + + /* Module information */ + message = message ~ "\t("; + message = message ~ context[1]~":"~context[2]; + message = message ~ "): "~text; + + /* Add trailing newline */ + message = message ~ '\n'; + + return message; + } +} + +/** +* Logger +* +* Represents a logger instance +*/ +public class Logger +{ + /* Starting transformation */ + private MessageTransform messageTransform; + + /** + * Constructs a new Logger with the default + * MessageTransform, see TODO (ref module) + */ + this() + { + this(new DefaultTransform()); + } + + /** + * Constructs a new Logger with the given + * MessageTransform + */ + this(MessageTransform messageTransform) + { + this.messageTransform = messageTransform; + } + + /** + * Log a message + */ + public final void log(TextType)(TextType message, string c1 = __FILE_FULL_PATH__, + string c2 = __FILE__, ulong c3 = __LINE__, + string c4 = __MODULE__, string c5 = __FUNCTION__, + string c6 = __PRETTY_FUNCTION__, string[] contextExtras = null) + { + /* Construct context array */ + string[] context = [c1, c2, to!(string)(c3), c4, c5, c6]~contextExtras; + + /* Apply the transformation on the message */ + string transformedMesage = messageTransform.execute(to!(string)(message), context); + + /* Call the underlying logger implementation */ + logImpl(transformedMesage); + } + + /** + * Logging implementation, this is where the fina + * transformed text will be transferred to and finally + * logged + */ + protected abstract void logImpl(string message); +} + +/** +* 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; + + /* Transformation (implement this) */ + public abstract string transform(string text, string[] context); + + /* Chain a transform */ + public final void chain(MessageTransform transform) + { + chainedTransform = transform; + } + + /* Perform the transformation */ + public final string execute(string text, string[] context) + { + /* Perform the transformation */ + string transformedText = transform(text, context); + + /* If there is a chained transformation */ + if(chainedTransform) + { + transformedText = chainedTransform.execute(transformedText, context); + } + + return transformedText; + } +} + +/** +* Tests the DefaultLogger +*/ +unittest +{ + Logger logger = new DefaultLogger(); + + logger.log("This is a log message"); + logger.log(1); + logger.log(1.1); + logger.log(true); + logger.log([1,2,3]); + logger.log('f'); + logger.log(logger); +} \ No newline at end of file diff --git a/source/dlog/defaults.d b/source/dlog/defaults.d new file mode 100644 index 0000000..ae66ef4 --- /dev/null +++ b/source/dlog/defaults.d @@ -0,0 +1,22 @@ +module dlog.defaults; + +import dlog.core : Logger; + +/** +* DefaultLogger +* +* The default logger logs to standard output (fd 0) +*/ +public final class DefaultLogger : Logger +{ + this() + { + /* Use the DefaultTransform */ + } + + protected override void logImpl(string message) + { + import std.stdio : write; + write(message); + } +} diff --git a/source/dlog/package.d b/source/dlog/package.d new file mode 100644 index 0000000..0e42c3b --- /dev/null +++ b/source/dlog/package.d @@ -0,0 +1,5 @@ +module dlog; + +/* TODO: Add imports */ +public import dlog.core; +public import dlog.defaults; diff --git a/source/dlog/testing/thing.d b/source/dlog/testing/thing.d new file mode 100644 index 0000000..2d64101 --- /dev/null +++ b/source/dlog/testing/thing.d @@ -0,0 +1,16 @@ +module dlog.testing.thing; + +import dlog; + +/** +* Tests the DefaultLogger +*/ +unittest +{ + Logger logger = new DefaultLogger(); + + logger.log("This is a log message"); + logger.log(1); + logger.log(true); + logger.log([1,2,3]); +}