forked from jrsoftware/issrc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLogging.pas
186 lines (166 loc) · 4.66 KB
/
Logging.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
unit Logging;
{
Inno Setup
Copyright (C) 1997-2007 Jordan Russell
Portions by Martijn Laan
For conditions of distribution and use, see LICENSE.TXT.
Logging functions
$jrsoftware: issrc/Projects/Logging.pas,v 1.12 2009/03/23 23:27:14 mlaan Exp $
}
interface
procedure Log(const S: String);
procedure LogFmt(const S: String; const Args: array of const);
procedure StartLogging(const Prefix: String);
procedure StartLoggingWithFixedFilename(const Filename: String);
function GetLogFileName: String;
const
SYesNo: array[Boolean] of String = ('No', 'Yes');
implementation
uses
Windows, SysUtils, Int64Em, CmnFunc2, FileClass, DebugClient;
var
LogFile: TTextFileWriter;
LogFileName: String;
LocalTimeBias: Integer64;
procedure InitLocalTimeBias;
var
UTCTime, LocalTime: Integer64;
begin
GetSystemTimeAsFileTime(TFileTime(UTCTime));
if FileTimeToLocalFileTime(TFileTime(UTCTime), TFileTime(LocalTime)) then begin
Dec6464(LocalTime, UTCTime);
LocalTimeBias := LocalTime;
end;
end;
procedure GetFixedLocalTime(var ST: TSystemTime);
{ Like GetLocalTime, but uses our LocalTimeBias as the offset, which cannot
change while the program is running }
var
FT: Integer64;
begin
GetSystemTimeAsFileTime(TFileTime(FT));
Inc6464(FT, LocalTimeBias);
FileTimeToSystemTime(TFileTime(FT), ST);
end;
procedure LogLogOpened;
var
Offset: Integer64;
PlusOrMinus: Char;
begin
Offset := LocalTimeBias;
if Longint(Offset.Hi) >= 0 then
PlusOrMinus := '+'
else begin
PlusOrMinus := '-';
{ Negate it }
Offset.Lo := not Offset.Lo;
Offset.Hi := not Offset.Hi;
Inc64(Offset, 1);
end;
Div64(Offset, 60 * 10000000);
LogFmt('Log opened. (Time zone: UTC%s%.2u:%.2u)', [PlusOrMinus,
Offset.Lo div 60, Offset.Lo mod 60]);
end;
procedure StartLogging(const Prefix: String);
var
Dir, DateStr, Filename: String;
I: Cardinal;
ST: TSystemTime;
F: TTextFileWriter;
begin
if Assigned(LogFile) then
Exit; { logging was already started }
Dir := GetTempDir;
GetFixedLocalTime(ST);
DateStr := Format('%.4u-%.2u-%.2u', [ST.wYear, ST.wMonth, ST.wDay]);
I := 1;
while True do begin
Filename := Dir + Format('%s Log %s #%.3u.txt', [Prefix, DateStr, I]);
if not FileOrDirExists(Filename) then begin
F := nil;
try
F := TTextFileWriter.Create(Filename, fdCreateNew, faWrite, fsRead);
except
on E: EFileError do begin
{ Don't propogate ERROR_FILE_EXISTS errors; just try again.
(Yes, we already checked if the file existed first, but this helps
to make it race-proof.) }
if E.ErrorCode <> ERROR_FILE_EXISTS then
raise;
end;
end;
if Assigned(F) then begin
LogFile := F;
LogFileName := FileName;
Break;
end;
end;
Inc(I);
end;
LogLogOpened;
end;
procedure StartLoggingWithFixedFilename(const Filename: String);
begin
if Assigned(LogFile) then
Exit; { logging was already started }
LogFile := TTextFileWriter.Create(Filename, fdCreateAlways, faWrite, fsRead);
LogFileName := FileName;
LogLogOpened;
end;
function GetLogFileName: String;
begin
Result := LogFileName;
end;
procedure Log(const S: String);
procedure WriteStr(const S: String);
begin
LogFile.Write(S);
end;
var
ST: TSystemTime;
LineStart, I: Integer;
begin
if Assigned(LogFile) then begin
GetFixedLocalTime(ST);
try
WriteStr(Format('%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u ',
[ST.wYear, ST.wMonth, ST.wDay, ST.wHour, ST.wMinute, ST.wSecond,
ST.wMilliseconds]));
LineStart := 1;
{ Lines except for last line }
for I := 1 to Length(S) do begin
if S[I] = #10 then begin
WriteStr(Copy(S, LineStart, I - LineStart + 1));
LineStart := I + 1;
{ Indent }
WriteStr(' ');
end;
end;
{ Last line }
if LineStart <= Length(S) then
WriteStr(Copy(S, LineStart, Length(S) - LineStart + 1));
WriteStr(#13#10);
except
{ Failed to write? Close the file and don't log anything further. }
try
FreeAndNil(LogFile);
except
end;
end;
end;
if Debugging then
DebugNotifyLogMessage(S);
end;
procedure LogFmt(const S: String; const Args: array of const);
begin
if Assigned(LogFile) or Debugging then
Log(Format(S, Args));
end;
initialization
InitLocalTimeBias;
finalization
if Assigned(LogFile) then begin
Log('Log closed.');
FreeAndNil(LogFile);
end;
end.