मल्टी-लेयर्ड आर्किटेक्चर: जहां मुझे त्रुटि लॉगिंग \ हैंडलिंग को लागू करना चाहिए?


17

मैं वर्तमान में एक बहुस्तरीय वास्तुकला के साथ एक बड़े सबसिस्टम को फिर से शुरू कर रहा हूं, और मैं एक प्रभावी त्रुटि लॉगिंग \ हैंडलिंग रणनीति डिजाइन करने के लिए संघर्ष कर रहा हूं।

मान लीजिए कि मेरी वास्तुकला में निम्नलिखित तीन परतें शामिल हैं:

  • सार्वजनिक इंटरफ़ेस (IE एक MVC नियंत्रक)
  • डोमेन परत
  • डेटा एक्सेस लेयर

भ्रम का मेरा स्रोत वह जगह है जहां मुझे त्रुटि लॉगिंग \ हैंडलिंग को लागू करना चाहिए:

  1. सबसे आसान समाधान शीर्ष स्तर पर लॉगिंग को लागू करना होगा (आईई पब्लिक इंटरफेस \ एमवीसी नियंत्रक)। हालांकि यह गलत लगता है क्योंकि इसका मतलब है कि अलग-अलग परतों के माध्यम से अपवाद को बुदबुदाना, और फिर इसे लॉग करना; इसके स्रोत पर अपवाद को लॉग करने के बजाय।

  2. इसका स्रोत पर अपवाद लॉगिंग स्पष्ट रूप से सबसे अच्छा समाधान है क्योंकि मेरे पास सबसे अधिक जानकारी है। इसके साथ मेरी समस्या यह है कि मैं सभी अपवादों को पकड़े बिना स्रोत पर हर अपवाद को नहीं पकड़ सकता, और डोमेन / सार्वजनिक इंटरफ़ेस परत में, यह अपवादों को पकड़ने का कारण होगा जो पहले से ही पकड़े गए, लॉग किए गए हैं और नीचे की परत द्वारा फिर से फेंक दिए गए हैं ।

  3. एक और संभावित रणनीति # 1 और # 2 का मिश्रण है; जिससे मैं उस स्तर पर विशिष्ट अपवादों को पकड़ता हूं, जो कि वे सबसे अधिक होने की संभावना रखते हैं (आईई कैचिंग, लॉगिंग और SqlExceptionsडेटा एक्सेस लेयर में फिर से फेंकना ) और फिर शीर्ष स्तर पर किसी भी अन्य अनकैप्ड अपवाद को लॉग करते हैं। हालांकि इसके लिए मुझे शीर्ष स्तर पर हर अपवाद को पकड़ने और फिर से लिखने की भी आवश्यकता होगी, क्योंकि मैं उन त्रुटियों के बीच अंतर नहीं कर सकता जो पहले से ही लॉग इन किए गए हैं, जो नहीं हैं।

अब, स्पष्ट रूप से यह अधिकांश सॉफ्टवेयर अनुप्रयोगों में एक मुद्दा है, इसलिए इस समस्या का एक मानक समाधान होना चाहिए, जिसके परिणामस्वरूप अपवादों को स्रोत पर पकड़ा जा सकता है, और एक बार लॉग इन किया जा सकता है; हालाँकि मैं अभी यह नहीं देख सकता कि यह कैसे करना है।

ध्यान दें, इस सवाल का शीर्षक ' एक बहु स्तरीय अनुप्रयोग में अपवादों को लॉग करना' के समान है , हालांकि उस पोस्ट के उत्तर में विस्तार का अभाव है और मेरे प्रश्न का उत्तर देने के लिए पर्याप्त नहीं है।


1
एक दृष्टिकोण जो मैं कभी-कभी उपयोग करता हूं, वह है अपना स्वयं का अपवाद (या रनटाइम एक्सेप्शन) उप-वर्ग बनाना और इसे फेंकना, मूल अपवाद सहित एक नेस्टेड के रूप में। बेशक इसका मतलब यह है कि जब ऊपरी स्तरों पर अपवादों को कैप्चर करना होता है, तो मुझे अपवाद के प्रकार की जांच करने की आवश्यकता होती है (मेरे खुद के अपवादों को केवल पुनर्विचार मिलता है, अन्य अपवाद लॉग किए जाते हैं और मेरे अपवादों के नए उदाहरणों में शामिल होते हैं)। लेकिन मैं लंबे समय से एकल काम कर रहा हूं इसलिए मैं "आधिकारिक" सलाह नहीं दे सकता।
SJuan76

4
The easiest solution would be to implement the logging at the top level- यह करो। उनके स्रोत पर अपवाद लॉग करना एक अच्छा विचार नहीं है और मैंने जो भी आवेदन किया है वह यह है कि यह पीआईए को डिबग करने के लिए था। अपवादों को संभालने के लिए कॉल करने वाले की जिम्मेदारी होनी चाहिए।
जस्टिन

