Mega Code Archive

 
Categories / Delphi / Examples
 

A simple yet useful Logger component (replaces TComponent)

Title: A simple yet useful Logger component (replaces TComponent) Question: Ever wonderd how to easily incorporate logging functionality into your delphi programs, without the hassle of copying the same code over and over again to every unit ? Answer: The TLogger component explained here is a simple and very useful tool for programmers when they want to incorporate LOGGING capabilities into their programs. The TLogger presented here is thread-safe and is extreamly easy to use. It also detects if the parent is of the same base type and inherits the Syncronization (thread safe behaviour) from the parent. Usage: 1 Create your TComponent based component with the TLogger as the inherited class instead Ex: TMyCompo = class(TLogger) private protected public published end; 2 Initialize the LogPath property. It defaults to the windows TEMP dir 3 Call the Log(''); method to log something ! The .log file is named YYYYMMDD.LOG where the Y,M and D are the year,month and date. -----------CUT-------------CUT-------------- unit Logger; interface uses Windows, Messages, SysUtils, Classes, SyncObjs; type TLogger = class(TComponent) private { Private declarations } protected { Protected declarations } Sync : TCriticalSection; FreeSync : Boolean; public { Public declarations } LogPath : String; LogFileName : String; Constructor Create(AOwner:TComponent); Override; Destructor Destroy; Override; { LOG procedure } Procedure Log( Str:String ); Virtual; published { Published declarations } end; implementation { TLogger } constructor TLogger.Create(AOwner:TComponent); Var B : Array[0..1024] of Char; P : PChar; begin Inherited Create(AOwner); { LogPath = Windows Temp directory } P := @B; GetTempPath( Sizeof(B),P); LogPath := StrPas(P); { If the owner is a TLogger get the parameters from it ! } If (AOwner IS TLogger) then Begin LogPath := TLogger(AOwner).LogPath; LogFileName := TLogger(AOwner).LogFileName; Sync := TLogger(AOwner).Sync; FreeSync := False; End Else Begin { Create the logger component and make sure we free it later } Sync := TCriticalSection.Create; FreeSync := True; End; end; destructor TLogger.Destroy; begin { Free the Sync object } If Assigned(Sync) AND (FreeSync) then Begin { Make sure nobody else is using the Sync object } Sync.Enter; Sync.Leave; { Free it } Sync.Free; Sync := NIL; End; { Call inherited method } Inherited Destroy; end; Procedure TLogger.Log( Str: String ); Var F : TFileStream; S : String; FN : String; OK : Boolean; Times : Integer; begin Try { Enter Sync state } Sync.Enter; { Build Log-String } S := FormatDateTime('HH:NN:SS',Now)+' '+Str+#13#10 { Build Filename } If LogFileName='' then FN := IncludeTrailingPathDelimiter( LogPath )+ FormatDateTime('YYYYMMDD',Date)+'.log'; Else FN := IncludeTrailingPathDelimiter( LogPath )+LogFileName; { Set timer } Times := 10; // Maximum 10 tries Repeat OK := True; Try F := NIL; Try { Open / Create file } If FileExists( FN ) then F := TFileStream.Create( FN, fmOpenWrite OR fmShareDenyWrite ) Else F := TFileStream.Create( FN, fmCreate OR fmShareDenyWrite ); { Go to end } F.Seek( 0, soFromEnd); { Append data } F.Write( S[1], Length(S)); Finally F.Free; End; Except On E:Exception do Begin OK := False; { Decrement try counter } Dec( Times ); { Terinate looping or sleep 10 ms and try again } If Times=0 then OK := True Else SleepEx(10,True); End; End; Until OK; Finally { Leave sync } Sync.Leave; End; end; end.