Just sharing a module I put together for the purpose of having a neat and handy way to log messages.
Features:
- - Add/Remove Custom Log Handlers (e.g. If you wanted to create one for a text file output)
- Methods protected with mutex, so should be fine using with threaded applications
- Built-in console log output handler.
- Enable/disable timestamp decoration
- Set custom timestamp format
- Verbose messages which will only be posted to the log output(s) when EnableVerbose is used.
Code: Select all
; ====================================================================================================
; Title: Logging Module
; Description: Module for logging messages to custom targets
; Author: Michael R. King (Env)
; License: MIT
; Revision: 1
; If you like it, feel free to use it, if you really like it then you can buy me coffee :)
; https://ko-fi.com/mikerking
; ====================================================================================================
DeclareModule Log
Enumeration Level
#Info
#Warning
#Error
#Verbose
EndEnumeration
Prototype pLogOutput(Level, Message.s) ;- Prototype for Log Outputs
Declare AddLogOutput(*Output.pLogOutput) ;- Add a logging output procedure
Declare RemoveLogOutput(*Output.pLogOutput) ;- Remove a logging output procedure
Declare EnableVerbose(State = #True) ;- Enable Verbose messages
Declare EnableTimestamp(State = #True) ;- Enable timestamp inclusion
Declare SetTimestampFormat(Format.s = "%hh:%ii:%ss") ;- Set the Timestamp format
Declare EnableConsoleOutput(State = #True) ;- Enable built-in Console log output
Declare Info(Message.s) ;- Post an informative message to the log
Declare Warning(Message.s) ;- Post a warning to the log
Declare Error(Message.s) ;- Post an error message to the log
Declare Verbose(Message.s) ;- Post a verbose message to the log
EndDeclareModule
Module Log
Structure sLogger
*mutex
verbose.a
timestamp.a
tsFormat.s
List *output()
EndStructure
Global gLogger.sLogger
With gLogger
\mutex = CreateMutex()
\timestamp = #True
\tsFormat = "%hh:%ii:%ss"
EndWith
Procedure ConsoleLogOutput(Level, Message.s)
Select Level
Case Log::#Info
ConsoleColor(7, 0)
Case Log::#Warning
ConsoleColor(14, 0)
Case Log::#Error
ConsoleColor(12, 0)
Case Log::#Verbose
ConsoleColor(3, 0)
EndSelect
PrintN(Message)
EndProcedure
Procedure AddLogOutput(*Output.pLogOutput)
With gLogger
RemoveLogOutput(*Output)
LockMutex(\mutex)
AddElement(\output())
\output() = *Output
UnlockMutex(\mutex)
EndWith
EndProcedure
Procedure RemoveLogOutput(*Output.pLogOutput)
With gLogger
LockMutex(\mutex)
ForEach \output()
If \output() = *Output
DeleteElement(\output())
ProcedureReturn
EndIf
Next
UnlockMutex(\mutex)
EndWith
EndProcedure
Procedure EnableVerbose(State = #True)
With gLogger
If State
\verbose = #True
Else
\verbose = #False
EndIf
EndWith
EndProcedure
Procedure EnableTimestamp(State = #True)
With gLogger
If State
\timestamp = #True
Else
\timestamp = #False
EndIf
EndWith
EndProcedure
Procedure SetTimestampFormat(Format.s = "%hh:%ii:%ss")
gLogger\tsFormat = Format
EndProcedure
Procedure EnableConsoleOutput(State = #True)
If State
AddLogOutput(@ConsoleLogOutput())
Else
RemoveLogOutput(@ConsoleLogOutput())
EndIf
EndProcedure
Procedure.s Timestamp()
If gLogger\timestamp
ProcedureReturn "[" + FormatDate(gLogger\tsFormat, Date()) + "] "
EndIf
ProcedureReturn ""
EndProcedure
Procedure Info(Message.s)
Protected *handler.pLogOutput
With gLogger
LockMutex(\mutex)
ForEach \output()
*handler = \output()
*handler(#Info, Timestamp() + Message)
Next
UnlockMutex(\mutex)
EndWith
EndProcedure
Procedure Warning(Message.s)
Protected *handler.pLogOutput
With gLogger
LockMutex(\mutex)
ForEach \output()
*handler = \output()
*handler(#Warning, Timestamp() + "Warning: " + Message)
Next
UnlockMutex(\mutex)
EndWith
EndProcedure
Procedure Error(Message.s)
Protected *handler.pLogOutput
With gLogger
LockMutex(\mutex)
ForEach \output()
*handler = \output()
*handler(#Error, Timestamp() + "ERROR: " + Message)
Next
UnlockMutex(\mutex)
EndWith
EndProcedure
Procedure Verbose(Message.s)
Protected *handler.pLogOutput
With gLogger
LockMutex(\mutex)
If \verbose
ForEach \output()
*handler = \output()
*handler(#Verbose, Timestamp() + Message)
Next
EndIf
UnlockMutex(\mutex)
EndWith
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
; ========= EXAMPLE =========
; Our Custom Log Output
Procedure MyLogTarget(MessageLevel, Message.s)
Debug Message
EndProcedure
; Add our Custom Log Output to the Logger
Log::AddLogOutput(@MyLogTarget())
; Use a Console to demonstrate the logging
OpenConsole("Log Test")
EnableGraphicalConsole(#True)
Log::EnableConsoleOutput(#True)
; Enable Verbose messages
Log::EnableVerbose(#True)
; Log some messages
Log::Verbose("Example has Started (This is a verbose message which can be filtered out by disabling them)")
Log::Info("This is just an informative message!")
Log::Warning("This is a warning!")
Log::Error("An error has happened. Luckily this is just an example error.")
Log::Info("The Example has ended. Hit return to quit")
Input()
End 0
CompilerEndIf