आप कुछ विशिष्ट कार्यान्वयन तकनीक / भाषा को ध्यान में रखते हैं, अन्यथा आपके कथन "जो लॉग लॉग किए गए थे, वे उन लोगों से अविभाज्य हैं जो" नहीं थे "समझना मुश्किल है। क्या आप अधिक संदर्भ दे सकते हैं?
वरफोंडेल

@Vroomfondel - तुम सही हो। मैं C # का उपयोग कर रहा हूं, और प्रत्येक लेयर में कोड को लपेटने के try{ ... } catch(Exception ex) { Log(ex); }परिणामस्वरूप प्रत्येक लेयर पर एक ही अपवाद लॉग किया जाएगा। (यह भी लगता है कि कोड बेस में हर परत पर हर अपवाद को पकड़ने के बजाय बुरा अभ्यास।)
किडकोड

जवाबों:


18

आपके प्रश्नों के लिए:

सबसे आसान समाधान शीर्ष स्तर पर लॉगिंग को लागू करना होगा

शीर्ष स्तर तक अपवाद बुलबुले का होना बिल्कुल सही और प्रशंसनीय दृष्टिकोण है। उच्च परत विधियों में से कोई भी विफलता के बाद कुछ प्रक्रिया को जारी रखने की कोशिश करती है, जो आमतौर पर सफल नहीं हो सकती है। और एक अच्छी तरह से सुसज्जित अपवाद में लॉगिंग के लिए आवश्यक सभी जानकारी शामिल है। और अपवादों के बारे में कुछ नहीं करने से आपको अपने कोड को साफ रखने में मदद मिलती है और विफलताओं के बजाय मुख्य कार्य पर ध्यान केंद्रित किया जाता है।

इसका स्रोत पर अपवाद लॉगिंग स्पष्ट रूप से सबसे अच्छा समाधान है क्योंकि मेरे पास सबसे अधिक जानकारी है।

वह आधा सही है। हां, सबसे उपयोगी जानकारी वहां उपलब्ध है। लेकिन मैं तुरंत इसे लॉग करने के बजाय अपवाद वस्तु (यदि यह पहले से ही नहीं है) में यह सब डालने की सलाह दूंगा। यदि आप निम्न स्तर पर लॉग इन करते हैं, तो आपको अपने कॉलर्स को यह बताने के लिए एक अपवाद फेंकने की आवश्यकता है कि आपने अपना काम पूरा नहीं किया है। यह एक ही घटना के कई लॉग में समाप्त होता है।

अपवाद

मेरा मुख्य दिशानिर्देश केवल शीर्ष स्तर पर अपवादों को पकड़ना और लॉग करना है। और नीचे सभी परतों को सुनिश्चित करना चाहिए कि सभी आवश्यक विफलता की जानकारी शीर्ष स्तर तक पहुंचाई जाए। जावा में एकल-प्रक्रिया वाले अनुप्रयोग के भीतर, इसका अर्थ है कि शीर्ष स्तर के बाहर सभी पर कोशिश करना / पकड़ना या लॉग इन न करना।

कभी-कभी, आप अपवाद लॉग में शामिल कुछ संदर्भ जानकारी चाहते हैं जो मूल अपवाद में उपलब्ध नहीं है, उदाहरण के लिए SQL कथन और पैरामीटर जो अपवाद को फेंक दिए जाने पर निष्पादित किए गए थे। फिर आप मूल अपवाद को पकड़ सकते हैं और एक नया फेंक सकते हैं, जिसमें मूल एक प्लस संदर्भ होगा।

बेशक, वास्तविक जीवन कभी-कभी हस्तक्षेप करता है:

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

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

लॉगिंग

मैं सामान्य रूप से केवल अपवाद-लॉगिंग के बारे में कुछ वाक्य जोड़ रहा हूं।

असाधारण स्थितियों के अलावा, आप अपने आवेदन की महत्वपूर्ण गतिविधियों को लॉग में दर्ज करना चाहते हैं। तो, एक लॉगिंग फ्रेमवर्क का उपयोग करें।

लॉग स्तर के बारे में सावधान रहें (लॉग्स पढ़ना जहां डिबग जानकारी और गंभीर त्रुटियों को अलग-अलग चिह्नित नहीं किया गया है तदनुसार एक दर्द है!)। विशिष्ट लॉग स्तर हैं:

  • त्रुटि: कुछ फ़ंक्शन अपरिवर्तनीय रूप से विफल हो गए। इसका मतलब यह नहीं है कि आपका पूरा कार्यक्रम दुर्घटनाग्रस्त हो गया, लेकिन कुछ काम पूरा नहीं हो सका। आमतौर पर, आपके पास विफलता का वर्णन करने वाली एक अपवाद वस्तु है।
  • चेतावनी: कुछ अजीब हुआ, लेकिन किसी भी कार्य को विफल करने का कारण नहीं बना (अजीब कॉन्फ़िगरेशन का पता चला, अस्थायी कनेक्शन टूटने के कारण कुछ रिट्रीट आदि)
  • जानकारी: आप स्थानीय सिस्टम व्यवस्थापक (इसके कॉन्फ़िगरेशन और सॉफ़्टवेयर संस्करण के साथ कुछ सेवा शुरू करने, डेटाबेस में डेटा फ़ाइलों को आयात करने, उपयोगकर्ताओं को सिस्टम में प्रवेश करने, आपको यह विचार मिलता है ...) के लिए कुछ महत्वपूर्ण प्रोग्राम एक्शन संवाद करना चाहते हैं।
  • DEBUG: डेवलपर के रूप में चीजें जो आप देखना चाहते हैं जब आप किसी मुद्दे पर डिबगिंग कर रहे हैं (लेकिन आप कभी भी पहले से नहीं जान पाएंगे कि इस या उस विशिष्ट बग के मामले में आपको वास्तव में क्या चाहिए - यदि आप इसे दूर कर सकते हैं, तो आप बग को ठीक कर देंगे। )। एक चीज जो हमेशा उपयोगी होती है वह है बाहरी इंटरफेस पर गतिविधियों को लॉग करना।

