2011-11-15 7 views
5

내 작업은 여러 응용 프로그램에서 사용자 활동을 수집 할 클래스를 만드는 것입니다.스레드 안전 로깅 구현

클래스 TLoggingLogging이라는 전역 개체가 있다고 가정 해 보겠습니다.

사용자 활동 (화면 열기, 등 ...)은 메모리에 수집되어 (TLogging의 (문자열) 목록에 삽입 될 수 있음) 일정 시간 간격 (10 분마다)이 지난 후 또는 로그 파일에 저장해야합니다 닫혀있다.

가장 중요한 것은 로깅이 "자동 모드"여야한다는 것입니다. 화면이 매달 리거나 예외가 발생하지 않는 방식으로 사용자 워크 플로에 영향을 주어서는 안됩니다.

이 작업의 방향을 알려주세요.

+2

당신 예외 추적, 방법 프로파일, 스레드 안전 또는 선택 사양 당 등의 모든 기능 (및 추가 기능을 가지고 (우리의 OpenSource'TSynLog' 클래스 (http://blog.synopse.info/post/2011/04/14/Enhanced-logging-in-SynCommons)에서 흥미로울 수 있습니다). XE2부터 델파이 5까지. 로그 뷰어 및 집합 기반 수준 (하나의 전역 수준이 아니라 사용자 지정 수준 집합)을 포함합니다. –

+2

@Arnaud 그 대답 아닌가요? – NGLN

+0

또한 [로깅 및 동기화] (http://stackoverflow.com/questions/659094), [로깅 라이브러리가 더 좋은 곳은 무엇입니까?] (http://stackoverflow.com/questions/72983) 및 그 외 모든 이전 [Delphi logging] (http://stackoverflow.com/search?q=%5Bdelphi%5D+logging) 관련 Q & A를 참조하십시오. – NGLN

답변

14

이것은 여러 영역을 다루는 매우 광범위한 질문입니다. 몇 가지 힌트 :

  • 적어도 이것을 위해 설정된 로깅 프레임 워크를 고려하십시오. 최신 델파이 버전은 CodeSite과 함께 제공됩니다. SmartInspect이 또 다른 대안입니다. TCriticalSection, TMREWSync

  • 당신이 스레드 안전 로깅 프레임 워크를 작성하기 전에 멀티 스레딩 및 동기화에 관련된 문제를 이해해야합니다 :

  • 를 사용하여 동기화 기본 스레드 안전 클래스를 확인합니다. 좋은 시작은 마틴 하비의 가이드 Multithreading - The Delphi Way입니다.

  • 일정한 간격으로 또는 충분한 데이터가 버퍼링 된 경우 로그 내용을 디스크에 플러시하는 백그라운드 스레드를 사용하십시오.

  • 특정 문제가 발생하는 경우 여기에서보다 구체적인 질문을하십시오.

3

OmniThreadLibrary를 사용하고 로깅 개체가 싱글 톤이라고 가정하면 이것은 매우 간단합니다. 또한 내부 대기열에서 너무 많은 메모리를 사용할 수 없도록 작성 대기중인 최대 메시지 수를 제한합니다.

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; 

(면책 조항 : 그렇지 않으면 검증되지 않은 "그것은 내 컴퓨터에서 컴파일".)