home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 January / Chip_2003-01_cd1.bin / zkuste / delphi / unity / d56 / FNDUTL.ZIP / System / cLog.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2002-10-29  |  13.3 KB  |  419 lines

  1. {$INCLUDE ..\cDefines.inc}
  2. unit cLog;
  3.  
  4. interface
  5.  
  6. uses
  7.   // Delphi
  8.   SysUtils,
  9.   Classes;
  10.  
  11.  
  12.  
  13. {                                                                              }
  14. {                              Log unit v3.02                                  }
  15. {                                                                              }
  16. {        This unit is copyright ⌐ 2002 by David Butler (david@e.co.za)         }
  17. {                                                                              }
  18. {                  This unit is part of Delphi Fundamentals.                   }
  19. {                     Its original file name is cLog.pas                       }
  20. {       The latest version is available from the Fundamentals home page        }
  21. {                     http://fundementals.sourceforge.net/                     }
  22. {                                                                              }
  23. {                I invite you to use this unit, free of charge.                }
  24. {        I invite you to distibute this unit, but it must be for free.         }
  25. {             I also invite you to contribute to its development,              }
  26. {             but do not distribute a modified copy of this file.              }
  27. {                                                                              }
  28. {          A forum is available on SourceForge for general discussion          }
  29. {             http://sourceforge.net/forum/forum.php?forum_id=2117             }
  30. {                                                                              }
  31. {                                                                              }
  32. { Revision history:                                                            }
  33. {   2002/02/07  v2.01  Added TLog component from cDebug to cSysUtils.          }
  34. {   2002/09/04  v3.02  Moved TLog component to cLog unit.                      }
  35. {                                                                              }
  36.  
  37.  
  38.  
  39. {                                                                              }
  40. { Log Component                                                                }
  41. {                                                                              }
  42. {$TYPEINFO ON}
  43. type
  44.   TLogClass = (lcInfo, lcError, lcWarning, lcDebug, lcEndRepeat,
  45.                lcUserEventBegin, lcUserEventEnd);
  46.   TLogEvent = Procedure (const Sender : TObject; const LogClass : TLogClass;
  47.       const LogMsg : String) of object;
  48.   TLogEditMessageEvent = Procedure (const Sender : TObject; const LogClass : TLogClass;
  49.       var LogMsg : String) of object;
  50.   TLogFileEvent = Procedure (const Sender : TObject; const LogClass : TLogClass;
  51.       var LogMsg : String; var LogToFile : Boolean) of object;
  52.   TLogOptions = Set of (loLogToFile,           // Output log to a file
  53.                         loKeepFileOpen,        // Keep log file open between messages
  54.                         loLogToDebugLog,       // Log to system debug log (IDE)
  55.                         loNoLogEvent,          // Don't generate log event
  56.                         loLogDate,             // Include date in log message
  57.                         loLogTime,             // Include time in log message
  58.                         loLogMilliSecDiff,     // Include milliseconds since last log in message
  59.                         loIgnoreLogFailure,    // Ignore log failures
  60.                         loCheckRepeats,        // Log first and last of repeated messages
  61.                         loIgnoreClassDebug,    // Ignore messages of class Debug
  62.                         loIgnoreClassError,    // Ignore messages of class Error
  63.                         loIgnoreClassWarning,  // Ignore messages of class Warning
  64.                         loIgnoreClassInfo);    // Ignore messages of class Info
  65.   TLog = class (TComponent)
  66.     protected
  67.     FOnLog          : TLogEvent;
  68.     FOnEditMessage  : TLogEditMessageEvent;
  69.     FOnLogFile      : TLogFileEvent;
  70.     FLogFile        : TFileStream;
  71.     FLogFileName    : String;
  72.     FLogOptions     : TLogOptions;
  73.     FLastLog        : Cardinal;
  74.     FLastLogMsg     : String;
  75.     FLogRepeatCount : Integer;
  76.     FLogTo          : TLog;
  77.  
  78.     Procedure SetLogFileName (const LogFileName : String);
  79.     Procedure SetLogOptions (const LogOptions : TLogOptions);
  80.     Procedure SetLogTo (const LogTo : TLog);
  81.  
  82.     Procedure Init; virtual;
  83.     Procedure RaiseError (const Msg : String);
  84.  
  85.     Procedure Notification (AComponent : TComponent; Operation : TOperation); override;
  86.  
  87.     Procedure TriggerLogMsg (const Sender : TObject; const LogClass : TLogClass;
  88.               const LogMsg : String); virtual;
  89.     Procedure Log (const LogClass : TLogClass; const LogMsg : String); overload;
  90.     Procedure Log (const LogMsg : String); overload;
  91.     Procedure LogDebug (const LogMsg : String);
  92.     Procedure LogError (const LogMsg : String);
  93.     Procedure LogWarning (const LogMsg : String);
  94.  
  95.     public
  96.     Constructor Create (AOwner : TComponent); override;
  97.     Destructor Destroy; override;
  98.  
  99.     Procedure Log (const Sender : TObject; const LogClass : TLogClass;
  100.               const LogMsg : String); overload; virtual;
  101.  
  102.     Procedure DeleteLogFile;
  103.  
  104.     Procedure LoadLogFileInto (const Destination : TStrings; const Size : Integer = -1);
  105.  
  106.     Property  OnLog : TLogEvent read FOnLog write FOnLog;
  107.     Property  OnEditMessage : TLogEditMessageEvent read FOnEditMessage write FOnEditMessage;
  108.     Property  OnLogFile : TLogFileEvent read FOnLogFile write FOnLogFile;
  109.     Property  LogFileName : String read FLogFileName write SetLogFileName;
  110.     Property  LogOptions : TLogOptions read FLogOptions write SetLogOptions;
  111.     Property  LogTo : TLog read FLogTo write SetLogTo;
  112.   end;
  113.   ELog = class (Exception);
  114.  
  115.  
  116.  
  117. {                                                                              }
  118. { Application Log                                                              }
  119. {                                                                              }
  120. Function  AppLog : TLog;
  121.  
  122.  
  123.  
  124. implementation
  125.  
  126. uses
  127.   // Delphi
  128.   Windows,
  129.  
  130.   // Fundamentals
  131.   cUtils,
  132.   cStrings;
  133.  
  134.  
  135.  
  136. {                                                                              }
  137. { Log Component                                                                }
  138. {                                                                              }
  139. Constructor TLog.Create (AOwner : TComponent);
  140.   Begin
  141.     inherited Create (AOwner);
  142.     Init;
  143.   End;
  144.  
  145. Destructor TLog.Destroy;
  146.   Begin
  147.     FreeAndNil (FLogFile);
  148.     inherited Destroy;
  149.   End;
  150.  
  151. Procedure TLog.Init;
  152.   Begin
  153.     FLogFileName := WithoutPrefix (ObjectClassName (self) + '.log', 'T');
  154.     FLogOptions := [{$IFDEF DEBUG}loLogToDebugLog{$ENDIF}];
  155.     {$IFDEF OS_MSWIN}
  156.     FLastLog := GetTickCount;
  157.     {$ENDIF}
  158.   End;
  159.  
  160. Procedure TLog.RaiseError (const Msg : String);
  161.   Begin
  162.     raise ELog.Create (Msg);
  163.   End;
  164.  
  165. Procedure TLog.Notification (AComponent : TComponent; Operation : TOperation);
  166.   Begin
  167.     inherited Notification (AComponent, Operation);
  168.     if Operation = opRemove then
  169.       if AComponent = FLogTo then
  170.         FLogTo := nil;
  171.   End;
  172.  
  173. Procedure TLog.SetLogFileName (const LogFileName : String);
  174.   Begin
  175.     if LogFileName = FLogFileName then
  176.       exit;
  177.     FreeAndNil (FLogFile);
  178.     FLogFileName := LogFileName;
  179.   End;
  180.  
  181. Procedure TLog.SetLogOptions (const LogOptions : TLogOptions);
  182.   Begin
  183.     if LogOptions = FLogOptions then
  184.       exit;
  185.     FLogOptions := LogOptions;
  186.     if not (loLogToFile in LogOptions) or not (loKeepFileOpen in LogOptions) then
  187.       FreeAndNil (FLogFile);
  188.   End;
  189.  
  190. Procedure TLog.SetLogTo (const LogTo : TLog);
  191. var L : TLog;
  192.   Begin
  193.     if LogTo = FLogTo then
  194.       exit;                    
  195.     if LogTo = nil then
  196.       begin
  197.         FLogTo := nil;
  198.         exit;
  199.       end;
  200.  
  201.     L := LogTo;
  202.     Repeat
  203.       if L = self then
  204.         RaiseError ('Circular LogTo reference');
  205.       L := L.FLogTo;
  206.     Until not Assigned (L);
  207.  
  208.     FLogTo := LogTo;
  209.   End;
  210.  
  211. Procedure TLog.TriggerLogMsg (const Sender : TObject; const LogClass : TLogClass; const LogMsg : String);
  212.   Begin
  213.   End;
  214.  
  215. Procedure TLog.Log (const Sender : TObject; const LogClass : TLogClass; const LogMsg : String);
  216. var S : String;
  217.     N : TDateTime;
  218.     I : Integer;
  219.     T : Cardinal;
  220.     R, F : Boolean;
  221.   Begin
  222.     try
  223.       if Assigned (FLogTo) then
  224.         FLogTo.Log (Sender, LogClass, LogMsg);
  225.     except
  226.       if not (loIgnoreLogFailure in FLogOptions) then
  227.         raise;
  228.     end;
  229.  
  230.     Case LogClass of
  231.       lcDebug   : if loIgnoreClassDebug in FLogOptions then exit;
  232.       lcInfo    : if loIgnoreClassInfo in FLogOptions then exit;
  233.       lcError   : if loIgnoreClassError in FLogOptions then exit;
  234.       lcWarning : if loIgnoreClassWarning in FLogOptions then exit;
  235.     end;
  236.  
  237.     try
  238.       if loCheckRepeats in FLogOptions then
  239.         begin
  240.           if LogMsg = FLastLogMsg then
  241.             begin
  242.               Inc (FLogRepeatCount);
  243.               exit;
  244.             end;
  245.           if FLogRepeatCount > 0 then
  246.             begin
  247.               I := FLogRepeatCount + 1;
  248.               FLogRepeatCount := 0;
  249.               Log (self, lcEndRepeat, IntToStr (I) + ' times');
  250.             end;
  251.           FLastLogMsg := LogMsg;
  252.         end;
  253.  
  254.       S := LogMsg;
  255.       if Assigned (FOnEditMessage) then
  256.         FOnEditMessage (Sender, LogClass, S);
  257.  
  258.       if not (loNoLogEvent in FLogOptions) and Assigned (FOnLog) then
  259.         FOnLog (Sender, LogClass, S);
  260.  
  261.       {$IFDEF OS_MSWIN}
  262.       if loLogMilliSecDiff in FLogOptions then
  263.         begin
  264.           T := GetTickCount;
  265.           S := PadLeft (IntToStr (T - FLastLog), ' ', 4, False) + ' ' + S;
  266.           FLastLog := T;
  267.         end;
  268.       {$ENDIF}
  269.  
  270.       if [loLogDate, loLogTime] * FLogOptions <> [] then
  271.         begin
  272.           N := Now;
  273.           if loLogTime in FLogOptions then
  274.             S := FormatDateTime ('hhnnss', N) + ' ' + S;
  275.           if loLogDate in FLogOptions then
  276.             S := FormatDateTime ('yymmdd', N) + ' ' + S;
  277.         end;
  278.  
  279.       TriggerLogMsg (Sender, LogClass, S);
  280.  
  281.       {$IFDEF OS_MSWIN}
  282.       if loLogToDebugLog in FLogOptions then
  283.         OutputDebugString (PChar (S));
  284.       {$ENDIF}
  285.  
  286.       if loLogToFile in FLogOptions then
  287.         begin
  288.           if FLogFileName = '' then
  289.             exit;
  290.           F := True;
  291.           if Assigned (FOnLogFile) then
  292.             FOnLogFile (Sender, LogClass, S, F);
  293.           if not F then
  294.             exit;
  295.  
  296.           R := False;
  297.           if not Assigned (FLogFile) then
  298.             try
  299.               FLogFile := TFileStream.Create (FLogFileName, fmOpenReadWrite);
  300.               R := True;
  301.             except
  302.               FLogFile := TFileStream.Create (FLogFileName, fmCreate);
  303.             end;
  304.           if R then
  305.             FLogFile.Seek (0, soFromEnd);
  306.  
  307.           try
  308.             if S <> '' then
  309.               FLogFile.Write (Pointer (S)^, Length (S));
  310.             FLogFile.Write (CRLF, Length (CRLF));
  311.           finally
  312.             if not (loKeepFileOpen in FLogOptions) then
  313.               FreeAndNil (FLogFile);
  314.           end;
  315.         end;
  316.     except
  317.       if not (loIgnoreLogFailure in FLogOptions) then
  318.         raise;
  319.     end;
  320.   End;
  321.  
  322. Procedure TLog.Log (const LogClass : TLogClass; const LogMsg : String);
  323.   Begin
  324.     Log (self, LogClass, LogMsg);
  325.   End;
  326.  
  327. Procedure TLog.Log (const LogMsg : String);
  328.   Begin
  329.     Log (lcInfo, LogMsg);
  330.   End;
  331.  
  332. Procedure TLog.LogDebug (const LogMsg : String);
  333.   Begin
  334.     Log (lcDebug, LogMsg);
  335.   End;
  336.  
  337. Procedure TLog.LogError (const LogMsg : String);
  338.   Begin
  339.     Log (lcError, LogMsg);
  340.   End;
  341.  
  342. Procedure TLog.LogWarning (const LogMsg : String);
  343.   Begin
  344.     Log (lcWarning, LogMsg);
  345.   End;
  346.  
  347. Procedure TLog.DeleteLogFile;
  348.   Begin
  349.     if FLogFileName = '' then
  350.       exit;
  351.     FreeAndNil (FLogFile);
  352.     SysUtils.DeleteFile (FLogFileName);
  353.   End;
  354.  
  355. Procedure TLog.LoadLogFileInto (const Destination : TStrings; const Size : Integer);
  356. var S : Int64;
  357.     C : Integer;
  358.     L : String;
  359.   Begin
  360.     Destination.Clear;
  361.     if Size = 0 then
  362.       exit;
  363.  
  364.     FreeAndNil (FLogFile);
  365.     try
  366.       FLogFile := TFileStream.Create (FLogFileName, fmOpenReadWrite);
  367.     except
  368.       exit;
  369.     end;
  370.  
  371.     S := FLogFile.Size;
  372.     if S = 0 then
  373.       exit;
  374.  
  375.     if Size < 0 then
  376.       C := S else
  377.       C := MinI (Size, S);
  378.     FLogFile.Position := S - C;
  379.     SetLength (L, C);
  380.     FLogFile.Read (Pointer (L)^, C);
  381.  
  382.     // Remove incomplete first line
  383.     TrimLeftInPlace (L, cs_AllChars - [#13, #10]);
  384.     TrimLeftInPlace (L, [#13, #10]);
  385.  
  386.     Destination.Text := L;
  387.   End;
  388.  
  389.  
  390.  
  391. {                                                                              }
  392. { Application Log                                                              }
  393. {                                                                              }
  394. var
  395.   FAppLog : TLog = nil;
  396.  
  397. Function AppLog : TLog;
  398.   Begin
  399.     if not Assigned (FAppLog) then
  400.       begin
  401.         FAppLog := TLog.Create (nil);
  402.         FAppLog.LogFileName := ChangeFileExt (ParamStr (0), '.log');
  403.         FAppLog.LogOptions := [
  404.             loLogToFile,
  405.             loLogDate, loLogTime
  406.             {$IFNDEF DEBUG}, loIgnoreLogFailure, loIgnoreClassDebug{$ENDIF}
  407.                               ];
  408.       end;
  409.     Result := FAppLog;
  410.   End;
  411.  
  412.   
  413.  
  414. initialization
  415. finalization
  416.   FreeAndNil (FAppLog);
  417. end.
  418.  
  419.