उत्पादन में, लॉग स्तर को INFO में सेट करें। परिणाम सिस्टम प्रशासक के लिए उपयोगी होने चाहिए, ताकि वह जान सके कि क्या हो रहा है। उम्मीद करें कि आपको लॉग इन और वार्निंग के हर ERROR के लिए सहायता या बग-फिक्सिंग के लिए कॉल करना होगा।

वास्तविक डिबगिंग सत्र के दौरान ही DEBUG स्तर सक्षम करें।

लॉग प्रविष्टियों को उचित श्रेणियों में वर्गीकृत करें (जैसे कि कोड उत्पन्न करने वाले कोड के पूरी तरह से योग्य वर्गनाम द्वारा), आपको अपने कार्यक्रम के विशिष्ट भागों के लिए डिबग लॉग पर स्विच करने की अनुमति देता है।


इस तरह के एक विस्तृत जवाब के लिए धन्यवाद, मैं वास्तव में लॉगिंग भाग की भी सराहना करता हूं।
किडकोड

-1

मैं खुद को डाउनवोट्स के लिए तैयार कर रहा हूं, लेकिन मैं एक अंग पर जा रहा हूं और कहता हूं कि मुझे यकीन नहीं है कि मैं इससे सहमत हो सकता हूं।

बबलिंग अप अपवाद, बहुत कम उन्हें फिर से लॉगिंग, कम लाभ के साथ अतिरिक्त प्रयास है। स्रोत पर अपवाद को पकड़ो (हाँ, सबसे आसान), इसे लॉग इन करें, लेकिन फिर अपवाद को फिर से न फेंकें, बस कॉलर को "त्रुटि" रिपोर्ट करें। "-1", शून्य, खाली स्ट्रिंग, कुछ एनम, जो भी हो। कॉल करने वाले को केवल यह जानना होगा कि कॉल विफल हो गया, लगभग कभी भी भीषण विवरण नहीं मिला। और वे लोग आपके लॉग में होंगे, है ना? दुर्लभ मामले में कि कॉल करने वाले को विवरण की आवश्यकता होती है, आगे बढ़ें और बबल अप करें, लेकिन स्वचालित अनथेकिंग डिफ़ॉल्ट के रूप में नहीं।


3
रिटर्न मानों द्वारा त्रुटि की रिपोर्ट करने में समस्या यह है: 1. यदि कॉलर विफलताओं की परवाह करता है तो उसे विशेष मूल्य की जांच करनी होगी। लेकिन रुकिए, क्या यह nullया खाली स्ट्रिंग है? क्या यह -1 या कोई नकारात्मक संख्या है? 2. यदि कॉलर परवाह नहीं करता है (यानी जांच नहीं करता है) तो यह मूल कारण से संबंधित त्रुटियों का पालन करने के लिए होता है, उदाहरण के लिए NullPointerException। या इससे भी बदतर: गणना गलत मूल्यों के साथ जारी है। 3. यदि कॉल करने वाले की देखभाल होगी लेकिन प्रोग्रामर इस तरीके को विफल नहीं मानता है, तो कंपाइलर उसे याद नहीं दिलाता है। अपवादों में यह समस्याएँ नहीं हैं, या तो आप पकड़ते हैं या आप पुनर्विचार करते हैं।
सीगी

1
क्षमा करें, मुझे इसे कम करना पड़ा। आप जिस दृष्टिकोण का वर्णन करते हैं (विशेष रिटर्न मूल्यों के साथ अपवादों को प्रतिस्थापित करें) 1970 के दशक में अत्याधुनिक था, जब सी भाषा की उत्पत्ति हुई थी, और कई अच्छे कारण हैं कि आधुनिक भाषाओं में अपवाद क्यों हैं, और मेरे लिए मुख्य है अपवादों का ठीक से उपयोग करने से मजबूत कोड लिखना बहुत आसान हो जाता है। और आपके "बुदबुदाने वाले अपवाद [...] अतिरिक्त प्रयास हैं [...]" स्पष्ट रूप से गलत है: बस अपवादों के बारे में कुछ नहीं करते हैं, और वे सभी को खुद से बुदबुदाएंगे।
राल्फ क्लेरॉफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.