Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.07.27;
Скачать: [xml.tar.bz2];

Вниз

Работа с логами   Найти похожие ветки 

 
123-ий ©   (2008-06-25 11:36) [0]

Как лучше организовать сабж? В том смысле, какими методами его лучше читать и писАть в него каку-либо инфу?


 
Palladin ©   (2008-06-25 11:38) [1]

какими тебе удобно


 
Ega23 ©   (2008-06-25 11:39) [2]

Ну вот некая заготовочка, в данный момент в процессе "затачивания"


unit uLogger;

interface
uses SysUtils;

function LogError(const Err : string) : Boolean;
function Log(const LogMess : string) : Boolean;
function LogTo(const Name : string; const LogMess : string) : Boolean;
function LogWithError(const Err : string) : Boolean;
function LogToFile(const FileName, LogMess : string;
                  const WriteTime : Boolean = False) : Boolean;

implementation

//*****************************************************************************

function LogWithError(const Err : string) : Boolean;
begin
 Result := LogError(Err) and Log(Err);
end;

//*****************************************************************************

function LogError(const Err : string) : Boolean;
begin
 Result := LogTo("SLErrLog", Err);
end;

//*****************************************************************************

function Log(const LogMess : string) : Boolean;
begin
 Result := LogTo("SLLog", LogMess);
end;

//*****************************************************************************

function LogTo(const Name : string; const LogMess : string) : Boolean;
var
 DirName, LogFileName : string;
 f : TextFile;
begin
 Result := True;
 DirName := ExtractFilePath(ParamStr(0)) + "Log\";
 LogFileName := DirName + Name + "_" + FormatdateTime("yyyy-mm-dd", Now) + ".log";
 if not DirectoryExists(DirName) then
 begin
   Result := CreateDir(DirName);
   if not Result then Exit;
 end;
 AssignFile(f, LogFileName);
 try
   try
     if not FileExists(LogFileName) then
       Rewrite(f)
     else
       Append(f);
     Writeln(f, FormatDateTime("dd.mm.yyyy hh:nn:ss", Now) + " : " + LogMess);
   except
     Result := False;
   end;
 finally
   CloseFile(f);
 end;
end;

//*****************************************************************************

function LogToFile(const FileName, LogMess : string; const WriteTime : Boolean) : Boolean;
var
 f : TextFile;
begin
 AssignFile(f, FileName);
 try
   try
     if not FileExists(FileName) then
       Rewrite(f)
     else
       Append(f);
     if WriteTime then
       Writeln(f, FormatDateTime("dd.mm.yyyy hh:nn:ss", Now) + " : " + LogMess)
     else
       Writeln(f, LogMess);
     Result := True;
   except
     begin
       Result := False;
       Exit;
     end;
   end;
 finally
   CloseFile(f);
 end;
end;

//*****************************************************************************
end.



 
clickmaker ©   (2008-06-25 11:39) [3]

CreateFile - WriteFile - CloseHandle
для ускорения можно открыть один раз и закрыть один раз, но если нужен постоянный монитор лога, то периодически делать FlushFileBuffers.
При записи из нескольких потоков оберни запись в критическую секцию


 
123-ий ©   (2008-06-25 11:47) [4]


> Ega23 ©   (25.06.08 11:39) [2]

Вот этот вариант - с помощью TextFile. Делал с помощью него, частенько вылезают глюки, типа файл занят другим приложением. Как вариант было - читать файл с помощью потоков TFileStream. Ещё не пробовал. А был вариант с помощью StringList.LoadFromFile. Работал. Так вот интересно, какой вариант наиболее оптимальный?


 
123-ий ©   (2008-06-25 11:49) [5]


> clickmaker ©   (25.06.08 11:39) [3]

постоянный монитор не нужен. ускорение тоже, ибо лог... ну у меня не совсем лог, скорее история работы с клиентом, там вряд ли будет дофига инфы.


 
stas ©   (2008-06-25 11:58) [6]

