-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathLogger.pas
More file actions
137 lines (111 loc) · 3.63 KB
/
Logger.pas
File metadata and controls
137 lines (111 loc) · 3.63 KB
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
{
Logger - Simple HTTP Server Component
Author: Gecko71
Copyright: 2025
LICENSE:
========
This code is provided for non-commercial use only. The code is provided "as is"
without warranty of any kind, either expressed or implied, including but not
limited to the implied warranties of merchantability and fitness for a particular
purpose.
You are free to:
- Use this code for personal, educational, or non-commercial purposes
- Modify, adapt, or build upon this code as needed
- Share the code with others under the same license terms
You may not:
- Use this code for commercial purposes without explicit permission
- Remove this license notice from any copies or derivatives
THE AUTHOR(S) SHALL NOT BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE
OF THIS SOFTWARE.
By using this code, you acknowledge that you have read and understood
this license and agree to its terms.
}
unit Logger;
interface
uses
System.SysUtils, System.Classes, System.SyncObjs, System.IOUtils;
type
TNewLogLineEvent = procedure(Sender: TObject; const LogLine: string) of object;
TNewLogLineProc = reference to procedure(Sender: TObject; const LogLine: string);
THttpLogger = class
private
FCriticalSection: TCriticalSection;
FLogDir: string;
FOnNewLogLine: TNewLogLineEvent;
FOnNewLogLineProc: TNewLogLineProc;
function GetLogFileName: string;
procedure EnsureLogDirExists;
procedure DoNewLogLine(const Line: string);
public
constructor Create(const LogDir: string = 'Log');
destructor Destroy; override;
procedure Log(const Msg: string);
property OnNewLogLine: TNewLogLineEvent read FOnNewLogLine write FOnNewLogLine;
property OnNewLogLineProc: TNewLogLineProc read FOnNewLogLineProc write FOnNewLogLineProc;
end;
implementation
{ THttpLogger }
constructor THttpLogger.Create(const LogDir: string);
begin
inherited Create;
FCriticalSection := TCriticalSection.Create;
FLogDir := IncludeTrailingPathDelimiter(TPath.Combine(ExtractFilePath(ParamStr(0)), LogDir));
EnsureLogDirExists;
end;
destructor THttpLogger.Destroy;
begin
FCriticalSection.Free;
inherited;
end;
procedure THttpLogger.EnsureLogDirExists;
begin
if not DirectoryExists(FLogDir) then
ForceDirectories(FLogDir);
end;
function THttpLogger.GetLogFileName: string;
begin
Result := FLogDir + FormatDateTime('yyyy_mm_dd', Now) + '.log';
end;
procedure THttpLogger.DoNewLogLine(const Line: string);
var
mLine:string;
begin
mLine := Line;
while (Length(mLine) > 0) and
((mLine[Length(mLine)] = #10) or (mLine[Length(mLine)] = #13)) do
begin
SetLength(mLine, Length(mLine) - 1);
end;
if Assigned(FOnNewLogLine) then
FOnNewLogLine(Self, mLine);
if Assigned(FOnNewLogLineProc) then
FOnNewLogLineProc(Self, mLine);
end;
procedure THttpLogger.Log(const Msg: string);
var
Line: string;
LogStream: TFileStream;
LogBytes: TBytes;
LogFileName: string;
begin
Line := FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Now) + ' - ' + Msg + sLineBreak;
LogBytes := TEncoding.UTF8.GetBytes(Line);
LogFileName := GetLogFileName;
FCriticalSection.Acquire;
try
if TFile.Exists(LogFileName) then
LogStream := TFileStream.Create(LogFileName, fmOpenReadWrite or fmShareDenyWrite)
else
LogStream := TFileStream.Create(LogFileName, fmCreate);
try
LogStream.Seek(0, soEnd);
LogStream.WriteBuffer(LogBytes, Length(LogBytes));
finally
LogStream.Free;
end;
finally
FCriticalSection.Release;
end;
DoNewLogLine(Line);
end;
end.