2012-06-08 15 views
11

मैं जावा के लिए नया हूं और मैं उस त्रुटि स्टैक ट्रेस द्वारा उपयोग किए जाने वाले स्वरूपण नियमों से परिचित नहीं हूं जब इसे फेंक दिया जाता है और बाद में मेरे वेब एप्लिकेशन के अंतिम उपयोगकर्ता को प्रदर्शित किया जाता है।जावा: त्रुटि स्टैक ट्रेस में कौन सी जानकारी हम आम तौर पर उपयोगकर्ताओं को दिखाना नहीं चाहते हैं?

ओरेकल डेटाबेस के साथ मेरा अनुभव यह है कि त्रुटि स्टैक में स्कीमा और प्रक्रिया नाम और लाइन नंबर (जैसे) की आंतरिक जानकारी होती है, जो डिबगिंग के लिए उपयोगी होती है, मैं उपयोगकर्ता को देखने से रोकना चाहता हूं।

java.sql.SQLException : ORA-20011: Error description here 
ORA-07894: at "NAME_OF_SCHEMA.PROCEDURE_NAME", line 121 
ORA-08932: at line 10 

स्ट्रिंग मैं उपयोगकर्ता के लिए प्रदर्शित करना चाहते हैं Error description here है: यहाँ एक उदाहरण है। मैं regex अभिव्यक्तियों का उपयोग करके इस स्ट्रिंग को निकाल सकता हूं क्योंकि मुझे पता है (1) यह स्ट्रिंग हमेशा पहली पंक्ति पर है, इसलिए मैं त्रुटि स्टैक ट्रेस की पहली पंक्ति निकाल सकता हूं, और (2) यह स्ट्रिंग हमेशा Error से शुरू होती है और समाप्त होती है पंक्ति का अंत। [ओरेकल उपयोगकर्ताओं के लिए नोट (मैं आपको गुमराह नहीं करना चाहता): उपर्युक्त केवल Error से शुरू होने वाली त्रुटि स्ट्रिंग के साथ RAISE_APPLICATION_ERROR का उपयोग करते समय लागू होता है, अन्यथा पाठ Error वहां नहीं है]।

जावा के लिए मेरे सवाल कर रहे हैं:

(1) क्या संभावित रूप से संवेदनशील है कि आप उन त्रुटि स्टैक में नहीं देखना चाहते हैं है? यदि ऐसा है तो क्या? उदाहरण के लिए, फ़ाइल पथ, सर्वर नाम/आईपी, आदि

(2) जावा त्रुटि स्टैक ट्रेस के लिए कोई स्वरूपण नियम हैं जो मैं गैर-संवेदनशील जानकारी निकालने के लिए भरोसा कर सकता हूं? या, दूसरों को इस चिंता का समाधान कैसे करें?

अद्यतन 1:

सभी उत्तर के लिए धन्यवाद अब तक, वे बहुत मददगार रहे हैं। जबकि कई लोग उपयोगी उपयोगकर्ता संदेशों में त्रुटियों को मैप करने के लिए getUserFriendlyMessage() जैसे फ़ंक्शन का उपयोग करने के लिए टिप्पणी करते हैं, मुझे आश्चर्य है कि कोई इस मैपिंग पर विस्तार कर सकता है या नहीं। यही है, सामान्य त्रुटियों (एसक्यूएल, आई/ओ, इत्यादि) के लिए, त्रुटि के प्रकार की पहचान करने के लिए इस त्रुटि स्टैक को खोजने के लिए "विश्वसनीय" पहचानकर्ता का उपयोग किया जा सकता है, और फिर आप किस पाठ पाठ की अनुशंसा करेंगे उपयोगकर्ता को दिखाने के लिए इस त्रुटि संदेश को मैप करने के लिए? @ आदर्श की प्रतिक्रिया नीचे एक अच्छी शुरुआत है। उदाहरण के लिए,

Identified Expected If found in error stack, display this friendly msg to user 
------------------- ---------------------------------------------------------- 
SQLException   An error occurred accessing the database. Please contact support at [email protected] 
IOException   Connection error(?). Please check your internet connection. 

मान लें संकलन से संबंधित त्रुटियों को संबोधित करने की जरूरत नहीं है, बल्कि उन त्रुटियों कि अंत उपयोगकर्ताओं सामान्य उपयोग के दौरान अनुभव हो सकता है ध्यान देते हैं। संदर्भ के लिए, यहां रन-टाइम त्रुटि संदेशों की एक सूची दी गई है: http://mindprod.com/jgloss/runerrormessages.html#IOEXCEPTION