У меня такой работает на многопоточном сервере, еще не разу не глючил.
Только при запуске проги делаем CreateLogFile, по завершении CloseFile
лог пишем WriteLog

unit LogWriter;

interface
uses sysutils;
Procedure OpenFile (FileName:String);
Procedure CloseFile;
Procedure WriteText (Text:String);
Procedure CreateLogFile;
Procedure WriteLog (Text:String);
//Procedure SetWritedLog (Writed:Boolean);

Var F:TextFile; WritedLog:Boolean=True;

implementation

Procedure OpenFile (FileName:String);
begin
//  if not writedLog then exit;
 Assign (F,FileName);
 if FileExists (FileNAme) then
 Reset (F); {else} Rewrite (f);
end;

Procedure CloseFile;
begin
 Close (F);
end;

Procedure WriteText (Text:String);
begin
 if writedLog then
 Writeln (F,Text);
end;

Procedure CreateLogFile;
Var fp,FName,fn:String; I:Integer;
begin
  fp:=ExtractFilePath(ParamStr(0))+"logs\";
  if not DirectoryExists (fp) then MkDir (fp);
  FName:=fp+"gsLog_"+FormatDateTime ("ddmmyyyy",now);
  i:=0;
  fn:= FName;
  While FileExists (FName) do
  begin
   FName:=FN+IntToStr(i);
   inc(i);
  end;
  OpenFile (FName);
end;

Procedure WriteLog (Text:String);
Var S:String;
begin
S:=FormatDateTime ("ddmmyyyy hh:mm:ss",now)+": "+Text;
try
WriteText(S);
except
end;
end;

end.


 
123-ий ©   (2008-06-25 11:59) [7]

ну вот попробую варианты Ega32 и stas. Может чего и выйдет умного...


 
Ega23 ©   (2008-06-25 12:00) [8]


> работает на многопоточном сервере,


А где критическая секция?


 
Ega23 ©   (2008-06-25 12:01) [9]


> варианты Ega32


Эй! Ты смотри, это всего только заготовка...  :) Её ещё тщательно "напильником" обрабатывать надо...  :)


 
stas ©   (2008-06-25 12:03) [10]

Ega23 ©   (25.06.08 12:00) [8]
try except ?


 
Ega23 ©   (2008-06-25 12:05) [11]


> try except ?


На сколько я понимаю, для реально многопоточного лога этого недостаточно...


 
stas ©   (2008-06-25 12:07) [12]

Ega23 ©   (25.06.08 12:05) [11]
тогда что вы имеете ввиду?


 
Ega23 ©   (2008-06-25 12:12) [13]

EnterCriticalSection
try
 try
   ....
   WriteLog
 except
   ....
 end;
finally
 LeaveCriticalSection
end;


 
stas ©   (2008-06-25 12:19) [14]

Ega23 ©   (25.06.08 12:12) [13]

Не слышал. А это для чего.

Пока у меня не возникало никаких проблем слогом сервер работает в течении года.
Но если это чему-то поможет буду благодарен.


 
Ega23 ©   (2008-06-25 12:24) [15]


> А это для чего.


Ну как же. 2 потока разом пытаются в файл что-то записать...


 
123-ий ©   (2008-06-25 12:35) [16]


> Ega23 ©   (25.06.08 12:01) [9]

Ну вот. У тебя получилась хорошая защита от копипастинга. Конечно я постараюсь разобраться в смысле кода, а потом уже и напильником и шкуркой. По любому рахмет, ой это ж по казахски... спасибо :)


 
Ega23 ©   (2008-06-25 12:38) [17]


> У тебя получилась хорошая защита от копипастинга.


Не, можно конечно брать и пользоваться, но я это дело "под себя" точил. Тебе может всего и не нужно совсем.


 
123-ий ©   (2008-06-25 12:54) [18]

Панятно. будем разбираться :)


 
Loginov Dmitry ©   (2008-06-25 12:59) [19]


> Как лучше организовать сабж? В том смысле, какими методами
> его лучше читать и писАть в него каку-либо инфу?


