lhs_lib/SYS/lhs_log.pbi
2021-05-21 08:04:40 +02:00

221 lines
5.8 KiB
Text

;**************************************
;*
;* lhs_log.pbi
;*
;* Single Logthread logger.
;*
;* For multiple logthread use lhs_log_ext.pbi
;*
;* (c) by René Linder
;* (c) by Linder Hard- und Software
;*
;* Lizenz LGPL V2.1
;{ Short Documentation:
;*
;* lhs_log::App_Name = "Test App"
;* lhs_log::SetLogFile("test_app.log"))
;* lhs_log::SetMaxSize(32)
;* lhs_log::SetLogLevel(lhs_log::#Error)
;* lhs_log::SetLogDateFormat("%yyyy.%mm.%dd %hh:%ii:%ss")
;* lhs_log::SetLogFileDateFormat("%yyyy_%mm_%dd_%hh_%ii_%ss")
;* lhs_log::Init()
;* lhs_log::Out("Log started.", #lhs_log::#Debug)
;* lhs_log::OutL(lhs_log::#Info, "Info Level")
;* lhs_log::Close()
;}
CompilerIf #PB_Compiler_Thread <> 1
CompilerError "Muss Threadsafe Kompiliert werden"
;Need to be compiled threadsafe
CompilerEndIf
DeclareModule lhs_log
Global.s App_Name = "lhs_Logger"
#Debug = 1
#NoDebug = 0
Enumeration LogLevel
#Info
#Warning
#Error
EndEnumeration
Declare SetLogFile(LogFileName.s)
Declare SetMaxSize(Megabyte.i)
Declare SetLogLevel(Level.i)
Declare SetLogFileDateFormat(DateFormat.s)
Declare SetLogDateFormat(DateFormat.s)
Declare Init()
Declare Out(ToLog.s, debugger.i = #NoDebug)
Declare OutL(LogType.i, ToLog.s, debugger.i = #NoDebug)
Declare Close()
EndDeclareModule
Module lhs_log
Global File_ID.i
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
Global LogFile.s = "/var/log/"+App_Name+".log"
CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
Global LogFile.s = GetPathPart(ProgramFilename())+App_Name+ ".log"
CompilerElse
CompilerError "Andere Betriebssysteme als Windows und Linux werden nicht unterstützt"
;Other Operatingsystems than Windows and Linux are currently unsupported
CompilerEndIf
Global Exit.i = 0
Global Mutex = CreateMutex()
Global Semaphore = CreateSemaphore()
Global ExitSemaphore = CreateSemaphore()
Global MaxSize.q = 32 * 1024 * 1024
Global LastSize.q = 0
Global LogLevel.i = #Info
Global LogFileDateFormat.s = "%yyyy_%mm_%dd_%hh_%ii_%ss"
Global LogDateFormat.s = "%yyyy.%mm.%dd %hh:%ii:%ss"
Global NewList Messages.s()
Procedure SetMaxSize(Megabyte.i)
If Megabyte > 0 And Megabyte < 1025
MaxSize = Megabyte * 1024 * 1024
Else
MaxSize = 32 * 1024 * 1024
EndIf
EndProcedure
Procedure SetLogLevel(Level.i)
Select Level
Case #Info
LogLevel = #Info
Case #Warning
LogLevel = #Warning
Case #Error
LogLevel = #Error
Default
LogLevel = #Error
EndSelect
EndProcedure
Procedure SetLogFile(LogFileName.s)
Protected.i TestFile_ID
TestFile_ID = OpenFile(#PB_Any, LogFileName, #PB_File_Append | #PB_File_NoBuffering)
If IsFile(TestFile_ID)
LogFile = LogFileName
CloseFile(TestFile_ID)
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
Procedure SetLogFileDateFormat(DateFormat.s)
If Len(DateFormat)>4
LogFileDateFormat = DateFormat
EndIf
EndProcedure
Procedure SetLogDateFormat(DateFormat.s)
If Len(DateFormat)>4
LogDateFormat = DateFormat
EndIf
EndProcedure
Procedure CheckMaxSize()
If LastSize = 0
LastSize = FileSize(LogFile)
EndIf
ProcedureReturn Bool(LastSize < MaxSize)
EndProcedure
Procedure UpdateLastSizeString(String.s)
LastSize + StringByteLength(String.s)
EndProcedure
Procedure LogThread(nix)
Shared Mutex
Define ToWrite.s
File_ID = OpenFile(#PB_Any, LogFile, #PB_File_Append | #PB_File_NoBuffering)
If IsFile(File_ID)
Repeat
WaitSemaphore(Semaphore)
If Exit = 1
LockMutex(Mutex)
If ListSize(Messages()) > 0
Repeat
FirstElement(Messages())
ToWrite = FormatDate(LogDateFormat, Date()) + " - " + Messages()
UpdateLastSizeString(ToWrite):WriteStringN(File_ID, ToWrite)
DeleteElement(Messages())
Until ListSize(Messages()) = 0
EndIf
CloseFile(File_ID)
UnlockMutex(Mutex)
Break
Else
LockMutex(Mutex)
FirstElement(Messages())
ToWrite = FormatDate(LogDateFormat, Date()) + " - " + Messages()
UpdateLastSizeString(ToWrite)
If Not CheckMaxSize()
CloseFile(File_ID)
If CopyFile(LogFile, LogFile+FormatDate(LogFileDateFormat, Date()))
DeleteFile(LogFile)
EndIf
File_ID = OpenFile(#PB_Any, LogFile, #PB_File_Append | #PB_File_NoBuffering)
EndIf
WriteStringN(File_ID, ToWrite)
DeleteElement(Messages())
UnlockMutex(Mutex)
EndIf
ForEver
SignalSemaphore(ExitSemaphore)
EndIf
EndProcedure
Procedure Init()
File_ID = OpenFile(#PB_Any, LogFile, #PB_File_Append | #PB_File_NoBuffering)
If IsFile(File_ID)
CloseFile(File_ID)
Else
ProcedureReturn #False
EndIf
CreateThread(@LogThread(), 1)
ProcedureReturn #True
EndProcedure
Procedure Out(ToLog.s, debugger.i = #NoDebug)
Shared Mutex
LockMutex(Mutex)
LastElement(Messages())
AddElement(Messages())
Messages() = ToLog
If debugger = #Debug
Debug ToLog
EndIf
UnlockMutex(Mutex)
SignalSemaphore(Semaphore)
EndProcedure
Procedure OutL(LogType.i, ToLog.s, debugger.i = #NoDebug)
If LogType >= LogLevel
Select LogType
Case #Info
ToLog = "Info: " + ToLog
Case #Warning
ToLog = "Warning: " + ToLog
Case #Error
ToLog = "Error: " + ToLog
Default
ToLog = "Error: " + ToLog
EndSelect
Out(ToLog, debugger)
EndIf
EndProcedure
Procedure Close()
Exit=1
SignalSemaphore(Semaphore)
WaitSemaphore(ExitSemaphore)
EndProcedure
EndModule