aboutsummaryrefslogtreecommitdiff
path: root/lib/Log/Simple.rakumod
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Log/Simple.rakumod')
-rw-r--r--lib/Log/Simple.rakumod314
1 files changed, 314 insertions, 0 deletions
diff --git a/lib/Log/Simple.rakumod b/lib/Log/Simple.rakumod
new file mode 100644
index 0000000..870edd0
--- /dev/null
+++ b/lib/Log/Simple.rakumod
@@ -0,0 +1,314 @@
+#! /usr/bin/env false
+
+use v6.d;
+
+use Log;
+use Log::Level;
+
+#| A simple implementation of Log.
+unit class Log::Simple is Log;
+
+#| An array of hashes. Each has must have a handle key, with an IO::Handle to
+#| print messages to. A level key with an integer to signify a Log::Level is
+#| also required.
+has @!outputs;
+
+#| A supplier to emit messages to.
+has Supplier $!messages;
+
+#| When enabled, include hostname in the log message. This can be useful when
+#| running the application redundantly in a cluster with centralized logging.
+has Bool $.hostname = False;
+
+#| Send an emergency message.
+multi method emergency (
+ #| The message to print.
+ Str:D $message,
+) {
+ $!messages.emit({
+ message => self!message('emergency', $message),
+ level => 0,
+ })
+}
+
+#| Send a formatted emergency message.
+multi method emergency (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('emergency', $format.sprintf(|@args)),
+ level => 0,
+ })
+}
+
+#| Send an alert message.
+multi method alert (
+ #| The message to print.
+ Str:D $message,
+) {
+ $!messages.emit({
+ message => self!message('alert', $message),
+ level => 1,
+ })
+}
+
+#| Send a formatted alert message.
+multi method alert (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('alert', $format.sprintf(|@args)),
+ level => 1,
+ })
+}
+
+#| Send a critical message.
+multi method critical (
+ #| The message to print.
+ Str:D $message,
+) {
+ $!messages.emit({
+ message => self!message('critical', $message),
+ level => 2,
+ })
+}
+
+#| Send a formatted critical message.
+multi method critical (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('critical', $format.sprintf(|@args)),
+ level => 2,
+ })
+}
+
+#| Send an error message.
+multi method error (
+ #| The message to print.
+ Str:D $message,
+) {
+ $!messages.emit({
+ message => self!message('error', $message),
+ level => 3,
+ })
+}
+
+#| Send a formatted error message.
+multi method error (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('error', $format.sprintf(|@args)),
+ level => 3,
+ })
+}
+
+#| Send a warning message.
+multi method warning (
+ #| The message to print.
+ Str:D $message,
+) {
+ $!messages.emit({
+ message => self!message('warning', $message),
+ level => 4,
+ })
+}
+
+#| Send a formatted warning message.
+multi method warning (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('warning', $format.sprintf(|@args)),
+ level => 4,
+ })
+}
+
+#| Send a notice message. This is the "normal" level to publish log entries on.
+multi method notice (
+ #| The message to print.
+ Str:D $message
+) {
+ $!messages.emit({
+ message => self!message('notice', $message),
+ level => 5,
+ })
+}
+
+#| Send a formatted notice message. This is the "normal" level to publish log
+#| entries on.
+multi method notice (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('notice', $format.sprintf(|@args)),
+ level => 5,
+ })
+}
+
+#| Send an informational message.
+multi method info (
+ #| The message to print.
+ Str:D $message
+) {
+ $!messages.emit({
+ message => self!message('info', $message),
+ level => 6,
+ })
+}
+
+#| Send a formatted informational message.
+multi method info (
+ #| The printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('info', $format.sprintf(|@args)),
+ level => 6,
+ })
+}
+
+#| Send a debug message.
+multi method debug (
+ #| The message to print.
+ Str:D $message,
+) {
+ $!messages.emit({
+ message => self!message('debug', $message),
+ level => 7,
+ })
+}
+
+#| Send a formatted debug message.
+multi method debug (
+ #| A printf-style format string.
+ Str:D $format,
+
+ #| Arguments to substitute into the format string placeholders.
+ *@args,
+) {
+ $!messages.emit({
+ message => self!message('debug', $format.sprintf(|@args)),
+ level => 7,
+ })
+}
+
+#| Add an output to the logger.
+multi method add-output (
+ #| The IO::Handle to write log messages to.
+ IO::Handle:D $handle,
+
+ #| The log level for this particular stream.
+ Int() $level where Log::Level::Emergency ≤ * ≤ Log::Level::Debug,
+
+ #| A filter function to apply to any messages sent to the output.
+ Callable :$filter?,
+) {
+ @!outputs.push({
+ :$handle,
+ :$level,
+ :$filter,
+ });
+}
+
+#| Convenience method to get the callee name. This is the package name if one
+#| exists, or the source file name.
+method !callee (
+ #| The depth of which to get the callframe.
+ Int:D $depth = 3,
+
+ --> Str
+) {
+ my $file = callframe($depth).annotations<file>;
+
+ return $file unless $file.ends-with(')');
+
+ $file.words.tail.substr(1, *-1);
+}
+
+#| Convenience method for formatting the message as desired.
+method !message (
+ #| A human readable identifier for the level.
+ Str:D $level,
+
+ #| The original message to be logged.
+ Str:D $message,
+
+ --> Str
+) {
+ (
+ DateTime.now.utc,
+ ($*KERNEL.hostname if $!hostname),
+ self!callee,
+ "<$level>",
+ )».Str.join(' ') ~ ": $message"
+}
+
+submethod TWEAK
+{
+ # Set up the Supply for messages.
+ $!messages .= new;
+ $!messages.Supply.tap(sub (%payload) {
+ @!outputs
+ .race
+ .grep(%payload<level> ≤ *<level>)
+ .grep({ $_<filter> ?? $_<filter>(%payload).so !! True })
+ .map(*<handle>.say(%payload<message>))
+ ;
+ });
+}
+
+=begin pod
+
+=NAME Log::Simple
+=VERSION 0.0.0
+=AUTHOR Patrick Spek <p.spek@tyil.nl>
+
+=begin LICENSE
+Copyright © 2020
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU Affero General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+details.
+
+You should have received a copy of the GNU Affero General Public License along
+with this program. If not, see http://www.gnu.org/licenses/.
+=end LICENSE
+
+=end pod
+
+# vim: ft=raku noet sw=8 ts=8