It is currently Thu Dec 05, 2019 4:10 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: [Module] Logging with multiple/custom log targets.
PostPosted: Fri Feb 08, 2019 5:02 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Apr 27, 2010 3:20 pm
Posts: 144
Location: Wales, United Kingdom
Hey folks,

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.

Example Included - This runs on the console, so if you see nothing then compile as a Console target.

Code:
; ====================================================================================================
; 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

_________________
Thanks!


Last edited by Env on Fri Feb 08, 2019 5:33 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] Logging with multiple/custom log targets.
PostPosted: Fri Feb 08, 2019 5:12 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Tue Apr 27, 2010 3:20 pm
Posts: 144
Location: Wales, United Kingdom
Example of a custom log file writer:

Code:
#Log_FileOutput = "log.txt"

Procedure FileLogOutput(MessageLevel, Message.s)
  Protected.i file
  If FileSize(#Log_FileOutput) < 1
    file = CreateFile(#PB_Any, #Log_FileOutput)
  Else
    file = OpenFile(#PB_Any, #Log_FileOutput)
  EndIf
  If IsFile(file)
    FileSeek(file, Lof(file))
    WriteStringN(file, Message)
    CloseFile(file)
  EndIf   
EndProcedure

Log::AddLogOutput(@FileLogOutput())

_________________
Thanks!


Top
 Profile  
Reply with quote  
 Post subject: Re: [Module] Logging with multiple/custom log targets.
PostPosted: Sat Feb 09, 2019 9:51 am 
Offline
Addict
Addict

Joined: Thu Aug 30, 2007 11:54 pm
Posts: 1153
Location: right here
Very nice, thanks :)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye