From 606f5159d4c3e4c2c9b0c9c6a0f88550cca89951 Mon Sep 17 00:00:00 2001 From: Ground0 Date: Fri, 21 May 2021 11:21:08 +0200 Subject: [PATCH] Add first release of Multi Logfile threaded logger --- SYS/lhs_log_ext.pbi | 317 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 SYS/lhs_log_ext.pbi diff --git a/SYS/lhs_log_ext.pbi b/SYS/lhs_log_ext.pbi new file mode 100644 index 0000000..83e4a6d --- /dev/null +++ b/SYS/lhs_log_ext.pbi @@ -0,0 +1,317 @@ +;************************************** +;* +;* 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 = 1 + #NoDebug = 0 + + 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 + List Messages.s() + EndStructure + + Global NewMap Logger.LogThreads() + Global NewList LoggerUUID.s() + + Enumeration LogLevel + #Info + #Warning + #Error + EndEnumeration + + 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() + + Procedure.s Create(Name.s) + Define.s InternalUUID + If Len(Name) > 0 And LockMutex(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" + UnlockMutex(CreateLoggerMutex) + ProcedureReturn InternalUUID + + EndIf + UnlockMutex(CreateLoggerMutex) + 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 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 + 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 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(UUID, ToLog, debugger) + 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