unit uAppLog; {$mode objfpc}{$H+} interface uses Classes, SysUtils; type TOnAppLogMessageProc = procedure (AMessage : String) of object; var TextLog: TStringList; {$ifopt D+} DebugLogging : boolean; procedure Debug(AMessage:String); overload; {$endif} procedure Log(AMessage:String); overload; procedure LogPause; procedure LogResume; procedure LogToFile(AFileName:String); procedure LogToFileClose; procedure RegisterAppLogMessageHandler(AProc : TOnAppLogMessageProc); procedure UnregisterAppLogMessageHandler(AProc : TOnAppLogMessageProc); implementation var CacheLog : TStringList; LogFreeze : boolean; LogFileName : String; Handlers : array of TOnAppLogMessageProc; {$ifopt D+} procedure Debug(AMessage: String); begin if DebugLogging then Log(AMessage); end; {$endif} procedure Log(AMessage:String); var AFileName : String; T : TextFile; I : integer; begin if AMessage = '' then AMessage := ''; AMessage:=FormatDateTime('YYYY-MM-DD hh:nn:ss: ', Now) + AMessage; if LogFreeze then begin CacheLog.Add(AMessage); Exit; end else if CacheLog.Count > 0 then begin CacheLog.Add(AMessage); AMessage:=CacheLog.Text; CacheLog.Clear; end; TextLog.Add(AMessage); if LogFileName <> '' then begin AFileName := LogFileName; try System.Assign(T, AFileName); System.Append(T); System.WriteLn(T, AMessage); System.Close(T); except LogFileName:=''; Log('error writing "' + AFileName + '" log file.'); end; end; //if Assigned(Hold) then // Hold(AMessage); for I := Low(Handlers) to High(Handlers) do if Assigned(Handlers[I]) then begin Handlers[I](AMessage); end; end; procedure LogToFileClose; begin if LogFileName = '' then exit; Log('closed "' + LogFileName + '" log file.'); LogFileName := ''; end; procedure RegisterAppLogMessageHandler(AProc: TOnAppLogMessageProc); begin SetLength(Handlers, Length(Handlers) + 1); Handlers[High(Handlers)]:=AProc; end; procedure UnregisterAppLogMessageHandler(AProc: TOnAppLogMessageProc); var I : Integer; begin for I := Low(Handlers) to High(Handlers) do if Handlers[I] = AProc then Handlers[I]:=nil; end; procedure LogPause; begin LogFreeze := True; end; procedure LogResume; begin LogFreeze := False; end; procedure LogToFile(AFileName: String); var T : TextFile; begin LogToFileClose; LogFileName:=AFileName; try System.Assign(T, AFileName); if FileExists(AFileName) then System.Append(T) else System.Rewrite(T); // Write All existing log data for session to file. System.WriteLn(T, TextLog.Text); System.Close(T); Log('opened "' + AFileName + '" log file.'); except LogFileName:=''; Log('unable to open "' + AFileName + '" log file.'); end; end; initialization {$ifopt D+} DebugLogging := False; {$endif} LogFileName := ''; TextLog := TStringList.Create; CacheLog := TStringList.Create; SetLength(Handlers,0); LogFreeze := False; Log('Initial startup'); finalization LogFreeze := False; Log('Terminated ' + IntToStr(ExitCode) + '.'); LogToFileClose; if Assigned(TextLog) then FreeAndNil(TextLog); if Assigned(CacheLog) then FreeAndNil(CacheLog); SetLength(Handlers,0); end.