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