brooklog.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. (*
  2. Brook for Free Pascal
  3. Copyright (C) 2014-2019 Silvio Clecio
  4. See the file LICENSE.txt, included in this distribution,
  5. for details about the copyright.
  6. This library is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. *)
  10. { Logger classes. }
  11. unit BrookLog;
  12. {$i brook.inc}
  13. interface
  14. uses
  15. BrookClasses, BrookException, BrookMessages, SysUtils, Classes;
  16. type
  17. { Handles exceptions for @link(TBrookLogger). }
  18. EBrookLogger = class(EBrook);
  19. { Is a metaclass for @link(TBrookLogger) class. }
  20. TBrookLoggerClass = class of TBrookLogger;
  21. { Defines an enumerator to represent the logger output kind. }
  22. TBrookLogOutput = (loFile, loSystem);
  23. { Defines an enumerator to represent the logger event types. }
  24. TBrookLogType = (ltCustom, ltInfo, ltWarning, ltError, ltDebug);
  25. { Defines a set to represent the logger event types. }
  26. TBrookLogTypes = set of TBrookLogType;
  27. { Is a type to the log event. }
  28. TBrookLogEvent = procedure(ASender: TObject; const AType: TBrookLogType;
  29. const S: string; const ACode: Word; const E: Exception;
  30. var AHandled: Boolean) of object;
  31. { Defines a pointer to the log event.}
  32. PBrookLogEvent = ^TBrookLogEvent;
  33. { Provides features for the application logging. }
  34. TBrookLogger = class(TBrookComponent)
  35. private
  36. FActive: Boolean;
  37. FAfterLog: TBrookLogEvent;
  38. FBeforeLog: TBrookLogEvent;
  39. FFileName: TFileName;
  40. FOutput: TBrookLogOutput;
  41. FPrepared: Boolean;
  42. FTypes: TBrookLogTypes;
  43. protected
  44. function GetActive: Boolean; virtual;
  45. procedure SetActive(const AValue: Boolean); virtual;
  46. function GetFileName: TFileName; virtual;
  47. procedure SetFileName(const AValue: TFileName); virtual;
  48. procedure SetOutput(const AValue: TBrookLogOutput); virtual;
  49. function GetOutput: TBrookLogOutput; virtual;
  50. public
  51. constructor Create(AOwner: TComponent); override;
  52. { Return the service class provided by this class. }
  53. class function GetServiceClass: TBrookLoggerClass;
  54. { Registers the service provided by this class. }
  55. class procedure RegisterService;
  56. { Unregisters the service provided by this class. }
  57. class procedure UnregisterService;
  58. { Return an instance of this class. }
  59. class function Service: TBrookLogger;
  60. { Prepare the logger broker. }
  61. procedure Prepare; virtual;
  62. { Unprepare the logger broker. }
  63. procedure Unprepare; virtual;
  64. { Writes a log. }
  65. procedure Log(const AType: TBrookLogType; const S: string;
  66. const ACode: Word; const E: Exception = nil); virtual; abstract;
  67. { Writes a log triggering the @code(AfterLog) and @(BeforeLog) events. }
  68. procedure DoLog(const AType: TBrookLogType; const S: string;
  69. const ACode: Word; const E: Exception = nil); virtual;
  70. { Writes a custom log. }
  71. procedure Custom(const S: string; const ACode: Word); virtual;
  72. { Writes an information log. }
  73. procedure Info(const S: string); virtual;
  74. { Writes a warning log. }
  75. procedure Warn(const S: string); virtual;
  76. { Writes a debug log. }
  77. procedure Debug(const S: string); virtual;
  78. { Writes an error log. }
  79. procedure Error(const S: string; E: Exception = nil); virtual;
  80. { Enables or disables the logger. }
  81. property Active: Boolean read GetActive write SetActive;
  82. { Defines the name of the log file. }
  83. property FileName: TFileName read GetFileName write SetFileName;
  84. { The logger output types. }
  85. property Types: TBrookLogTypes read FTypes write FTypes;
  86. { The logger output mode. }
  87. property Output: TBrookLogOutput read GetOutput write SetOutput;
  88. { Return @code(True) if broker is prepared. }
  89. property Prepared: Boolean read FPrepared;
  90. { Is triggered after the logger writes a log. }
  91. property AfterLog: TBrookLogEvent read FAfterLog write FAfterLog;
  92. { Is triggered before the logger writes a log. }
  93. property BeforeLog: TBrookLogEvent read FBeforeLog write FBeforeLog;
  94. end;
  95. implementation
  96. var
  97. _BrookLoggerService: TBrookLogger = nil;
  98. _BrookLoggerServiceClass: TBrookLoggerClass = nil;
  99. { TBrookLogger }
  100. constructor TBrookLogger.Create(AOwner: TComponent);
  101. begin
  102. inherited Create(AOwner);
  103. FTypes := [ltCustom, ltInfo, ltWarning, ltError, ltDebug];
  104. end;
  105. class function TBrookLogger.GetServiceClass: TBrookLoggerClass;
  106. begin
  107. Result := _BrookLoggerServiceClass;
  108. end;
  109. class procedure TBrookLogger.RegisterService;
  110. begin
  111. if Assigned(_BrookLoggerServiceClass) then
  112. raise EBrookLogger.Create(Self, SBrookLoggerServiceAlreadyRegisteredError);
  113. _BrookLoggerServiceClass := Self;
  114. end;
  115. class procedure TBrookLogger.UnregisterService;
  116. begin
  117. FreeAndNil(_BrookLoggerService);
  118. _BrookLoggerServiceClass := nil;
  119. end;
  120. class function TBrookLogger.Service: TBrookLogger;
  121. begin
  122. if not Assigned(_BrookLoggerService) then
  123. begin
  124. if not Assigned(_BrookLoggerServiceClass) then
  125. raise EBrookLogger.Create(Self, SBrookNoLoggerServiceRegisteredError);
  126. _BrookLoggerService := _BrookLoggerServiceClass.Create(nil);
  127. end;
  128. Result := _BrookLoggerService;
  129. end;
  130. procedure TBrookLogger.Prepare;
  131. begin
  132. FPrepared := True;
  133. end;
  134. procedure TBrookLogger.Unprepare;
  135. begin
  136. FPrepared := False;
  137. end;
  138. procedure TBrookLogger.DoLog(const AType: TBrookLogType; const S: string;
  139. const ACode: Word; const E: Exception);
  140. var
  141. VHandled: Boolean = False;
  142. begin
  143. try
  144. if Assigned(FBeforeLog) then
  145. FBeforeLog(Self, AType, S, ACode, E, VHandled);
  146. if VHandled then
  147. Exit;
  148. if not FPrepared then
  149. Prepare;
  150. Log(AType, S, ACode, E);
  151. finally
  152. if Assigned(FAfterLog) then
  153. FAfterLog(Self, AType, S, ACode, E, VHandled);
  154. end;
  155. end;
  156. procedure TBrookLogger.Custom(const S: string; const ACode: Word);
  157. begin
  158. DoLog(ltCustom, S, ACode, nil);
  159. end;
  160. procedure TBrookLogger.Info(const S: string);
  161. begin
  162. DoLog(ltInfo, S, 0, nil);
  163. end;
  164. procedure TBrookLogger.Warn(const S: string);
  165. begin
  166. DoLog(ltWarning, S, 0, nil);
  167. end;
  168. procedure TBrookLogger.Debug(const S: string);
  169. begin
  170. DoLog(ltDebug, S, 0, nil);
  171. end;
  172. procedure TBrookLogger.Error(const S: string; E: Exception);
  173. begin
  174. DoLog(ltError, S, 0, E);
  175. end;
  176. function TBrookLogger.GetActive: Boolean;
  177. begin
  178. Result := FActive;
  179. end;
  180. procedure TBrookLogger.SetActive(const AValue: Boolean);
  181. begin
  182. if AValue <> FActive then
  183. begin
  184. FActive := AValue;
  185. Unprepare;
  186. end;
  187. end;
  188. function TBrookLogger.GetFileName: TFileName;
  189. begin
  190. Result := FFileName;
  191. end;
  192. procedure TBrookLogger.SetFileName(const AValue: TFileName);
  193. begin
  194. if AValue <> FFileName then
  195. begin
  196. FFileName := AValue;
  197. Unprepare;
  198. end;
  199. end;
  200. procedure TBrookLogger.SetOutput(const AValue: TBrookLogOutput);
  201. begin
  202. if AValue <> FOutput then
  203. begin
  204. FOutput := AValue;
  205. Unprepare;
  206. end;
  207. end;
  208. function TBrookLogger.GetOutput: TBrookLogOutput;
  209. begin
  210. Result := FOutput;
  211. end;
  212. end.