Лог в EPCL: exLog
Введение
В процессе отладки приложения часто возникает необходимость вести лог событий...
примеры здесь:
EPCL\samples\log_sample
Создание лога
Лог в файл
var
log: TStreamLog; //TStreamLog - это тот лог, который записывает в TStream
begin
log:=TStreamLog.CreateLocal;
log:=TStreamLog.CreateLocal(Owner);
Создание CreateLocal создаст лог в папке, полученной с помощью
GetAppConfigDir с аргументом Global = false
Рекомендуется именно этот способ создания, т.к. он простой и создаст лог не в папке с исполняемом файлом, а в папаке настроек пользователя, на которую у него точно есть права на запись. Под линухом данная папка лежит где-то в
home,
под виндой - где-то в
Documents and Settings. В итоге, имя файла для лога будет иметь вид:
configdir/ApplicationTitle/log.text
Имя файла можно получить из свойства TStreamLog.FileName:
log + 'File is "' + log.FileName + '"' + endl;
Имя файла можно задать конкретно:
log:=TStreamLog.Create('FileName.text');
log:=TStreamLog.Create(Owner, 'FileName.text');
Т.к. TLog является наследником TComponent, удобно создать его с собственником, например, Forms.Application, чтобы, когда собственник будет разрушаться, остановился и лог.
Лог в TStream
log:=TStreamLog.Create(Owner, Stream); //в Stream будет производиться
// запись текста
log:=TStreamLog.Create(Owner, Stream, true); //log.Free повлечёт Stream.Free
Можно указывать как экземпляр TFileStream, так и TMemoryStream. И вообще любой экземпляр наследника TStream.
Настраиваемый лог
Для того, чтобы создать собственный лог, нужно перекрыть метод
protected function TextIt(const aText: string): boolean; virtual;
В нём нужно указать те действия, которые нужно производить при поступлении текста в лог.
TCustomLog можно использовать и в чистом виде. Он не хранит и не записывает поступающий в него текст, но ему можно вешать обработчики события поступления текста.
var
log: TCustomLog;
begin
log:=TCustomLog.Create(Onwer);
log.OnTexts.Add(@myobj.OnTextProc); //добавить обработчик
log.OnTexts.Add([@myobj.OnTextProc1, myobj.OnTextProc2]); //добавить обработчики
log.OnTexts.Delete(@myobj.OnTextProc); //снять тоже можно
//Создание с указанием обработчиков
log:=TCustomLog.Create(Owner, [@x1.OnText1, @x2.OnText2, ..., @xN.OnTextN]);
При этом onText - метод объекта вида
function logIt(const s: string): boolean;
Пример:
TSilly = class(TComponent, IStringConvable)
function CoutIt(const s: string): boolean;
end;
function TSilly.CoutIt(const s: string): boolean;
begin
Write(s);
result:=true; // не обязательно
end;
Обработчики можно вешать и на TStreamLog в той же степени. Так, иногда, полезно, чтобы лог выводился не только в файл, но и на экран.
Вывод в лог
Примеры:
{ Log started at 16:04:16, 02.06.2010 }
log + 'Log started at ' + logTime + ', ' + logDate + endl;
//logTime и logDate - модификаторы, позволяющие записать время и дату
log + 'File is "' + log.FileName + '"' + endl;
x:=6;
r:=22.1;
{ Global variable x is 6 }
log<<'Global variable x is '<< x <<endl;
log<<'Gobal variable m is '<< m <<endl;
log<<'test: ' + 1.6 + '; ' + r + '; ' + m + endl;
Вывод текста в лог с указанием активного объекта:
procedure TSilly.DoSmth(aParam: integer);
begin
log - self + 'Doing something (' + aParam + ')' + endl;
end;
var
m: TSilly;
begin
m:=TSilly.Create(nil);
m.DoSmth(1); // выведет TSilly: Doing something (1)
m.Name:='mySilly';
m.DoSmth(2); // выведет TSilly mySilly: Doing something (2)
// Таким образом,
log - self; {в общем, } log - someObject;
//выводит TClassName: объекта или же добавляет Name объекта, если он TComponent
Список поддерживаемых типов
На текущий момент
string
integer
int64
real
double
extended
boolean // "True", "False"
TLogModifier = (logDate, logTime, endl)
TObject // и наследники
TComponent // и наследники
При этом, если экземпляр объекта наследует интерфейс IStringConvable, то он преобразуется в текст с помощью его метода getAsString (см.
EPCL.exStrigns - Туториал по строковым утилитам )
Все переменные можно выводить как плюсом, так и <<'ом
log<<x<<y; { равносильно } log + x + y;