Пример надежной записи в лог здесь:
http://matrix.kladovka.net.ru/download.php?getfilename=uploads/other/ldslogger.zip


 
stas ©   (2008-06-25 13:01) [20]

Ega23 ©   (25.06.08 12:24) [15]
пишут, ошибка не возникает. O_O.
Ок, попытаюсь разобраться.


 
stas ©   (2008-06-25 13:22) [21]

Ega23 ©   (25.06.08 12:24) [15]
возникала такая ошибка когда я вyenhb функции LogWrite, открывал потом закрывал файл, когда сделал f глобальной переменной и открываю файл один раз, эти проблемы ушли.


 
Игорь Шевченко ©   (2008-06-25 13:29) [22]


> Эй! Ты смотри, это всего только заготовка...  :) Её ещё
> тщательно "напильником" обрабатывать надо...  :)


точнее выкинуть


 
123-ий ©   (2008-06-26 07:54) [23]


> Игорь Шевченко ©   (25.06.08 13:29) [22]

а что так невесело?


 
123-ий ©   (2008-06-26 10:50) [24]


> Ega23 ©   (25.06.08 11:39) [2]
а чтение лога? у тебя ж только запись... или ты чтение вообще не делал
?


 
Ega23 ©   (2008-06-26 10:54) [25]


> или ты чтение вообще не делал


А нафига мне чтение??? Если чё, мне заказчик этот лог вышлет. А я уже там сам в блокноте разберусь...  :)))


 
Игорь Шевченко ©   (2008-06-26 21:01) [26]


> а что так невесело?


сам посмотри на код


 
Германн ©   (2008-06-26 21:34) [27]

4 года назад тут Панов выкладывал код для ведения лога на ~400 строк кода.
:-)


 
123-ий ©   (2008-06-27 08:29) [28]

фигасе. А мне чтение нужно шобы в программу содержимое выводить. Лана, буду сам додумывать. :)


 
Anatoly Podgoretsky ©   (2008-06-27 08:38) [29]


> 4 года назад тут Панов выкладывал код для ведения лога на
> ~400 строк кода.

Он схалтурил, ему лень было полный код писать.


 
@!!ex ©   (2008-06-27 09:28) [30]

Я один такой не модный, что у меня 10 строчек логирование? :\
Оно правда на С++, но ниче умного нет на дельфи переделать. Работает мгновенно, даже если сообщения валятся пачками.

static osal::cFile* s_Log;

void loger::Init(const std::string FileName)
{
s_Log = new osal::cFile(FileName,osal::WRITE);
};

void loger::Finish()
{
delete s_Log;
};

void loger::Add(const std::string Text)
{
osal::PrintInConsole(Text+"\n");
s_Log->WriteText(Text);
s_Log->Flush();
};


 
@!!ex ©   (2008-06-27 09:28) [31]

правда тут не многопоточное действо.


 
Поросенок Винни-Пух ©   (2008-06-27 09:36) [32]

unit LogUnit;

interface

procedure Log(const AMsg : string; const AParam : string = "");

implementation

uses Classes, SysUtils,SyncObjs;

var LogName:string;
   cs : TCriticalSection = nil;