वैकल्पिक रूप से, क्या उपयोगकर्ता को प्रदर्शित करने के लिए केवल स्टैक ट्रेस के पहले लाइन का उपयोग करना संभव है? इस कड़ी की तरह है जो मैं ऊपर अपने मूल प्रश्न में पर हो रही थी:

http://www3.ntu.edu.sg/home/ehchua/programming/howto/ErrorMessages.html

उदाहरण के लिए, यदि पहचानकर्ता Exception हमेशा प्रयोग किया जाता है, एक बस पाठ कि Exception और के बीच आने वाली निकाल सकते पहली पंक्ति मुझे नहीं पता कि हम हमेशा Exception पर भरोसा कर सकते हैं या नहीं।

+0

मैंने आपके अपडेट के आधार पर अपना उत्तर अपडेट किया है। –

+0

इस संबंधित प्रश्न को देखें: http://stackoverflow.com/q/7361201/545127 – Raedwald

उत्तर

7

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

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

अद्यतन:

मैं सवाल अद्यतन के आधार पर कुछ टिप्पणी है। सबसे पहले, मैं पूरी तरह से उपयोगकर्ता को और सुरक्षा के लिए दयालु होने के लिए, आपके सिस्टम के किसी भी आंतरिक से उपयोगकर्ता को पूरी तरह से अपनाना चाहता हूं। (उदाहरण के लिए, यहां तक ​​कि यह जानकर कि आप java.sql पैकेज का उपयोग कर रहे हैं, एक चालाक हैकर को भेद्यता का सुझाव दे सकता है।) तो अपवाद संदेश, स्टैक ट्रेस की पहली पंक्ति, या उपयोगकर्ता को कुछ भी प्रदर्शित करते समय ऐसा कुछ भी न करें ।

दूसरा, आपको अपवाद स्तर (जिस पर वे आपके कोड में अनुभव कर रहे हैं) से सभी त्रुटियों को मैप करना चाहिए जो उपयोगकर्ता के लिए अमूर्तता के सही स्तर पर हैं। ऐसा करने का सही तरीका आपके सिस्टम के आंतरिक पर निर्भर करेगा और अपवाद उठाए जाने पर उपयोगकर्ता क्या करने का प्रयास कर रहा था। इसका मतलब यह हो सकता है कि आपके सिस्टम को परतों में संरचित करना जैसे कि प्रत्येक परत जो अपवाद को पकड़ती है उसे अबास्ट्रक्शन की उच्च परत पर अपवाद में अनुवाद करती है। एक जावा अपवाद एक और अपवाद (कारण) लपेट सकता है। उदाहरण के लिए:

public boolean copyFile(File source, File destination) throws CopyException { 
    try { 
     // lots of code 
     return true; 
    } catch (IOException e) { 
     throw new CopyException("File copy failed", e); 
    } 
} 

तो यह एक उपयोगकर्ता कक्षा में एक उच्च स्तर पर इस्तेमाल किया जा सकता:

public boolean shareFile(File source, User otherUser) throws ShareException { 
    if (otherUser.hasBlocked(this) { 
     throw new ShareException("You cannot share with that user."); 
    } 
    try { 
     return copyFile(source, otherUser.getSharedFileDestination(source)); 
    } catch (CopyException e) { 
     throw new ShareException("Sharing failed due to an internal error", e); 
    } 
} 

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

कारण यह है कि आप इस तरह की चीजों को संभालना चाहते हैं (किसी भी तरह से संदेश और/या स्टैक ट्रेस को मालिश करने की बजाय) यह है कि अपवाद (उदाहरण के लिए संदेश के साथ एक IOException " अनुमति अस्वीकृत ") का मतलब विभिन्न संदर्भों में उपयोगकर्ता (और आपके सिस्टम में) के लिए पूरी तरह से अलग चीज़ें हो सकता है।

+0

विवरण टेड के लिए धन्यवाद, वास्तव में इसकी सराहना करें। – ggkmath

1

जब आपका ऐप डीबग मोड में होता है तो आपको केवल स्टैक निशान दिखाना चाहिए। उत्पादन मोड में, आपको एक सामान्य त्रुटि संदेश दिखाना चाहिए (या Exception.getUserFriendlyMessage() लागू करें) और त्रुटि लॉग करें (यदि संभव हो तो लॉग आईडी प्रदान करें)।

1

मैं जिस स्ट्रिंग को उपयोगकर्ता को प्रदर्शित करना चाहता हूं वह Error description here है।

आप इस उद्देश्य के लिए Exception.getMessage() उपयोग कर सकते हैं, हालांकि के रूप में जुआन मेंडेज़ का सुझाव दिया, एक अधिक "उपयोगकर्ता के अनुकूल" त्रुटि संदेश के अंत उपयोगकर्ता के लिए त्रुटियों को प्रदर्शित करने के लिए तंत्र को लागू करने पर विचार करें।

यदि आप नहीं चाहते हैं कि अंतिम उपयोगकर्ता स्टैकट्रैस में आपकी कक्षाओं, विधियों और फ़ील्ड के नामों को देखने के लिए, Proguard जैसे obfuscator का उपयोग करने पर विचार करें। मैं लॉग फ़ाइलों में obfuscated stacktraces मुद्रित करना चाहता हूं, फिर डीबगिंग उद्देश्यों के लिए उन्हें unobfuscate करने के लिए ReTrace का उपयोग करें।

(1) क्या कोई संभावित रूप से संवेदनशील है कि आप नहीं चाहते हैं कि उपयोगकर्ता त्रुटि स्टैक में देखें? यदि ऐसा है तो क्या? उदाहरण के लिए, फ़ाइल पथ, सर्वर नाम/आईपी, आदि

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

+0

मुझे एक तरीका 'getUserFriendlyMessage' करना पसंद है ताकि हम कभी भी कुछ भी तकनीकी नहीं दिखा रहे हैं –

+0

@ जुआनमेन्डेस सहमत हैं, असल में मैं अपने कोड –

+0

@ जुआनमेंडेस में एक समान प्रकार की चीज करता हूं, मुझे नहीं पता कि मैं इससे सहमत हूं या नहीं। यदि विभिन्न अपवादों में एक ही अपवाद फेंक दिया जा सकता है, तो आप प्रति संदर्भ एक अलग त्रुटि संदेश प्रदर्शित करना चाहेंगे। – Michael

5

अंतिम उपयोगकर्ता को अपवाद संदेश/स्टैकट्रैक न दिखाएं। इसके बजाय एक अपवाद - संदेश मैपिंग दृष्टिकोण का प्रयास करें और उपयोग करें।

उदाहरण के लिए:

  • SQLException - क्षमा करें, एक डेटाबेस त्रुटि उत्पन्न हुई। कृपया बाद में पुनः प्रयास करें
  • RuntimeException/Exception - क्षमा करें एक त्रुटि हुई। कृपया बाद में पुनः प्रयास करें

वास्तव में, आप इसे यथासंभव सामान्य बना सकते हैं। शायद आप एक कस्टम त्रुटि कोड मैपिंग का उपयोग कर सकते हैं। उदाहरण के लिए, E0001SQLException, E0000Exception के लिए और इस पर अंतिम उपयोगकर्ता को प्रदर्शित करें और प्रदर्शित करें। यह सहायक होगा जब वे अंततः त्रुटि कोड के साथ ग्राहक सेवा से संपर्क करेंगे।

+0

दिलचस्प। क्या ऐसे कीवर्ड की एक सूची है जो मैं स्टैक ट्रेस में विश्वसनीय रूप से खोज सकता हूं? आपने उपर्युक्त कुछ का उल्लेख किया है (उदा। एसक्यूलेक्सप्शन, रनटाइम अपवाद)। यह बढ़िया होगा यदि आप अपने उत्तर का विस्तार कर सकते हैं ताकि विश्वसनीय कीवर्ड की एक सूची शामिल हो सके जो दिखाई दे सकें, और उचित प्रतिक्रियाएं शामिल हों। मुझे अब तक जो पसंद है वह मुझे पसंद है। – ggkmath

+0

यह वास्तव में आपके आवेदन पर निर्भर करता है। ये कस्टम अपवाद वर्ग भी हो सकते हैं जैसे 'MyRuntimeException' या' NoSuchProductException'। – adarshr

3

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

  • हमारे कार्यक्रम में अस्थायी कठिनाइयों का अनुभव हुआ है। सहायता के लिए कृपया तकनीकी सहायता लाइन पर कॉल करें।

अंतिम उपयोगकर्ता आपके प्रोग्राम के आंतरिक संगठन, डेटाबेस, ढेर, et cetera के बारे में कम परवाह नहीं कर सके। वे सभी जानते हैं कि कुछ ऐसा जो उन्होंने सोचा था, काम करना चाहिए, असफल रहा, इसलिए वे सहायता की तलाश में हैं।

स्टैक निशान त्रुटि लॉग के लिए हैं: आप उन्हें अपने लिए सहेज सकते हैं, या उन्हें तकनीकी सहायता के लिए ईमेल कर सकते हैं, लेकिन आप उन्हें अंतिम उपयोगकर्ताओं को नहीं दिखाना चाहते हैं।

+2

मैं आम तौर पर सहमत हूं, लेकिन मुझे लगता है कि कुछ स्थितियों में यह थोड़ा और जानकारी प्रदान करने में मददगार हो सकता है। उदाहरण के लिए, यदि आपको सर्वर टाइमआउट मिलता है, तो यह केवल उनके नेटवर्क कनेक्शन के साथ एक समस्या हो सकती है, और यदि आप उन्हें वह जानकारी प्रदान करते हैं, तो वे इसे स्वयं ठीक करने में सक्षम हो सकते हैं और समर्थन टिकट खोलना नहीं है –

+1

@ केविन - अधिकांश उपयोगकर्ताओं को यह जानने की आवश्यकता होगी कि समस्या स्थायी है ("यह काम नहीं करता है और यह काम नहीं करेगा"), अस्थायी ("यह काम नहीं करता है, कृपया बाद में पुनः प्रयास करें"), या उपयोगकर्ता द्वारा सुधार योग्य ("कृपया एक टिप्पणी छोड़ने के लिए लॉग इन करें")। उपयोगकर्ता को यह बताते हुए कि यह "नेटवर्क कनेक्शन के साथ एक समस्या" अर्थहीन या बदतर, गैर-तकनीकी उपयोगकर्ताओं को डराता है। कार्यक्रम केवल उन संदेशों को प्रदर्शित करना चाहिए जो लक्षित उपयोगकर्ता के विशेषज्ञता के स्तर के लिए उपयुक्त हैं। (बेशक, डेवलपर्स के लिए एक ऐप में अधिक तकनीकी अनुभव हो सकता है, लेकिन विचार अभी भी वही है।) –

1

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

Exception.getMessage() विधि केवल अपवाद के संदेश को वापस कर देगा, न कि संपूर्ण स्टैक ट्रेस। लेकिन ऐसा लगता है कि आपके द्वारा दिए गए उदाहरण में, दूसरी और तीसरी पंक्तियां अपवाद संदेश का भी हिस्सा हैं, जिससे आपकी मदद नहीं होती है।

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

+0

अच्छा बिंदु। लेकिन अगर Exception.getMessage() रिटर्न में विश्वसनीय कीवर्ड हैं, तो मैं उन लोगों की खोज कर सकता हूं और इस संदेश को और अधिक उपयुक्त के साथ बदल सकता हूं। उपरोक्त मूल पोस्टिंग में मेरा अद्यतन 1 देखें। – ggkmath

1

जैसा कि अन्य ने कहा है, आपको उपयोगकर्ताओं को स्टैक-ट्रेस की रिपोर्ट नहीं करनी चाहिए। कई अन्य लोगों ने सुझाव दिया है कि आप getMessage() टेक्स्ट प्रदर्शित करें। मैं की सिफारिश नहीं करता हूं। I've said before के रूप में:

  • संदेश बनाया गया था जब अपवाद उत्पन्न हुआ था। इसलिए यह सर्वोत्तम रूप से बहुत कम स्तर की जानकारी प्रदान कर सकता है, जो किसी उपयोगकर्ता को रिपोर्ट करने के लिए अनुचित हो सकता है।
  • दार्शनिक रूप से, संदेश का उपयोग करके मुझे अपवादों के पूरे बिंदु के खिलाफ लगता है, जो हैंडलिंग और रिपोर्टिंग (catch भाग) पूरा होने से त्रुटि प्रबंधन (throw भाग) का पता लगाने और दीक्षा को अलग करना है। संदेश का उपयोग करना मतलब है कि संदेश रिपोर्टिंग के लिए अच्छा होना चाहिए, जो उस स्थान पर रिपोर्ट करने की ज़िम्मेदारी लेता है जो केवल पहचान और दीक्षा के लिए ज़िम्मेदार होना चाहिए। यही है, मैं तर्क दूंगा कि Throwable के डिजाइन का हिस्सा एक गलती थी।
  • संदेश स्थानीयकृत नहीं है। इसके नाम के बावजूद, getLocalizedMessage() बहुत अच्छा नहीं है क्योंकि आपको पता नहीं हो सकता कि आप catch अपवाद तक क्या लोकेल का उपयोग करना चाहते हैं (क्या आपके अंग्रेजी सिस्टम प्रशासकों द्वारा पढ़े गए सिस्टम लॉग पर जाने की रिपोर्ट है, या यह एक पॉप अप करने के लिए है जीयूआई के फ्रांसीसी उपयोगकर्ता के लिए खिड़की?)।