Ucięty plik tekstowy - DLACZEGO !?

2012-01-17 13:57
0

Może mi ktoś powiedzieć czemu mi logi upieraa w połowie tzn
w pliku mam

+---- START ------- [2012-01-17] [13:44:41] --------------+
[13:44:41] [Application] AppDir [C:\Users\ProQix Polaczeq\Desktop\Tia\Server\Server.exe]
[13:44:41] [Application] Load CFG
[13:44:41] [Plugins Manager] Exec [plugin_in

Po zamknięciu aplikacji nic się nie zmienia
a procedurki za to odpowiedzialne wyglądają tak

procedure TTiaServerBody.LogEvent(Data:String);
begin
 WriteLn(g_EventFile,Data);
end;
procedure TTiaServerBody.LogEventBegin;
begin
 AssignFile(g_EventFile,AppDir+'Logs\'+DateToStr(Date)+' - Events.log');
 if FileExists(AppDir+'Logs\'+DateToStr(Date)+' - Events.log') = True then Append(g_EventFile) else Rewrite(g_EventFile);
 LogEvent(Format('+---- START ------- [%s] [%s] --------------+',[DateToStr(Date),TimeToStr(Time)]));
end;
procedure TTiaServerBody.LogEventEnd;
begin
 LogEvent(Format('+----- END --------- [%s] [%s] --------------+',[DateToStr(Date),TimeToStr(Time)]));
 Sleep(400);
 CloseFile(g_EventFile);
 LogsBox.Items.SaveToFile(AppDir+'Logs\'+DateToStr(Date)+' - Events.log');
end;
LogEvent(Format('[%s] [%s] AppDir [%s]',[TimeToStr(Time),'Application',Application.ExeName]));

podobnie wygląda reszta tylko nie wiem czemu tak ucina?

Ostatnia linia w pliku powinna wyglądać tak
[13:45:57] [Plugins Manager] Exec [plugin_initd] - DLL [C:\WEBServer\Lib\tester.dll]

a Format('+----- END --------- [%s] [%s] --------------+',[DateToStr(Date),TimeToStr(Time)]) nie ma a powinno być


CodeGear Delphi 2007 | Windows 7 |
Jak to dobrze że istnieje opcja edytuj post ;]

Pozostało 580 znaków

2012-01-17 14:42
ŁF
0

pracowicie zapisujesz do pliku, a na koniec robisz LogsBox.Items.SaveToFile(AppDir+'Logs\'+DateToStr(Date)+' - Events.log'); nadpisując to, co wcześniej zapisałeś


Pozostało 580 znaków

2012-01-17 15:01
0

fakt
LogsBox.Items.SaveToFile(AppDir+'Logs\'+DateToStr(Date)+' - Events.log');
to było dla testu przed tym żeby sprawdzić czy się zapisuje inną metodą i jak tak zapisałem to wleciało wszystko, jednak tego nie mogę używać bo logi muszą być zapisywane na bieżąco bo liczy się ile pracował program i co zrobił zanim się zawiesił/wyłączył albo coś innego (taki debugger). Bo program jest na razie nie stabilny a jak będę tego używał a pozycji będzie max 60 (zwalniam pamięć bo wyobraź sobie 100000 linii do zapisania po 64 B !) to by kasowało poprzednie logi.


CodeGear Delphi 2007 | Windows 7 |
Jak to dobrze że istnieje opcja edytuj post ;]

Pozostało 580 znaków

2012-01-17 15:32
ŁF
0

i słusznie, logów nie trzyma się w pamięci, dopisujesz kolejne linijki do pliku i to wszystko. rozmiarem martwi się administrator. sto tysięcy linijek po kilkaset znaków to raptem kilkadziesiąt MB (w produkcyjnych zastosowaniach logi mogą osiągać rozmiar kilkuset GB i więcej).
sprawdź, czy nie masz wyłączonej opcji "huge strings".


Pozostało 580 znaków

2012-01-17 17:44
0

to nie ma z tym związku niestety :( (mam CG Delphi 2007 i win 7)


CodeGear Delphi 2007 | Windows 7 |
Jak to dobrze że istnieje opcja edytuj post ;]

Pozostało 580 znaków

2012-01-17 20:14
123
0

Sleep(400);

A to po co?

Zapewne nie używasz zamykania logu i dlatego go obcina bo jest bufor zapisu. Jak log ma działać nawet mimo wykrzaczenia aplikacji to dodaj po writeln flush(plik); (zapisze bufor).

I BTW. naprawdę dopiski w temacie typu "DLACZEOG !?" są niepotrzebne a nawet niewskazane. Zachowuj się porządnie...

Pozostało 580 znaków

2012-01-17 20:32
0

@proqix, dlaczego wybrałeś takie rozwiązanie (pozwoliłem sobie sformatować kod, bo niewiele w nim widziałem):

procedure TTiaServerBody.LogEvent(Data: String);
begin
  WriteLn(g_EventFile, Data);
end;

procedure TTiaServerBody.LogEventBegin;
begin
  AssignFile(g_EventFile, AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log');

  if FileExists(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log') then
    Append(g_EventFile)
  else
    Rewrite(g_EventFile);

  LogEvent(Format('+---- START ------- [%s] [%s] --------------+', [DateToStr(Date), TimeToStr(Time)]));
end;

procedure TTiaServerBody.LogEventEnd;
begin
  LogEvent(Format('+----- END --------- [%s] [%s] --------------+', [DateToStr(Date), TimeToStr(Time)]));
  Sleep(400);

  CloseFile(g_EventFile);
  LogsBox.Items.SaveToFile(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log');
end;

??? Trochę to dziwne, że używasz takiej konstrukcji; Czy klasa TTiaServerBody jest w całości napisana przez Ciebie? Bo jeżeli tak, to czemu wykorzystujesz g_EventFile jako zmienną globalną? Czy g_EventFile jest polem prywatnym?

Musisz się zastanowić nad tym zapisem i zrobić (tak jak Ci podpowiada @123) Flush(g_EventFile);, albo po prostu otwierać i zamykać plik każdorazowo, jak trzeba zapisać doń jakieś informacie; Wiadomo, ten sposób będzie mało wydajny, ale mniej błędny; Zrób trzy procedury:

  1. do wpisywania początku logu
  2. do wpisywania aktualnych wartości logu
  3. do wpisywania zakończenia logu
    i sprzęż je tak, by argumentem była wartość, a otwieranie i zamykanie pliku było oprogramowane tylko raz:
procedure TTiaServerBody.SaveLogEvent(Data: String);
begin
  AssignFile(g_EventFile, AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log');

  try
    if FileExists(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log') then
      Append(g_EventFile)
    else
      Rewrite(g_EventFile);

    WriteLn(g_EventFile, Data);
  finally
    CloseFile(g_EventFile);
  end;
end;

procedure TTiaServerBody.LogEventBegin();
begin
  SaveLogEvent(Format('+---- START ------- [%s] [%s] --------------+',
               [DateToStr(Date), TimeToStr(Time)]));
end;

procedure TTiaServerBody.LogEventBegin();
begin
  SaveLogEvent(Format('+----- END --------- [%s] [%s] --------------+',
               [DateToStr(Date), TimeToStr(Time)]));
  Sleep(400);
  LogsBox.Items.SaveToFile(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log');
end;

Co Ty na to?


edytowany 3x, ostatnio: furious programming, 2012-01-17 20:41

Pozostało 580 znaków

2012-01-17 20:40
0

g_EventFile : TextFile jest w głównym varze (tak gdzie TiaServerBody: TTiaServerBody;) procedury zadeklarowane w public, ja potrzebuje wydajności !
LogEventBegin; jest używany w OnCreate formy a LogEventend; w OnClose, LogEvent jest wykorzystywany przez inne formy (Unity).

Jak pisałem w wyżej LogsBox.Items.SaveToFile(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log'); użyłem by sprawdzić czy się zapisuje dobrze jak użyję domyślnej procedury, bo muszę często opróżniać pamięć bo raz przy włączeniu programu poszedłem do kibla a jak wruciłem to miałem 200kB logów oczywiście ostatnia linia została ucięta :(


CodeGear Delphi 2007 | Windows 7 |
Jak to dobrze że istnieje opcja edytuj post ;]
edytowany 1x, ostatnio: proqix, 2012-01-17 20:43

Pozostało 580 znaków

2012-01-17 20:48
0
proqix napisał(a)

g_EventFile : TextFile jest w głównym varze (tam gdzie TiaServerBody: TTiaServerBody;) procedury zadeklarowane w public

To błąd, wiesz przecież, że nie zaleca się korzystania ze zmiennych globalnych... Czy te procedury masz zadeklarowane w sekcji public klasy formularza? Bo jeżeli tak, to wg mnie źle to przemyślałeś; Polecam bardzo gorąco utworzyć osobną klasę, w której zaimplementujesz obsługę pliku log; Dzięki temu unikniesz bałaganu w kodzie i w jedym obiekcie zawrzesz i metody do obsługi pliku log i zmienną plikową, która będzie widoczna tylko w obrębie modułu klasy (czyli w sekcji private klasy); Dzięki temu bezpośrednio nie będzie można dokonywać modyfikacji na zmiennej plikowej, a metody, które służą do zapisywania poszczególnych linii w pliku będą mogły swobodnie z niej korzystać;

ja potrzebuje wydajności !

Z jaką częstotliwością będzie realizowane zapisywanie linii do pliku?

@ Ta linia:

LogsBox.Items.SaveToFile(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log');

będzie Ci nadpisywać zawartość wcześniej uzupełnionego pliku; Trzeba ją usunąć (a może ja ją niepotrzebnie wkleiłem do kodu..?);


edytowany 1x, ostatnio: furious programming, 2012-01-17 20:50

Pozostało 580 znaków

2012-01-17 21:03
0

@ tak ona była dla testu,
@ co do częstotliwości to zależny czy błędy się będą sypać jak lawina pomijając logi ważnych zmiennych takich ja użycie procedury/funkcji z bibliotek (pluginów)
jeżeli chodzi o zamknięcie loggera w osobnej klasie to nie myślałem o tym gdyż to małe czynności są ;] ale zaraz zrobię to i zobaczymy


CodeGear Delphi 2007 | Windows 7 |
Jak to dobrze że istnieje opcja edytuj post ;]

Pozostało 580 znaków

2012-01-17 21:07
1
proqix napisał(a)

@ co do częstotliwości to zależny czy błędy się będą sypać jak lawina pomijając logi ważnych zmiennych takich ja użycie procedury/funkcji z bibliotek (pluginów)

A tak mniej więcej? Jakie maksimum przewidujesz? Kilka, kilkanaście, kilkaset na sekundę? Mniej więcej; Bo jeżeli będzie ich maksymalnie kilka, to nie musisz się bać, że program będzie się dławił, jak za każdym razem gdy chcesz zapisać coś w pliku będziesz go otwierał i zamykał;

Zawsze możesz przeprowadzić test na klasie - zapuść pętlę na 10.000 iteracji, w której będziesz odpowiednio:

  1. otwierał plik
  2. zapisywał linię
  3. zamykał plik
    i zobacz, w jakim czasie on to wykona; Później oblicz ile możesz takich operacji wykonać, żeby program się nie przycinał;

Jeżeli wszystko będzie w porządku - skorzystaj z takiego rozwiązania :)

proqix napisał(a)

jeżeli chodzi o zamknięcie loggera w osobnej klasie to nie myślałem o tym gdyż to małe czynności są

Owszem, ale przejżystość kodu wzrośnie co jest atutem;

@ Naszkicowałem Ci przykładową klasę do obsługi pliku log (kod modułu):

unit uLogFileSupport;

interface

uses
  SysUtils;

type
  TLogFileSupport = class(TObject)
  private
    FLogFileName: String;
  public
    constructor Create(LogFileName: String);
    destructor Destroy(); override;

    procedure LogEvent(Event: String);
    procedure BeginLog();
    procedure EndLog();
  end;

implementation

  constructor TLogFileSupport.Create(LogFileName: String);
  begin
    inherited Create();

    FLogFileName := LogFileName;
  end;

  destructor TLogFileSupport.Destroy();
  begin
    inherited Destroy();
  end;

  procedure TLogFileSupport.LogEvent(Event: String);
  var
    fLogFile: TextFile;
  begin
    AssignFile(fLogFile, FLogFileName);

    try
      case FileExists(FLogFileName) of
        True:  Append(fLogFile);
        False: ReWrite(fLogFile);
      end;

      WriteLn(fLogFile, Event);
    finally
      CloseFile(fLogFile);
    end;
  end;

  procedure TLogFileSupport.BeginLog();
  begin
    LogEvent(Format('+---- START ------- [%s] [%s] --------------+',
                    [DateToStr(Date), TimeToStr(Time)]));
  end;

  procedure TLogFileSupport.EndLog();
  begin
    LogEvent(Format('+----- END --------- [%s] [%s] --------------+',
                    [DateToStr(Date), TimeToStr(Time)]));
  end;

end.

Tworzenie i usuwanie obiektu (odpowiednio podczas tworzenia i niszczenia formularza):

procedure TForm1.FormCreate(Sender: TObject);
begin
  lfsLog := TLogFileSupport.Create(AppDir + 'Logs\' + DateToStr(Date) + ' - Events.log');
  lfsLog.BeginLog();
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  lfsLog.EndLog();
  lfsLog.Free();
end;

Wpisywanie zdarzenia do pliku:

lfsLog.LogEvent('Treść zdarzenia');

Klasa przetestowana i działa w 100%; Uruchomienie aplikacji, trzykrotne zapisanie zdarzenia i zamknięcie aplikacji spowodowało zapisanie do pliku treści:

+---- START ------- [2012-01-17] [21:34:49] --------------+
Treść zdarzenia
Treść zdarzenia
Treść zdarzenia
+----- END --------- [2012-01-17] [21:34:52] --------------+

Wszystko pięknie; Może być taka konstrukcja? :)


edytowany 6x, ostatnio: furious programming, 2012-01-17 21:38

Pozostało 580 znaków

Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0