341 lines
9.6 KiB
Text
341 lines
9.6 KiB
Text
;**************************************
|
|
;*
|
|
;* lhs_log_ext.pbi
|
|
;*
|
|
;* Multi Logfile thread logger.
|
|
;*
|
|
;* For single logthread use lhs_log.pbi
|
|
;*
|
|
;* (c) by René Linder
|
|
;* (c) by Linder Hard- und Software
|
|
;*
|
|
;* Lizenz LGPL V2.1
|
|
|
|
;{ Short Documentation:
|
|
;*
|
|
;* lhs_log_ext::App_Name = "Test App"
|
|
;* LogUUID.s = lhs_log_ext::Create("TestLog")
|
|
;* lhs_log_ext::SetLogFile(LogUUID,"test_app.log"))
|
|
;* lhs_log_ext::SetMaxSize(LogUUID,32)
|
|
;* lhs_log_ext::SetLogLevel(LogUUID,lhs_log_ext::#Error)
|
|
;* lhs_log_ext::SetLogDateFormat(LogUUID,"%yyyy.%mm.%dd %hh:%ii:%ss")
|
|
;* lhs_log_ext::SetLogFileDateFormat(LogUUID,"%yyyy_%mm_%dd_%hh_%ii_%ss")
|
|
;* lhs_log_ext::Init(LogUUID,)
|
|
;* lhs_log_ext::Out(LogUUID,"Log started.", #lhs_log_ext::#Debug)
|
|
;* lhs_log_ext::OutL(LogUUID,lhs_log_ext::#Info, "Info Level")
|
|
;* lhs_log_ext::Close(LogUUID)
|
|
;* lhs_log_ext::StopAllLogger()
|
|
;}
|
|
CompilerIf #PB_Compiler_Thread <> 1
|
|
CompilerError "Muss Threadsafe Kompiliert werden"
|
|
;Need to be compiled threadsafe
|
|
CompilerEndIf
|
|
|
|
|
|
|
|
DeclareModule lhs_log_ext
|
|
Global.s App_Name = "lhs_ext_Logger"
|
|
#Debug = #True
|
|
#NoDebug = #False
|
|
#Console = #True
|
|
#NoConsole = #False
|
|
|
|
Structure LogThreads
|
|
Logger_UUID.s
|
|
Logger_Name.s
|
|
Thread.i
|
|
FileID.i
|
|
LogFile.s
|
|
Mutex.i
|
|
WorkerSemaphore.i
|
|
ExitSemaphore.i
|
|
Exit.i
|
|
MaxSize.q
|
|
LastSize.q
|
|
LogLevel.i
|
|
LogFileDateFormat.s
|
|
LogDateFormat.s
|
|
debugger.i
|
|
console.i
|
|
List Messages.s()
|
|
EndStructure
|
|
|
|
Global NewMap Logger.LogThreads()
|
|
Global NewList LoggerUUID.s()
|
|
|
|
Enumeration LogLevel
|
|
#NoLog
|
|
#Error
|
|
#Warning
|
|
#Info
|
|
#Debugging
|
|
EndEnumeration
|
|
|
|
Declare IsCreated(UUID.s)
|
|
Declare SetLogFile(UUID.s, LogFileName.s)
|
|
Declare SetMaxSize(UUID.s, Megabyte.i)
|
|
Declare SetLogLevel(UUID.s, Level.i)
|
|
Declare SetLogFileDateFormat(UUID.s, DateFormat.s)
|
|
Declare SetLogDateFormat(UUID.s, DateFormat.s)
|
|
Declare.s Create(Name.s)
|
|
Declare Init(UUID.s)
|
|
Declare Out(UUID.s, ToLog.s, debugger.i = #NoDebug)
|
|
Declare OutL(UUID.s, LogType.i, ToLog.s, debugger.i = #NoDebug)
|
|
Declare Close(UUID.s)
|
|
Declare StopAllLogger()
|
|
EndDeclareModule
|
|
|
|
Module lhs_log_ext
|
|
XIncludeFile "lhs_uuid.pbi"
|
|
|
|
Global CreateLoggerMutex.i = CreateMutex()
|
|
Global ConsoleMutex.i = CreateMutex()
|
|
|
|
Procedure.s Create(Name.s)
|
|
Define.s InternalUUID
|
|
If Len(Name) > 0 And TryLockMutex(CreateLoggerMutex)
|
|
InternalUUID = CreateUUID()
|
|
AddElement(LoggerUUID())
|
|
LoggerUUID() = InternalUUID
|
|
Logger(InternalUUID)\Logger_UUID = InternalUUID
|
|
Logger(InternalUUID)\Logger_Name = Name
|
|
Logger(InternalUUID)\LastSize = 0
|
|
Logger(InternalUUID)\Exit.i = 0
|
|
Logger(InternalUUID)\Mutex = CreateMutex()
|
|
Logger(InternalUUID)\WorkerSemaphore = CreateSemaphore()
|
|
Logger(InternalUUID)\ExitSemaphore = CreateSemaphore()
|
|
Logger(InternalUUID)\MaxSize.q = 32 * 1024 * 1024
|
|
Logger(InternalUUID)\LastSize.q = 0
|
|
Logger(InternalUUID)\LogLevel.i = #Info
|
|
Logger(InternalUUID)\LogFileDateFormat.s = "%yyyy_%mm_%dd_%hh_%ii_%ss"
|
|
Logger(InternalUUID)\LogDateFormat.s = "%yyyy.%mm.%dd %hh:%ii:%ss"
|
|
Logger(InternalUUID)\console = #NoConsole
|
|
UnlockMutex(CreateLoggerMutex)
|
|
ProcedureReturn InternalUUID
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure IsCreated(UUID.s)
|
|
If FindMapElement(Logger(), UUID)
|
|
ProcedureReturn #True
|
|
EndIf
|
|
ProcedureReturn #False
|
|
EndProcedure
|
|
|
|
|
|
Procedure StopAllLogger()
|
|
LockMutex(CreateLoggerMutex)
|
|
ResetList(LoggerUUID())
|
|
While NextElement(LoggerUUID())
|
|
Close(LoggerUUID())
|
|
Wend
|
|
ClearList(LoggerUUID())
|
|
If MapSize(Logger()) = 0
|
|
UnlockMutex(CreateLoggerMutex)
|
|
Else
|
|
ResetMap(Logger())
|
|
While NextMapElement(Logger())
|
|
If IsThread(Logger()\Thread)
|
|
Close(Logger()\Logger_UUID)
|
|
Else
|
|
DeleteMapElement(Logger())
|
|
EndIf
|
|
Wend
|
|
EndIf
|
|
|
|
EndProcedure
|
|
|
|
|
|
Procedure SetMaxSize(UUID.s, Megabyte.i)
|
|
If IsCreated(UUID)
|
|
If Megabyte > 0 And Megabyte < 1025
|
|
Logger(UUID)\MaxSize = Megabyte * 1024 * 1024
|
|
Else
|
|
Logger(UUID)\MaxSize = 32 * 1024 * 1024
|
|
EndIf
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure SetLogLevel(UUID.s, Level.i)
|
|
If IsCreated(UUID)
|
|
Select Level
|
|
Case #Info
|
|
Logger(UUID)\LogLevel = #Info
|
|
Case #Warning
|
|
Logger(UUID)\LogLevel = #Warning
|
|
Case #Error
|
|
Logger(UUID)\LogLevel = #Error
|
|
Default
|
|
Logger(UUID)\LogLevel = #Error
|
|
EndSelect
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure SetLogFile(UUID.s, LogFileName.s)
|
|
Protected.i TestFile_ID
|
|
If IsCreated(UUID)
|
|
TestFile_ID = OpenFile(#PB_Any, LogFileName, #PB_File_Append | #PB_File_NoBuffering)
|
|
If IsFile(TestFile_ID)
|
|
Logger(UUID)\LogFile = LogFileName
|
|
CloseFile(TestFile_ID)
|
|
ProcedureReturn #True
|
|
Else
|
|
ProcedureReturn #False
|
|
EndIf
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure SetLogFileDateFormat(UUID.s, DateFormat.s)
|
|
If IsCreated(UUID)
|
|
If Len(DateFormat)>4
|
|
Logger(UUID)\LogFileDateFormat = DateFormat
|
|
EndIf
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure SetLogDateFormat(UUID.s, DateFormat.s)
|
|
If IsCreated(UUID)
|
|
If Len(DateFormat)>4
|
|
Logger(UUID)\LogDateFormat = DateFormat
|
|
EndIf
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure CheckMaxSize(UUID.s)
|
|
If IsCreated(UUID)
|
|
If Logger(UUID)\LastSize = 0
|
|
Logger(UUID)\LastSize = FileSize(Logger(UUID)\LogFile)
|
|
EndIf
|
|
ProcedureReturn Bool(Logger(UUID)\LastSize < Logger(UUID)\MaxSize)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure UpdateLastSizeString(UUID.s, String.s)
|
|
If IsCreated(UUID)
|
|
Logger(UUID)\LastSize + StringByteLength(String.s)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure LogThread(UUID_Address)
|
|
Protected MyUUID.s = PeekS(UUID_Address)
|
|
Protected File_ID
|
|
Define ToWrite.s
|
|
SignalSemaphore(Logger(MyUUID)\ExitSemaphore)
|
|
WaitSemaphore(Logger(MyUUID)\WorkerSemaphore)
|
|
File_ID = OpenFile(#PB_Any, Logger(MyUUID)\LogFile, #PB_File_Append | #PB_File_NoBuffering)
|
|
If IsFile(File_ID)
|
|
Repeat
|
|
WaitSemaphore(Logger(MyUUID)\WorkerSemaphore)
|
|
If Exit = 1
|
|
LockMutex(Logger(MyUUID)\Mutex)
|
|
If ListSize(Logger(MyUUID)\Messages()) > 0
|
|
Repeat
|
|
FirstElement(Logger(MyUUID)\Messages())
|
|
ToWrite = FormatDate(Logger(MyUUID)\LogDateFormat, Date()) + " - " + Logger(MyUUID)\Messages()
|
|
UpdateLastSizeString(MyUUID, ToWrite):WriteStringN(File_ID, ToWrite)
|
|
DeleteElement(Logger(MyUUID)\Messages())
|
|
Until ListSize(Logger(MyUUID)\Messages()) = 0
|
|
EndIf
|
|
CloseFile(File_ID)
|
|
UnlockMutex(Logger(MyUUID)\Mutex)
|
|
Break
|
|
Else
|
|
LockMutex(Logger(MyUUID)\Mutex)
|
|
FirstElement(Logger(MyUUID)\Messages())
|
|
ToWrite = FormatDate(Logger(MyUUID)\LogDateFormat, Date()) + " - " + Logger(MyUUID)\Messages()
|
|
UpdateLastSizeString(MyUUID, ToWrite)
|
|
If Not CheckMaxSize(MyUUID)
|
|
CloseFile(File_ID)
|
|
If CopyFile(Logger(MyUUID)\LogFile, Logger(MyUUID)\LogFile+FormatDate(Logger(MyUUID)\LogFileDateFormat, Date()))
|
|
DeleteFile(Logger(MyUUID)\LogFile)
|
|
EndIf
|
|
File_ID = OpenFile(#PB_Any, Logger(MyUUID)\LogFile, #PB_File_Append | #PB_File_NoBuffering)
|
|
EndIf
|
|
WriteStringN(File_ID, ToWrite)
|
|
DeleteElement(Logger(MyUUID)\Messages())
|
|
UnlockMutex(Logger(MyUUID)\Mutex)
|
|
EndIf
|
|
ForEver
|
|
SignalSemaphore(Logger(MyUUID)\ExitSemaphore)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure Init(UUID.s)
|
|
If IsCreated(UUID)
|
|
File_ID = OpenFile(#PB_Any, Logger(UUID)\LogFile, #PB_File_Append | #PB_File_NoBuffering)
|
|
If IsFile(File_ID)
|
|
CloseFile(File_ID)
|
|
Else
|
|
ProcedureReturn #False
|
|
EndIf
|
|
|
|
CreateThread(@LogThread(), @UUID)
|
|
WaitSemaphore(Logger(UUID)\ExitSemaphore)
|
|
SignalSemaphore(Logger(UUID)\WorkerSemaphore)
|
|
ProcedureReturn #True
|
|
Else
|
|
ProcedureReturn #False
|
|
EndIf
|
|
|
|
EndProcedure
|
|
|
|
Procedure OutPutConsole(ToLog.s)
|
|
;Hardlock ConsoleOutput
|
|
If LockMutex(ConsoleMutex)
|
|
PrintN(ToLog)
|
|
UnlockMutex(ConsoleMutex)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure Out(UUID.s, ToLog.s, debugger.i = #NoDebug)
|
|
If IsCreated(UUID)
|
|
LockMutex(Logger(UUID)\Mutex)
|
|
LastElement(Logger(UUID)\Messages())
|
|
AddElement(Logger(UUID)\Messages())
|
|
Logger(UUID)\Messages() = ToLog
|
|
If Logger(UUID)\debugger = #Debug
|
|
Debug ToLog
|
|
EndIf
|
|
If Logger(UUID)\console = #Console
|
|
OutPutConsole(ToLog)
|
|
EndIf
|
|
UnlockMutex(Logger(UUID)\Mutex)
|
|
SignalSemaphore(Logger(UUID)\WorkerSemaphore)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure OutL(UUID.s, LogType.i, ToLog.s, debugger.i = #NoDebug)
|
|
If IsCreated(UUID)
|
|
If debugger = #Debug
|
|
LogType = #Debugging
|
|
EndIf
|
|
|
|
If LogType <= Logger(UUID)\LogLevel Or debugger = #Debug
|
|
Select LogType
|
|
Case #Info
|
|
ToLog = "Info: " + ToLog
|
|
Case #Warning
|
|
ToLog = "Warning: " + ToLog
|
|
Case #Error
|
|
ToLog = "Error: " + ToLog
|
|
Case #Debugging
|
|
ToLog = "Debug: " + ToLog
|
|
Default
|
|
ToLog = "Debug: " + ToLog
|
|
EndSelect
|
|
Out(UUID, ToLog, debugger)
|
|
ProcedureReturn #True
|
|
EndIf
|
|
EndIf
|
|
EndProcedure
|
|
|
|
Procedure Close(UUID.s)
|
|
If IsCreated(UUID)
|
|
Logger(UUID)\Exit=1
|
|
SignalSemaphore(Logger(UUID)\WorkerSemaphore)
|
|
WaitSemaphore(Logger(UUID)\ExitSemaphore)
|
|
DeleteMapElement(Logger(), UUID)
|
|
EndIf
|
|
EndProcedure
|
|
|
|
EndModule
|