procedure Log(const AMsg : string; const AParam : string = "");
var F:Text;
begin
cs.Enter;
Assign(F,LogName);
try
 if FileExists(LogName) then Append(F) else Rewrite(F);
 Writeln(F,FormatDateTime("dd.mm.yyyy hh:mm:ss",Now),#9,AMsg,#9,AParam);
finally
 Close(F);
 cs.Leave;
end;
end;

initialization
cs := TCriticalSection.Create;
LogName:=ChangeFileExt(ParamStr(0),".log");
finalization
cs.Free;
end.


 
Тын-Дын ©   (2008-06-27 11:08) [33]

А во всех этих пример и реализациях нагрузочное многопоточное тестирование проводилось?


 
Поросенок Винни-Пух ©   (2008-06-27 11:09) [34]

не только тестирование, но и многолетняя эксплуатация


 
Тын-Дын ©   (2008-06-27 11:26) [35]


> Поросенок Винни-Пух ©   (27.06.08 11:09) [34]
> не только тестирование, но и многолетняя эксплуатация


Ну и как с нагрузкой?
Сколько записей в секунду выдерживает и время реакции(время начала/конца обращения к процедуре?).


 
Поросенок Винни-Пух ©   (2008-06-27 11:30) [36]

Сколько записей в секунду выдерживает

это важно, если стоит задача быстрого наполнения лога все равно чем.
у меня такой задачи нет, лог используется по прямому назначению.


 
Тын-Дын ©   (2008-06-27 11:32) [37]


> Поросенок Винни-Пух ©   (27.06.08 11:30) [36]
> Сколько записей в секунду выдерживает
>
> это важно, если стоит задача быстрого наполнения лога все
> равно чем.


Неверно.
Есть задачи с большим потоком обработки данных, и операции нужно протоколировать, не мешая основной задаче.
Это и есть прямое назначение.


 
Поросенок Винни-Пух ©   (2008-06-27 11:33) [38]

в одном из фрагментов сегодняшнего лога нашел 21 запись в течении одной секунды. наверное было бы больше, если бы логируемая операция содержала больше шагов.


 
Поросенок Винни-Пух ©   (2008-06-27 11:34) [39]

У меня не мешает.


 
Поросенок Винни-Пух ©   (2008-06-27 11:36) [40]

Есть задачи с большим потоком обработки данных, и операции нужно протоколировать, не мешая основной задаче.
Это и есть прямое назначение.


И каким образом спрошенное у меня количество записей в секунду может что-то сказать про это?


 
Игорь Шевченко ©   (2008-06-27 11:42) [41]


> И каким образом спрошенное у меня количество записей в секунду
> может что-то сказать про это?


повод померяться...


 
Игорь Шевченко ©   (2008-06-27 11:47) [42]


> А во всех этих пример и реализациях нагрузочное многопоточное
> тестирование проводилось?


На свете существуют разные задачи.


 
Anatoly Podgoretsky ©   (2008-06-27 11:48) [43]

> Поросенок Винни-Пух  (27.06.2008 11:33:38)  [38]

for I := 1 to N do Log(IntToStr(I));


 
Тын-Дын ©   (2008-06-27 12:07) [44]


> Поросенок Винни-Пух ©   (27.06.08 11:36) [40]
> Есть задачи с большим потоком обработки данных, и операции
> нужно протоколировать, не мешая основной задаче.
> Это и есть прямое назначение.
>
> И каким образом спрошенное у меня количество записей в секунду
> может что-то сказать про это?


Отвеченное количество может помочь оценить эффективность реализации.
Странно, что такой простой вопрос в тупик ставит.


> Игорь Шевченко ©   (27.06.08 11:47) [42]
>
> > А во всех этих пример и реализациях нагрузочное многопоточное
>
> > тестирование проводилось?
>
>
> На свете существуют разные задачи


Совершенно верно.


> Поросенок Винни-Пух ©   (27.06.08 11:34) [39]
> У меня не мешает.


см. [42]

Нет, так нет.
Значит, не возникали подобные задачи.


 
Поросенок Винни-Пух ©   (2008-06-27 12:11) [45]

Отвеченное количество может помочь оценить эффективность реализации.
Странно, что такой простой вопрос в тупик ставит.


Ну давай, зацени.
Логируются не вычисления в памяти, а обращения к бд, криптографические операции и прочее, само по себе затратное по времени, все это прерывается ожиданиями сервера окончания интеракитвых фаз на клиенте.

Число записей в секунду - 21.
Оцени хоть что-нибудь.


 
Тын-Дын ©   (2008-06-27 12:27) [46]


> Поросенок Винни-Пух ©   (27.06.08 12:11) [45]
> Отвеченное количество может помочь оценить эффективность
> реализации.
> Странно, что такой простой вопрос в тупик ставит.
>
> Ну давай, зацени.
> Логируются не вычисления в памяти, а обращения к бд, криптографические
> операции и прочее, само по себе затратное по времени, все
> это прерывается ожиданиями сервера окончания интеракитвых
> фаз на клиенте.
>
> Число записей в секунду - 21.
> Оцени хоть что-нибудь.


Число обращений к функции протоколирования 21 ни о чем не говорит.
Вот если бы ты обращался 1000 раз в секунду к функции записи в журнал из нескольких потоков, тогда можно было бы оценить с замерами в каждом потоке количества обращений и замером количества строк, записанных в журнал за единицу времени.


 
Поросенок Винни-Пух ©   (2008-06-27 13:28) [47]

Удалено модератором


 
Поросенок Винни-Пух ©   (2008-06-27 13:30) [48]

Удалено модератором


 
Тын-Дын ©   (2008-06-27 13:45) [49]

Удалено модератором


 
Поросенок Винни-Пух ©   (2008-06-27 13:45) [50]

Удалено модератором


 
Тын-Дын ©   (2008-06-27 13:46) [51]

Удалено модератором


 
Поросенок Винни-Пух ©   (2008-06-27 13:46) [52]

Удалено модератором


 
Тын-Дын ©   (2008-06-27 13:48) [53]

Удалено модератором


 
Тын-Дын ©   (2008-06-27 13:49) [54]

Удалено модератором


 
Поросенок Винни-Пух ©   (2008-06-27 13:53) [55]

Ну что же еще остается, если твоей крутой реализации лога мы все равно здесь не увидим.

Спорим, что не увидим?
А если увидим, то ничего сколько нибудь отличного по производительности и надежности там не будет.

спорим?!


 
Тын-Дын ©   (2008-06-27 14:06) [56]

Удалено модератором


 
Поросенок Винни-Пух ©   (2008-06-27 14:07) [57]

Удалено модератором


 
@!!ex ©   (2008-06-27 14:13) [58]

> [35] Тын-Дын ©   (27.06.08 11:26)
>
> > Поросенок Винни-Пух ©   (27.06.08 11:09) [34]
> > не только тестирование, но и многолетняя эксплуатация
>
>
> Ну и как с нагрузкой?
> Сколько записей в секунду выдерживает и время реакции(время
> начала/конца обращения к процедуре?).

за 30 секунд 80 мегабайт лога, без видимого падения ФПС.


 
@!!ex ©   (2008-06-27 14:15) [59]

Правда в один поток.


 
Игорь Шевченко ©   (2008-06-27 14:15) [60]

Поросенок Винни-Пух ©   (27.06.08 13:53) [55]


> спорим?!


people may not see the difference


 
Поросенок Винни-Пух ©   (2008-06-27 14:22) [61]

people may not see the difference

Не, ну объясните мотивы персонажа.
Кто-то просто привет модуль без коментариев.
Рисуется перец, который ехидно страшивает, типа ну и скока там у вас?
Ему в ответ: а зачем тебе и что ты по ответу можешь сказать?
Он: - мне это поможет оценить всякую хрень.
Я - на, оценивай.
Он: мне количество обращений нифига не говорит, а ты не понтуйся.

Каково, а?


 
Игорь Шевченко ©   (2008-06-27 14:37) [62]

завязываем с оффтопиком. можно вполне предметно побеседовать в чате - для чего-то его тут сделали ?


 
Тын-Дын ©   (2008-06-28 01:40) [63]


> Поросенок Винни-Пух ©   (27.06.08 14:22) [61]
> people may not see the differenceНе, ну объясните мотивы
> персонажа.Кто-то просто привет модуль без коментариев.Рисуется
> перец, который ехидно страшивает, типа ну и скока там у
> вас?Ему в ответ: а зачем тебе и что ты по ответу можешь
> сказать?Он: - мне это поможет оценить всякую хрень.Я - на,
>  оценивай.Он: мне количество обращений нифига не говорит,
>  а ты не понтуйся.Каково, а?


Для крутых перцев:
Вот реализация ведения протокола: http://89.223.39.99/files/threadlog.zip

Тестовый пример:

uses
 uThreadLog;

type
TThrPing=class(TThread)
private
 FHost: String;
 FLog: TThreadLog;
protected
 procedure Execute; override;
public
 constructor Create(Host: String; Log: TThreadLog);
end;

implementation

{ TThrPing }

constructor TThrPing.Create(Host: String; Log: TThreadLog);
begin
 inherited Create(True);
 FreeOnTerminate := True;
 FHost := Host;
 FLog := Log;
 Resume;
end;

procedure TThrPing.Execute;
var
 s: String;
 i: Integer;
 dt: Cardinal;
begin
 dt := GetTickCount;
 for i := 0 to 100000 do
 begin
   s := FormatDateTime("hh:nn:ss  ",now)+ IntToStr(ThreadId)+"("+IntToStr(i)+"):"+StringOfChar("a",50);
   FLog.Add(s);
   if (i>0) and ((i mod 10000)=0) then
   begin
     MessageBox(0,PChar(IntTOStr(GetTickCount-dt)),"",MB_OK);
     Exit;
   end;
 end;
end;

//Тест1
procedure TForm1.Button1Click(Sender: TObject);
var
 Log1: TThreadLog;
begin
Log1 := TThreadLog.Create("c:\Log1","c:\ArchLog",100);
Log1.Start;
          TThrPing.Create("127.0.0.1",Log1);
          TThrPing.Create("127.0.0.2",Log1);
          TThrPing.Create("127.0.0.3",Log1);
end;

//Тест2
procedure TForm1.Button2Click(Sender: TObject);
var
 s: String;
 i: Integer;
 dt: Cardinal;
begin
 dt := GEtTickCount;
 for i := 0 to 100000 do
 begin
   s := FormatDateTime("hh:nn:ss  ",now)+ "qqqq"+"("+IntToStr(i)+"):"+StringOfChar("a",31);
   Log(s);
   if (i>0) and ((i mod 10000)=0) then
   begin
     MEssageBox(0,PChar(IntTOStr(GetTickCount-dt)),"",MB_OK);
     Exit;
   end;
 end;
end;

//Тест3
procedure TForm1.Button3Click(Sender: TObject);
var
 ld: TLDSLogger;
 s: String;
 i: Integer;
 dt: Cardinal;
begin
 ld := TLDSLogger.Create("c:\lds.log");
 dt := GEtTickCount;
 for i := 0 to 100000 do
 begin
   s := FormatDateTime("hh:nn:ss  ",now)+ "qqqq"+"("+IntToStr(i)+"):"+StringOfChar("a",31);
   ld.LogStr(s);
   if (i>0) and ((i mod 10000)=0) then
   begin
     MEssageBox(0,PChar(IntTOStr(GetTickCount-dt)),"",MB_OK);
     Exit;
   end;
 end;
 ld.Free;
end;

Время выполнения:
Тест1(Запись из 3х потоков) ~ 328-400мс
Тест2(Запись из 1 потока)    ~ 1203-1359мс
Тест3(Запись из 1 потока)    ~ 1172-1395мс


В LDS хорошая функциональность. При обычных требованиях к ведению журнала - отлично сделанная вещь.


 
Тын-Дын ©   (2008-06-28 01:42) [64]

PS.
Тест1 - Тын-Дын
Тест2 - Поросенок Винни-Пух
Тест3 - Loginov Dmitry



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2008.07.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.63 MB
Время: 0.009 c
2-1214288355
Муслик
2008-06-24 10:19
2008.07.27
treeview


2-1214668224
Ivan.S
2008-06-28 19:50
2008.07.27
TTreeView


15-1213375788
-koha
2008-06-13 20:49
2008.07.27
Всем смотреть!


1-1196157020
Pakito
2007-11-27 12:50
2008.07.27
Послать комбинацию клавиш стороннему приложению


2-1214379371
123-ий
2008-06-25 11:36
2008.07.27
Работа с логами





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский