-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogger.pas
159 lines (126 loc) · 3.1 KB
/
logger.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
unit Logger;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LCLType, Dialogs;
type
TRecorder = procedure(AMessage : String) of object;
TRecorderList = class
private
FItems : array of TRecorder;
function GetCount : integer;
public
constructor Create;
procedure Add(ARecorder : TRecorder);
function Get(AIndex : Integer) : TRecorder;
property Count : integer read GetCount;
end;
TLogger = class(TThread)
private
FRunning : boolean;
FRecorders : TRecorderList;
FLogQueue : TStringList;
FCriticalSection : TRTLCriticalSection ;
FSnifferTerminateEvent : PRTLEvent;
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
procedure AddRecorder(ARecorder : TRecorder);
procedure Log(AMessage : String; ALevel : integer = 0);
property Running : boolean read FRunning;
property SnifferTerminateEvent : PRTLEvent read FSnifferTerminateEvent;
end;
const
LOG_DEBUG = 0;
LOG_VERBOSE = 1;
LOG_INFO = 2;
LOG_ERROR = 3;
LOG_WARN = 4;
LOG_FATAL = 5;
implementation
constructor TRecorderList.Create;
begin
SetLength(FItems, 0);
end;
function TRecorderList.GetCount : integer;
begin
GetCount := Length(FItems);
end;
procedure TRecorderList.Add(ARecorder : TRecorder);
begin
SetLength(FItems, Length(FItems) + 1);
FItems[Length(FItems) - 1] := ARecorder;
end;
function TRecorderList.Get(AIndex : integer) : TRecorder;
begin
Get := FItems[AIndex];
end;
constructor TLogger.Create;
begin
FRunning := false;
FSnifferTerminateEvent := RTLEventCreate;
FreeOnTerminate := true;
FLogQueue := TStringList.Create;
FRecorders := TRecorderList.Create;
InitCriticalSection(FCriticalSection);
inherited Create(false);
end;
destructor TLogger.Destroy;
begin
while FRunning do
Sleep(10);
FLogQueue.Free;
FRecorders.Free;
DoneCriticalSection(FCriticalSection);
end;
procedure TLogger.Execute;
var
I, Q : integer;
Recorder : TRecorder;
Message : String;
begin
FRunning := true;
while (not Terminated) or (FLogQueue.Count > 0) do
begin
if (FRecorders.Count = 0) or (FLogQueue.Count = 0) then
begin
Sleep(200);
continue;
end;
EnterCriticalsection(FCriticalSection);
try
for Message in FLogQueue do
begin
for I := 0 to FRecorders.Count - 1 do
begin
if (Terminated) then
break;
Recorder := FRecorders.Get(I);
if not (Recorder = nil) then
Recorder(Message);
end;
end;
FLogQueue.Clear;
finally
LeaveCriticalSection(FCriticalSection);
end;
end;
RTLeventWaitFor(FSnifferTerminateEvent);
FRunning := false;
end;
procedure TLogger.AddRecorder(ARecorder : TRecorder); // TODO: Should include levels that are logged
begin
FRecorders.Add(ARecorder);
end;
procedure TLogger.Log(AMessage : String; ALevel : integer = 0);
begin
EnterCriticalsection(FCriticalSection);
try
FLogQueue.Add(AMessage); // TODO: Fix to include log level
finally
LeaveCriticalsection(FCriticalSection);
end;
end;
end.