2011-11-15 14 views
5

Moje zadanie polega na utworzeniu klasy, która gromadzi aktywność użytkowników w różnych aplikacjach.Implementowanie logowania bezpiecznego dla wątków

Załóżmy, że mam klasę TLogging i obiekt globalny o nazwie Logging.

Aktywność użytkownika (ekran otwarty, itp.) Powinna zostać zebrana w pamięci (może być umieszczona w liście (ciąg) o numerze TLogging) i zapisana w pliku dziennika po pewnym czasie (co 10 minut) lub po uruchomieniu aplikacji zamknięte.

Najważniejsze jest to, że rejestrowanie musi odbywać się w "trybie cichym", nie może w żaden sposób wpływać na przebieg pracy użytkownika: bez zawieszania się ekranu, bez wyjątków.

Proszę podać kierunek tego zadania.

+2

mieć wszystkie te cechy (a także dodatkowe funkcje, takie jak śledzenie wyjątku metody profilowania, nitki bezpieczeństwa lub opcjonalnym os -tread logowanie, które może być interesujące) w [naszej klasie OpenSource 'TSynLog'] (http://blog.synopse.info/post/2011/04/14/Enhanced-logging-in-SynCommons). Dla Delphi 5 do XE2. Zawiera przeglądarkę dziennika i poziom oparty na zestawie (nie jeden poziom globalny, ale zestaw niestandardowych poziomów). –

+2

@Arnaud Czy to nie jest odpowiedź? – NGLN

+0

Zobacz też: [Logging and Synchronization] (http://stackoverflow.com/questions/659094), [Która biblioteka logowania jest lepsza?] (Http://stackoverflow.com/questions/72983) i cała inna przeszłość [Delphi logowanie] (http://stackoverflow.com/search?q=%5Bdelphi%5D+logging) powiązane pytania i odpowiedzi. – NGLN

Odpowiedz

14

To bardzo szerokie zagadnienie, które dotyczy kilku obszarów. Kilka wskazówek:

  • Przynajmniej należy wziąć pod uwagę ustalone ramy logowania. Nowsze wersje Delphi pochodzą z CodeSite. SmartInspect to kolejna alternatywa.

  • Zastosowanie synchronizacji prymitywy, aby twoja klasa bezpieczny wątku: TCriticalSection, TMREWSync

  • Upewnij się zrozumieć problemy związane z wielowątkowości i synchronizacji przed przystąpieniem do pisania ramy rejestrowania wątku bezpieczny. Dobrym początkiem jest przewodnik Martina Harveya: Multithreading - The Delphi Way.

  • Użyj wątku tła, który wypróżnia zawartość dziennika na dysk w regularnych odstępach czasu lub jeśli buforował wystarczającą ilość danych.

  • Należy zadać bardziej szczegółowe pytania na ten temat, jeśli napotkasz określone problemy.

3

Korzystanie z OmniThreadLibrary i zakładając, że obiekt Logging jest singletonem, jest to naprawdę proste. Ograniczałbym także maksymalną liczbę wiadomości oczekujących na zapis, aby wewnętrzna kolejka nie mogła zużywać zbyt dużo pamięci.

const 
    CMaxMsgCount = 1000; 
    CMaxLogTimeout_ms = 10{min}*60{sec/min}*1000{ms/sec}; 

type 
    TLogging = class 
    strict private 
    FLogMsgCount: IOmniResourceCount; 
    FLogQueue: IOmniBlockingCollection; 
    FWriter: IOmniTaskControl; 
    strict protected 
    procedure Logger(const task: IOmniTask); 
    public 
    constructor Create; 
    destructor Destroy; 
    procedure Log(const msg: string); 
    end; 

var 
    Logging: TLogging; 

constructor TLogging.Create; 
begin 
    FLogMsgCount := CreateResourceCount(CMaxMsgCount); 
    FLogQueue := TOmniBlockingCollection.Create; 
    FWriter := CreateTask(Logger, 'Logger').Run; 
end; 

destructor TLogging.Destroy; 
begin 
    FWriter.Terminate; 
end; 

procedure TLogging.Log(const msg: string); 
begin 
    FLogQueue.Add(msg); 
    FLogMsgCount.Allocate; 
end; 

procedure TLogging.Logger(const task: IOmniTask); 

    procedure Flush; 
    var 
    logData: TOmniValue; 
    begin 
    // open file, possibly with retry 
    while FLogQueue.TryTake(logData) do begin 
     FLogMsgCount.Release; 
     // write logData.AsString 
    end; 
    // close file 
    end; 

begin 
    while DSiWaitForTwoObjects(task.TerminateEvent, FLogMsgCount.Handle, false, CMaxLogTimeout_ms) <> WAIT_OBJECT_0 do 
    Flush; 
    Flush; 
end; 

(Zastrzeżenie: „To kompiluje na moim komputerze”, w przeciwnym razie niesprawdzone.)

Powiązane problemy