2011-11-15 9 views
5

मेरा कार्य एक कक्षा बनाना है जो कई अनुप्रयोगों के आसपास उपयोगकर्ता गतिविधि एकत्र करेगा।थ्रेड-सुरक्षित लॉगिंग लागू करें

मान लें कि मेरे पास कक्षा TLogging है और Logging नामक वैश्विक वस्तु है।

उपयोगकर्ता गतिविधि (स्क्रीन खुली, आदि ...) स्मृति में एकत्र की जानी चाहिए (शायद TLogging की एक (स्ट्रिंग) सूची में डाल दी जानी चाहिए) और कुछ समय अंतराल (प्रत्येक 10 मिनट) के बाद लॉग फ़ाइल में सहेजा जाना चाहिए, या जब आवेदन बंद हो गया है।

सबसे महत्वपूर्ण यह है कि लॉगिंग "मूक मोड" में होनी चाहिए, यह किसी भी तरह से उपयोगकर्ता वर्कफ़्लो को प्रभावित नहीं करेगा: कोई स्क्रीन लटकती नहीं है, कोई अपवाद नहीं है।

कृपया मुझे इस कार्य के लिए दिशा दें।

+2

आप उन सभी सुविधाओं (और यह भी अतिरिक्त सुविधाओं, अपवाद ट्रेसिंग, विधि की रूपरेखा, धागे की सुरक्षा या एक वैकल्पिक प्रति की तरह है थ्रेड लॉगिंग जो दिलचस्प हो सकती है) [हमारे ओपन सोर्स 'टीएसआईनलॉग क्लास] में (http://blog.synopse.info/post/2011/04/14/ उन्नत-logging-in-SynCommons)। डेल्फी 5 तक XE2 तक। एक लॉग व्यूअर, और एक सेट-आधारित स्तर (एक वैश्विक स्तर नहीं, बल्कि अनुकूलित स्तरों का एक सेट) सहित। –

+2

@Arnaud क्या यह उत्तर नहीं है? – NGLN

+0

यह भी देखें: [लॉगिंग और सिंक्रनाइज़ेशन] (http://stackoverflow.com/questions/659094), [कौन सी लॉगिंग लाइब्रेरी बेहतर है?] (Http://stackoverflow.com/questions/72983) और अन्य सभी अतीत [डेल्फी लॉगिंग] (http://stackoverflow.com/search?q=%5Bdelphi%5D+logging) संबंधित प्रश्नोत्तर। – NGLN

उत्तर

14

यह एक बहुत व्यापक सवाल है जो कई क्षेत्रों को छूता है। कुछ संकेत:

  • कम से कम इसके लिए एक स्थापित लॉगिंग ढांचे पर विचार करें। न्यूर डेल्फी संस्करण CodeSite के साथ आते हैं। SmartInspect एक और विकल्प है। TCriticalSection, TMREWSync

  • सुनिश्चित करें कि आप एक धागा सुरक्षित प्रवेश ढांचे लिखने के लिए प्रयास करने से पहले multithreading और तुल्यकालन में शामिल मुद्दों को समझते हैं:

  • उपयोग तुल्यकालन पुरातन अपनी कक्षा धागा सुरक्षित बनाने के लिए। मार्टिन हार्वे की मार्गदर्शिका Multithreading - The Delphi Way अच्छी शुरुआत है।

  • पृष्ठभूमि थ्रेड का उपयोग करें जो नियमित अंतराल में डिस्क पर लॉग सामग्री को फ़्लश करता है या पर्याप्त डेटा buffered किया गया है।

  • यदि आपको विशिष्ट समस्याएं आती हैं तो SO पर अधिक विशिष्ट प्रश्न पूछें।

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; 

(अस्वीकरण:, अन्यथा अपरीक्षित "यह मेरे मशीन पर संकलित"।)

संबंधित मुद्दे