2010-11-29 18 views
11

मेरे पास मेरी वेबसाइट द्वारा प्रकट कुछ अलग-अलग वेब सेवाएं हैं। यहां एक लक्ष्य है जो मैं प्राप्त करना चाहता हूं:log4net: संग्रहीत करने के लिए डेटा को कस्टमाइज़ करने के लिए कैसे करें

  1. डीबी में सभी डेटा एक तालिका में स्टोर करें;
  2. प्रत्येक रिकॉर्ड में 'सेवा/घटक' नाम के साथ टेक्स्ट फ़ील्ड होना चाहिए;
  3. किसी भी विधि को कॉल करते समय सभी आय मानकों को स्टोर करना आवश्यक है;
  4. यदि कोई अपवाद हुआ है तो सभी परिणाम पैरामीटर और त्रुटि संदेशों को स्टोर करना आवश्यक है।

मेरा मूल उद्देश्य log4net का उपयोग करना था। लेकिन इन चलने से (http://sadi02.wordpress.com/2008/09/15/how-to-store-log-in-डेटा-using-log4net/, http://logging.apache.org/log4net/release/config-examples.html) मुझे एक आसान तरीका नहीं दिख रहा है लॉग तालिका में कस्टम डेटा जोड़ने के लिए।

क्या ऐसे उद्देश्यों के लिए log4net का उपयोग करना संभव है? कस्टम डेटा स्टोर करने के लिए मैं लॉगिंग टेबल स्कीमा कैसे बदल सकता हूं? क्या मुझे log4net लाइब्रेरी के स्रोत कोड को संशोधित करना चाहिए? ऐसे प्रकार के डेटा को स्टोर करने के लिए शायद एक कस्टम कार्यक्षमता लिखना बेहतर होगा?

धन्यवाद।

उत्तर

2

सुझाए गए उत्तरों में से कोई भी मेरे लिए काम नहीं करता है। समस्या यह है कि मुझे कई कस्टम फ़ील्ड होने की आवश्यकता है। मेरे लिए यह लॉगर के विभिन्न उदाहरण बनाने या 'गुण' के माध्यम से हर बार कॉलम मान सेट करने के लिए बहुत जटिल लगता है।

मैं (वास्तव में, पहले ही कार्यान्वित) कस्टम लॉगर (डीबी में डेटा डाल दूंगा) जाऊंगा।

1

log4net प्रलेखन को देखते हुए, क्या आप यह समझ सकते हैं कि फ़ाइल में अपना कस्टम डेटा कैसे लॉग किया जाए? यदि ऐसा है, तो आपको डेटाबेस में लॉग इन उसी डेटा को भी प्राप्त करने में सक्षम होना चाहिए। अपनी तालिका में बस अधिक कॉलम जोड़ें, AdoNetAppender के <command text> नोड में और अधिक कॉलम और अधिक <parameter> नोड्स जोड़ें।

मुझे लगता है कि आपके आने वाले और आउटगोइंग पैरामीटर लॉग इन करने के लिए आपके पास कुछ काम होगा। क्या आपको अलग कॉलम में लॉग इन करने की ज़रूरत है (शायद साफ-सफाई करना आसान नहीं है)? क्या यह ठीक है अगर वे संदेश के साथ लॉग इन हैं?

उदाहरण के लिए, यदि आप निम्न विधि है कि आप में प्रवेश करने डाल चाहते हैं:

public void DoSomething(int x, int y) 
{ 
    log.Info("Inside DoSomething"); 
} 

क्या आप की तरह लग रहे करने के लिए अपने उत्पादन करना चाहते हैं? क्या आप "मानक" log4net जानकारी को अलग-अलग कॉलम (टाइमस्टैम्प, लॉगगाइमनाम, स्तर, संदेश) में दिखाना चाहते हैं? पैरामीटर के बारे में क्या? x और y अलग-अलग कॉलम में दिखाई देनी चाहिए (शायद नहीं बहुत आसान है जब तक कि हर विधि मानकों का एक ही नंबर है करने के लिए) या यह ठीक है, तो पैरामीटर इस तरह लॉग इन थे होगा:

public void DoSomething(int x, int y) 
{ 
    ILog log = LogManager.GetLogger("abc"); 
    log.InfoFormat("Parameters: x = {0}, y = {1}", x, y); 
    log.Info("Inside DoSomething"); 
} 

लॉग बयान संदेशों उत्पन्न होगा यह इस तरह कुछ दिखाई देगा:

11/29/2010 16:36:00 | abc | INFO | Parameters: x = 10, y = 20 
11/29/2010 16:36:00 | abc | INFO | Inside DoSomething 

मैंने उपयोग किया है | चरित्र दिखाने के लिए कि फ़ील्ड पैटर्न पैटर्न के साथ क्या होगा जो टाइमस्टैम्प, लॉगगाइमनाम, लॉग स्तर और संदेश दिखाता है।

PostSharp जैसे एओपी समाधान को देखकर आपकी मदद हो सकती है क्योंकि आप लॉगिंग स्टेटमेंट के साथ अपने एप्लिकेशन स्रोत कोड को "प्रदूषित" किए बिना अपेक्षाकृत आसानी से प्रवेश/निकास लॉगिंग जोड़ सकते हैं। लॉगिंग "पहलू" के अंदर आपको विधि के पैरामीटर तक पहुंच होगी।

मुझे कुछ याद आ रहा है, लेकिन मुझे संदेह है कि यदि आप डेटाबेस में अलग-अलग कॉलम के रूप में अपने विधि पैरामीटर को बनाए रखना चाहते हैं तो आपको यह करना मुश्किल होगा। यदि आप प्रत्येक विधि के लिए सभी पैरामीटर (मैन्युअल रूप से) को एक कॉलम (अनिवार्य रूप से एक स्वरूपित स्ट्रिंग) के रूप में संयोजित करने से संतुष्ट हैं, तो यह आसान होगा।आपको एक कीमत चुकानी पड़ेगी कि आपको सभी पैरामीटर स्पष्ट रूप से लॉग इन करना होगा (जब तक आप एओपी रूट नहीं जाते)।

यदि आप log4net का उपयोग करने पर विचार कर रहे हैं, तो आपको एनएलओजी का उपयोग करने पर भी विचार करना चाहिए। यह आपके ऊपर वर्णित मुद्दों के साथ जरूरी नहीं है, लेकिन मुझे लगता है कि यह log4net के लिए एक योग्य प्रतियोगी है।

[संपादित करें]

"घटक का नाम" log4net द्वारा लॉग, आप अपने घटकों के लिए अपने वालों नाम रखना चाहिए पाने के लिए। जब आप LogManager.GetLogger (नाम) को कॉल करते हैं, तो आप किसी भी नाम (या प्रकार) को पास कर सकते हैं। एक आम पैटर्न प्रत्येक वर्ग में इस तरह कोड है:

public class MyClass 
{ 
    private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    public void DoSomething(int x) 
    { 
    logger.InfoFormat("Inside DoSomething. x = {0}", x); 
    } 
} 

यह पूरी तरह से योग्य वर्ग के नाम (नाम स्थान + वर्ग के नाम) के साथ नाम का एक लकड़हारा मिल जाएगा। यदि आप प्रत्येक वर्ग में ऐसा करते हैं, तो आप प्रति वर्ग लॉगिंग (स्तर, कौन सा एपेंडर इसे जाता है, आदि) नियंत्रित कर सकते हैं। तो, आप आसानी से कक्षा 1 के लिए लॉगिंग को बंद कर सकते हैं और कक्षा 2 के लिए लॉगिंग कर सकते हैं, आदि। यह आपको अपने लॉगिंग के नियंत्रण की सबसे बड़ी डिग्री की संभावना देता है।

अब, अपनी कॉन्फ़िगरेशन फ़ाइल में, आप प्रत्येक लॉगर (यानी प्रत्येक पूरी तरह से योग्य वर्ग नाम) को स्पष्ट रूप से सूचीबद्ध करने के लिए बाध्य नहीं हैं। आप रूट लॉगर को बस कॉन्फ़िगर कर सकते हैं और फिर उन सेटिंग्स को प्रत्येक लॉगर पर लागू किया जाएगा। आप नामस्थान द्वारा लॉगिंग को नियंत्रित कर सकते हैं। उदाहरण के लिए, यदि आप CompanyX के लिए काम करते हैं और आप स्पष्ट नाम स्थान नियम है, अपने नामस्थान प्रकार दिखाई देंगे:

CompanyX 
CompanyX.DataAccess 
CompanyX.DataAccess.Read 
CompanyX.DataAccess.Write 
CompanyX.GUI 
CompanyX.Forms 
CompanyX.Controls 

प्रत्येक नाम स्थान के भीतर कई विभिन्न डेटा पाठक, सहायक कक्षाएं, डेटा लेखकों की तरह, आप विभिन्न वर्ग हो सकता है (, आदि)। आपके साथ इस तरह व्यवस्थित कक्षाएं और आपके वर्गों के ऊपर के रूप में लॉगर्स प्राप्त करने के साथ, आप आसानी से CompanyX में सभी वर्गों के लिए लॉगिंग कॉन्फ़िगर कर सकते हैं, या CompanyX.DataAccess, या CompanyX.DataAccess.Read, आदि में सभी लॉगर्स आसानी से लॉग इन कर सकते हैं। आप सभी लॉगिंग बंद भी कर सकते हैं , लेकिन इसे उस परेशानी वर्ग के लिए चालू करें जो आपको समस्याएं दे रहा है।

आप अपने लॉगर्स को मनमाना नामों से भी प्राप्त कर सकते हैं (यानी यदि आप नहीं चाहते हैं तो आपको कक्षा का नाम उपयोग करने की आवश्यकता नहीं है)। आप अपने ऐप में कार्यात्मक क्षेत्रों को परिभाषित कर सकते हैं और उस पर आधारित लॉगर्स प्राप्त कर सकते हैं:

ILog logger = LogManager.GetLogger("DataAccess"); 
ILog logger = LogManager.GetLogger("Performance"); 
ILog logger = LogManager.GetLogger("UI"); 

और इसी तरह। मुझे नहीं लगता कि यह पूरी तरह से योग्य वर्ग नाम का उपयोग करने पर अधिक लाभ देता है। यदि आपके नेमस्पेस अच्छी तरह व्यवस्थित हैं, तो आपके लॉगिंग को कॉन्फ़िगर करने की आपकी क्षमता में आपके हिस्से पर न्यूनतम प्रयास के साथ अधिकतम लचीलापन होगा।

NLog पर एक और शब्द ... एनएलओजी log4net के समान है।

Logger logger = NLog.LogManager.GetCurrentClassLogger(); 

यह कम से कम अपनी ओर से कुछ टाइपिंग की बचत होती है: यह स्वचालित रूप से वर्तमान वर्ग के लिए एक लकड़हारा वापस जाने के लिए सक्षम होने की उपयोगी सुविधा है। एनएलओजी अभी भी एक नई रिलीज के साथ बाहर आया है (वर्तमान में बीटा में)।

पता नहीं है कि इनमें से कोई भी मदद करता है, लेकिन मुझे उम्मीद है कि यह हुआ!

शुभकामनाएं!

+0

1 फ़ील्ड में सभी पैरामीटर रखना ठीक है, लेकिन (जैसा कि मैंने किसी अन्य उत्तर में टिप्पणी में उल्लेख किया है) मैं एक अलग कॉलम में घटक नाम रखना चाहता हूं (प्रत्येक कॉल के लिए वैश्विक संदर्भ को बदले बिना)। इसके अलावा मुझे 3 अतिरिक्त कॉलम चाहिए: आय_डेटा, outcome_data, error_message। शायद, मैं कुछ अलग लॉगर इंस्टेंस (प्रति घटक 1) को कॉन्फ़िगर कर सकता हूं? और इस मामले में मुझे हर बार वैश्विक सेटिंग्स बदलने की आवश्यकता नहीं होगी? क्षमा करें, मैं log4net के साथ नया हूँ। – Budda

+0

हां, आप शायद प्रति घटक कम से कम एक लॉगर चाहते हैं। मैंने अपने जवाब में कुछ उदाहरण जोड़े हैं। – wageoghe

14

इस discussion के अनुसार, प्रक्रिया बहुत सरल है।करने के लिए

<commandText value="INSERT INTO Log4Net ([Date],[Thread],[Level],[Logger],[Message],[Exception],[MyColumn]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception,@MyColumn)"/>   

अगले कदम है और कस्टम स्तंभ के लिए एक नया पैरामीटर परिभाषा जोड़ें::

<parameter> 
    <parameterName value="@MyColumn "/> 
    <dbType value="String" /> 
    <size value="255" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%property{MyColumn}" /> 
    </layout> 
</parameter> 

पहला कदम है अपने कॉन्फ़िग फ़ाइल में appender घोषणा में आदेश पाठ अद्यतन करने के लिए है

log4net.GlobalContext.Properties["MyColumn"] = "MyValue"; 
log.Debug("My message"); 
:

अंत में, आप log4net की GlobalContext गुण के माध्यम से मूल्य तक पहुँच सकते हैं 10

आप इसे जितनी जरूरत हो उतनी फ़ील्ड के लिए कर सकते हैं।

+0

क्या मैं सही ढंग से समझता हूं कि प्रत्येक लेखन से पहले मुझे "MyColumn" का उचित मूल्य निर्धारित करना चाहिए? उदाहरण के लिए, मेरी वेबसाइट को 3 अलग-अलग "घटकों" का समर्थन करना है। मैं एक अलग कॉलम में घटक का नाम रखना चाहता हूं, इस मामले में क्या मुझे प्रत्येक कॉल से पहले वैश्विक संदर्भ की "MyComponent" संपत्ति सेट करनी चाहिए? मुझे नहीं लगता कि मुझे यही चाहिए (मुझे भी समेकन को संभालने की आवश्यकता होगी) ... – Budda

+0

शायद, मैं कुछ अलग लॉगर इंस्टेंस (प्रति घटक 1) को कॉन्फ़िगर कर सकता हूं? क्या मैं इस धारणा के साथ सही हूँ? और इस मामले में मुझे हर बार वैश्विक सेटिंग्स बदलने की आवश्यकता नहीं होगी? क्षमा करें, मैं log4net के साथ नया हूँ। – Budda

+0

@ बुड्डा हां, आपको आवश्यकतानुसार प्रत्येक "MyColumn" उदाहरण के लिए आवश्यक मानों को दोहराना होगा। घटकों के लिए, आपको प्रत्येक इंस्टेंस के लिए एक सेट अप करना होगा, लेकिन याद रखें कि सभी परिशिष्ट एक ही लॉग डेटा का उपयोग करते हैं, ताकि आप आसानी से एक डीबी एपेंडर प्रक्रिया MyColumn1 और दूसरी एपेंडर प्रक्रिया MyColumn2 की आवश्यकता हो। –

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

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