eventlog.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2003 by the Free Pascal development team
  4. Cross-platform event logging facility.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$h+}
  13. {$IFNDEF FPC_DOTTEDUNITS}
  14. unit eventlog;
  15. {$ENDIF FPC_DOTTEDUNITS}
  16. interface
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. uses System.SysUtils,System.Classes;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses SysUtils,Classes;
  21. {$ENDIF FPC_DOTTEDUNITS}
  22. Type
  23. TEventLog = Class;
  24. TLogType = (ltSystem,ltFile,ltStdOut,ltStdErr);
  25. TLogCodeEvent = Procedure (Sender : TObject; Var Code : DWord) of Object;
  26. TLogCategoryEvent = Procedure (Sender : TObject; Var Code : Word) of Object;
  27. TLogMessageEvent = Procedure (Sender : TObject; EventType : TEventType; Const Msg : String) of Object;
  28. TEventLog = Class(TComponent)
  29. Private
  30. fAppendContent : Boolean;
  31. FEventIDOffset : DWord;
  32. FLogHandle : Pointer;
  33. FStream : TFileStream;
  34. FActive: Boolean;
  35. FRaiseExceptionOnError: Boolean;
  36. FIdentification: String;
  37. FDefaultEventType: TEventType;
  38. FLogtype: TLogType;
  39. FFileName: String;
  40. FTimeStampFormat: String;
  41. FCustomLogType: Word;
  42. FOnGetCustomCategory : TLogCategoryEvent;
  43. FOnGetCustomEventID : TLogCodeEvent;
  44. FOnGetCustomEvent : TLogCodeEvent;
  45. FOnLogMessage: TLogMessageEvent;
  46. FPaused : Boolean;
  47. procedure SetActive(const Value: Boolean);
  48. procedure SetIdentification(const Value: String);
  49. procedure SetlogType(const Value: TLogType);
  50. procedure ActivateLog;
  51. procedure DeActivateLog;
  52. procedure ActivateFileLog;
  53. procedure SetFileName(const Value: String);
  54. procedure ActivateIOLog;
  55. procedure ActivateSystemLog;
  56. function DefaultFileName: String;
  57. function FormatLogMessage(EventType : TEventType; const Msg: String): String;
  58. procedure WriteFileLog(EventType : TEventType; const Msg: String);
  59. procedure WriteSystemLog(EventType: TEventType; const Msg: String);
  60. procedure WriteIOLog(EventType: TEventType; const Msg: String; var OutFile: TextFile);
  61. procedure DeActivateFileLog;
  62. procedure DeActivateSystemLog;
  63. procedure CheckIdentification;
  64. Procedure DoGetCustomEventID(Var Code : DWord);
  65. Procedure DoGetCustomEventCategory(Var Code : Word);
  66. Procedure DoGetCustomEvent(Var Code : DWord);
  67. Procedure DoLogMessage(EventType : TEventType; const Msg: String);
  68. Protected
  69. Procedure CheckInactive;
  70. Procedure EnsureActive;
  71. function MapTypeToEvent(EventType: TEventType): DWord;
  72. Function MapTypeToCategory(EventType : TEventType) : Word;
  73. Function MapTypeToEventID(EventType : TEventType) : DWord;
  74. Public
  75. Destructor Destroy; override;
  76. Function EventTypeToString(E : TEventType) : String;
  77. Function RegisterMessageFile(AFileName : String) : Boolean; virtual;
  78. Function UnRegisterMessageFile : Boolean; virtual;
  79. Procedure Pause;
  80. Procedure Resume;
  81. Procedure Log (EventType : TEventType; const Msg : String); {$ifndef fpc }Overload;{$endif}
  82. Procedure Log (EventType : TEventType; const Fmt : String; Args : Array of const); {$ifndef fpc }Overload;{$endif}
  83. Procedure Log (const Msg : String); {$ifndef fpc }Overload;{$endif}
  84. Procedure Log (const Fmt : String; Args : Array of const); {$ifndef fpc }Overload;{$endif}
  85. Procedure Warning (const Msg : String); {$ifndef fpc }Overload;{$endif}
  86. Procedure Warning (const Fmt : String; Args : Array of const); {$ifndef fpc }Overload;{$endif}
  87. Procedure Error (const Msg : String); {$ifndef fpc }Overload;{$endif}
  88. Procedure Error (const Fmt : String; Args : Array of const); {$ifndef fpc }Overload;{$endif}
  89. Procedure Debug (const Msg : String); {$ifndef fpc }Overload;{$endif}
  90. Procedure Debug (const Fmt : String; Args : Array of const); {$ifndef fpc }Overload;{$endif}
  91. Procedure Info (const Msg : String); {$ifndef fpc }Overload;{$endif}
  92. Procedure Info (const Fmt : String; Args : Array of const); {$ifndef fpc }Overload;{$endif}
  93. Published
  94. Property AppendContent : Boolean Read fAppendContent Write fAppendContent;
  95. Property Identification : String Read FIdentification Write SetIdentification;
  96. Property LogType : TLogType Read Flogtype Write SetlogType;
  97. Property Active : Boolean Read FActive write SetActive;
  98. Property RaiseExceptionOnError : Boolean Read FRaiseExceptionOnError Write FRaiseExceptionOnError;
  99. Property DefaultEventType : TEventType Read FDEfaultEventType Write FDefaultEventType;
  100. Property FileName : String Read FFileName Write SetFileName;
  101. Property TimeStampFormat : String Read FTimeStampFormat Write FTimeStampFormat;
  102. Property CustomLogType : Word Read FCustomLogType Write FCustomLogType;
  103. Property EventIDOffset : DWord Read FEventIDOffset Write FEventIDOffset;
  104. Property OnGetCustomCategory : TLogCategoryEvent Read FOnGetCustomCategory Write FOnGetCustomCategory;
  105. Property OnGetCustomEventID : TLogCodeEvent Read FOnGetCustomEventID Write FOnGetCustomEventID;
  106. Property OnGetCustomEvent : TLogCodeEvent Read FOnGetCustomEvent Write FOnGetCustomEvent;
  107. Property OnLogMessage : TLogMessageEvent read FOnLogMessage write FOnLogMessage;
  108. Property Paused : Boolean Read FPaused Write FPaused;
  109. End;
  110. ELogError = Class(Exception);
  111. Resourcestring
  112. SLogInfo = 'Info';
  113. SLogWarning = 'Warning';
  114. SLogError = 'Error';
  115. SLogDebug = 'Debug';
  116. SLogCustom = 'Custom (%d)';
  117. SErrLogFailedMsg = 'Failed to log entry (Error: %s)';
  118. SErrLogOpenStdOut = 'Standard Output not available for logging';
  119. SErrLogOpenStdErr = 'Standard Error not available for logging';
  120. implementation
  121. {$i eventlog.inc}
  122. (* File based dummy implementation is used for all platforms not providing
  123. specific implementation of eventlog.inc for the particular platform. *)
  124. { TEventLog }
  125. Resourcestring
  126. SErrOperationNotAllowed = 'Operation not allowed when eventlog is active.';
  127. procedure TEventLog.CheckInactive;
  128. begin
  129. If Active then
  130. Raise ELogError.Create(SErrOperationNotAllowed);
  131. end;
  132. procedure TEventLog.Debug(const Fmt: String; Args: array of const);
  133. begin
  134. Debug(Format(Fmt,Args));
  135. end;
  136. procedure TEventLog.Debug(const Msg: String);
  137. begin
  138. Log(etDebug,Msg);
  139. end;
  140. procedure TEventLog.EnsureActive;
  141. begin
  142. If Not Active then
  143. Active:=True;
  144. end;
  145. Procedure TEventLog.Pause;
  146. begin
  147. Paused:=True;
  148. end;
  149. Procedure TEventLog.Resume;
  150. begin
  151. Paused:=False;
  152. end;
  153. procedure TEventLog.Error(const Fmt: String; Args: array of const);
  154. begin
  155. Error(Format(Fmt,Args));
  156. end;
  157. procedure TEventLog.Error(const Msg: String);
  158. begin
  159. Log(etError,Msg);
  160. end;
  161. procedure TEventLog.Info(const Fmt: String; Args: array of const);
  162. begin
  163. Info(Format(Fmt,Args));
  164. end;
  165. procedure TEventLog.Info(const Msg: String);
  166. begin
  167. Log(etInfo,Msg);
  168. end;
  169. procedure TEventLog.Log(const Msg: String);
  170. begin
  171. Log(DefaultEventType,msg);
  172. end;
  173. procedure TEventLog.Log(EventType: TEventType; const Fmt: String;
  174. Args: array of const);
  175. begin
  176. Log(EventType,Format(Fmt,Args));
  177. end;
  178. procedure TEventLog.Log(EventType: TEventType; const Msg: String);
  179. begin
  180. If Paused then
  181. exit;
  182. EnsureActive;
  183. Case FlogType of
  184. ltFile : WriteFileLog(EventType,Msg);
  185. ltSystem : WriteSystemLog(EventType,Msg);
  186. ltStdOut : WriteIOLog(EventType,Msg,StdOut);
  187. ltStdErr : WriteIOLog(EventType,Msg,StdErr);
  188. end;
  189. DoLogMessage(EventType, Msg);
  190. end;
  191. function TEventLog.FormatLogMessage(EventType : TEventType; const Msg: String): String;
  192. Var
  193. TS,T : String;
  194. begin
  195. If FTimeStampFormat='' then
  196. FTimeStampFormat:='yyyy-mm-dd hh:nn:ss.zzz';
  197. TS:=FormatDateTime(FTimeStampFormat,Now);
  198. T:=EventTypeToString(EventType);
  199. Result:=Format('%s [%s %s] %s',[Identification,TS,T,Msg]);
  200. end;
  201. procedure TEventLog.WriteFileLog(EventType : TEventType; const Msg : String);
  202. Var
  203. S : String;
  204. begin
  205. S:=FormatLogMessage(EventType, Msg)+LineEnding;
  206. try
  207. FStream.WriteBuffer(S[1],Length(S));
  208. S:='';
  209. except
  210. On E : Exception do
  211. S:=E.Message;
  212. end;
  213. If (S<>'') and RaiseExceptionOnError then
  214. Raise ELogError.CreateFmt(SErrLogFailedMsg,[S]);
  215. end;
  216. procedure TEventLog.WriteIOLog(EventType: TEventType; const Msg: String; var OutFile: TextFile);
  217. begin
  218. Writeln(OutFile,FormatLogMessage(EventType,Msg));
  219. end;
  220. procedure TEventLog.Log(const Fmt: String; Args: array of const);
  221. begin
  222. Log(Format(Fmt,Args));
  223. end;
  224. procedure TEventLog.SetActive(const Value: Boolean);
  225. begin
  226. If Value<>FActive then
  227. begin
  228. If Value then
  229. ActivateLog
  230. else
  231. DeActivateLog;
  232. FActive:=Value;
  233. end;
  234. end;
  235. Procedure TEventLog.ActivateLog;
  236. begin
  237. Case FLogType of
  238. ltFile : ActivateFileLog;
  239. ltSystem : ActivateSystemLog;
  240. ltStdOut,
  241. ltStdErr : ActivateIOLog;
  242. end;
  243. end;
  244. Procedure TEventLog.DeActivateLog;
  245. begin
  246. Case FLogType of
  247. ltFile : DeActivateFileLog;
  248. ltSystem : DeActivateSystemLog;
  249. { nothing to do here }
  250. ltStdOut,ltStdErr : ;
  251. end;
  252. end;
  253. Procedure TEventLog.ActivateFileLog;
  254. var
  255. fFileFlags : Word;
  256. begin
  257. If (FFileName='') then
  258. FFileName:=DefaultFileName;
  259. // This will raise an exception if the file cannot be opened for writing !
  260. if fAppendContent and FileExists(FFileName) then
  261. fFileFlags := fmOpenWrite
  262. else
  263. fFileFlags := fmCreate;
  264. fFileFlags := fFileFlags or fmShareDenyWrite;
  265. FStream:=TFileStream.Create(FFileName,fFileFlags);
  266. if fAppendContent then
  267. FStream.Seek(0,soFromEnd);
  268. end;
  269. Procedure TEventLog.ActivateIOLog;
  270. var
  271. errmsg: String;
  272. m: LongInt;
  273. begin
  274. if FLogtype = ltStdOut then begin
  275. m := TextRec(StdOut).Mode;
  276. errmsg := SErrLogOpenStdOut;
  277. end else begin
  278. m := TextRec(StdErr).Mode;
  279. errmsg := SErrLogOpenStdErr;
  280. end;
  281. if (m <> fmOutput) and (m <> fmAppend) then
  282. raise ELogError.Create(errmsg);
  283. end;
  284. Procedure TEventLog.DeActivateFileLog;
  285. begin
  286. FStream.Free;
  287. FStream:=Nil;
  288. end;
  289. procedure TEventLog.SetIdentification(const Value: String);
  290. begin
  291. FIdentification := Value;
  292. end;
  293. procedure TEventLog.SetlogType(const Value: TLogType);
  294. begin
  295. CheckInactive;
  296. Flogtype := Value;
  297. end;
  298. procedure TEventLog.Warning(const Fmt: String; Args: array of const);
  299. begin
  300. Warning(Format(Fmt,Args));
  301. end;
  302. procedure TEventLog.Warning(const Msg: String);
  303. begin
  304. Log(etWarning,Msg);
  305. end;
  306. procedure TEventLog.SetFileName(const Value: String);
  307. begin
  308. CheckInactive;
  309. FFileName := Value;
  310. end;
  311. Procedure TEventLog.CheckIdentification;
  312. begin
  313. If (Identification='') then
  314. Identification:=ChangeFileExt(ExtractFileName(Paramstr(0)),'');
  315. end;
  316. Function TEventLog.EventTypeToString(E : TEventType) : String;
  317. begin
  318. Case E of
  319. etInfo : Result:=SLogInfo;
  320. etWarning : Result:=SLogWarning;
  321. etError : Result:=SLogError;
  322. etDebug : Result:=SLogDebug;
  323. etCustom : Result:=Format(SLogCustom,[CustomLogType]);
  324. end;
  325. end;
  326. Procedure TEventLog.DoGetCustomEventID(Var Code : DWord);
  327. begin
  328. If Assigned(FOnGetCustomEventID) then
  329. FOnGetCustomEventID(Self,Code);
  330. end;
  331. Procedure TEventLog.DoGetCustomEventCategory(Var Code : Word);
  332. begin
  333. If Assigned(FOnGetCustomCategory) then
  334. FOnGetCustomCategory(Self,Code);
  335. end;
  336. Procedure TEventLog.DoGetCustomEvent(Var Code : DWord);
  337. begin
  338. If Assigned(FOnGetCustomEvent) then
  339. FOnGetCustomEvent(Self,Code);
  340. end;
  341. Procedure TEventLog.DoLogMessage(EventType : TEventType; const Msg: String);
  342. begin
  343. If Assigned(FOnLogMessage) then
  344. FOnLogMessage(Self,EventType,Msg);
  345. end;
  346. destructor TEventLog.Destroy;
  347. begin
  348. Active:=False;
  349. inherited;
  350. end;
  351. end.