Лог в EPCL: exLog


Table of Contents

Лог в EPCL: exLog
Введение
Создание лога
Лог в файл
Лог в TStream
Настраиваемый лог
Вывод в лог
Список поддерживаемых типов

Введение

В процессе отладки приложения часто возникает необходимость вести лог событий...
примеры здесь: 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;