आप आमतौर पर लॉग एंट्री कैसे टैग करते हैं? (एंड्रॉयड)


96

मुझे लगता है कि आप में से अधिकांश लोग android.util के बारे में जानते हैं। सभी लॉगिंग विधियाँ पहले तर्क के रूप में 'स्ट्रिंग टैग' को स्वीकार करती हैं।

और मेरा सवाल यह है कि आप आमतौर पर अपने अनुप्रयोगों में अपने लॉग को कैसे टैग करते हैं? मैंने इस तरह से कुछ हार्डकोड देखा है:

public class MyActivity extends Activity {
    private static final String TAG = "MyActivity";
    //...
    public void method () {
        //...
        Log.d(TAG, "Some logging");
    }
}

यह कई कारणों से अच्छा नहीं लगता है:

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

क्या क्लास के लिए TAG पाने का कोई साफ तरीका है?


2
TAG का उपयोग Android javadoc द्वारा सुझाया गया है , इसलिए मुझे नहीं लगता कि यह रनटाइम पर वर्ग नाम पाने से भी बदतर है
व्लादिमीर

मैं GeneralConstants की तरह एक विशिष्ट वर्ग बनाना पसंद करता हूं और उस पर अपना TAG लगाता हूं और मैं अपने टैग किसी भी वर्ग तक पहुंचा सकता हूं जो मैं चाहता हूं; GeneralConstans.MY_TAG
cagryInside

6
मुझे लगता है कि टीएजी को कक्षा में परिभाषित करना सबसे अच्छा है, क्लास का नाम हार्डकोडिंग बदसूरत है, लेकिन गार्ड के साथ काम करने का एकमात्र विश्वसनीय तरीका है। यदि आप कभी भी पहरेदारी नहीं करते हैं तो MyActivity.class.getName () सबसे अच्छा समाधान है। यदि आप डुप्लिकेट नामों से चिंतित हैं तो पैकेज नाम शामिल करें। एक अलग स्थान पर TAG नाम रखने से एक रखरखाव दुःस्वप्न बन जाएगा।
राल्फ मुलर

जवाबों:


179

मैं एक TAG का उपयोग करता हूं, लेकिन मैं इसे इस तरह शुरू करता हूं:

private static final String TAG = MyActivity.class.getName();

इस तरह जब मैं अपना कोड रीफैक्टर करता हूं तो टैग भी उसी के अनुसार बदल जाएगा।


21
मैं इसी तरह से TAG स्थिरांक को परिभाषित कर रहा हूं। हालाँकि, मैं सोच रहा हूँ कि कोड स्थापन उपकरण मेरे वर्ग के नाम को कैसे प्रभावित करेंगे और परिणामस्वरूप इस स्थिरांक का मूल्य?
गुरमीत

1
यह सब समय मैं मैन्युअल रूप से चिपकाया है "MyActivity.class.getName();"। मैंने हमेशा सोचा है कि "TAG" Google आदि के उदाहरणों में सिर्फ एक प्लेसहोल्डर था ... वास्तविक Staticचर नहीं! यह एक बेहतर समाधान है धन्यवाद :)
वायर्ड 00

4
स्थैतिक को हटाने के this.getClass().getName()बजाय इसे अधिक सामान्य बनाने के लिए उपयोग क्यों न करें ?
दिबांग

11
आप TAG पर लंबाई सीमाओं से बचने के लिए इस .getClass (। GetSimpleName) को आज़माना चाहते हैं। IllegalArgumentException को फेंक दिया जाता है अगर tag.length ()> 23.
माइकल लेवी

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

16

मैं आमतौर पर एक Appवर्ग बनाता हूं जो एक अलग पैकेज में बैठता है और इसमें उपयोगी स्थिर विधियां हैं। एक विधि एक getTag()विधि है, इस तरह मैं हर जगह टीएजी प्राप्त कर सकता हूं।
Appवर्ग इस तरह दिखता है:

संपादित करें : प्रति br भीड़ टिप्पणी में सुधार (धन्यवाद :))

public class App {

    public static String getTag() {
        String tag = "";
        final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
        for (int i = 0; i < ste.length; i++) {
            if (ste[i].getMethodName().equals("getTag")) {
                tag = "("+ste[i + 1].getFileName() + ":" + ste[i + 1].getLineNumber()+")";
            }
        }
        return tag;
    }

}

और जब मैं इसका उपयोग करना चाहता हूं:

Log.i(App.getTag(), "Your message here");

getTagविधि का आउटपुट कॉलर वर्ग (पैकेज नाम के साथ) का नाम है, और लाइन नंबर जहां हैgetTag से कॉल किया जाता है, आसान डीबगिंग के लिए।


6
मैं निश्चित रूप से ऐसा नहीं करूंगा .. अगर आप करते हैं तो आपका लॉग स्टेटमेंट एक बड़ा प्रदर्शन करने वाला है। यदि आप ऐसा करते हैं, तो आप निश्चित रूप से प्रोडक्शन बिल्ड पर चेतावनी से कम किसी भी चीज के लिए लॉग संदेश को हटा देना चाहते हैं।
मैट वोल्फ

1
मैट, आप बिल्कुल सही कह रहे हैं! उत्पादन पर स्ट्रीप लॉग को हटाने के लिए यह एक अच्छा अभ्यास है - stackoverflow.com/a/2019563/2270166
यानिव

2
यह शायद अब अनुशंसित नहीं है क्योंकि टैग की लंबाई अब 23 वर्णों तक सीमित है
क्लाउडियो Redi

मुझे दिखाने के लिए धन्यवाद कि कैसे getStackTrace()काम करता है। लेकिन मैं इसका इस्तेमाल नहीं करेगा क्योंकि इसका महंगा
करूंगा ब्लूव्हेल

12

Android Studio पर जाएं -> वरीयता -> लाइव टेम्पलेट -> AndroidLog तब Log.d (TAG, String) चुनें

में खाका पाठ की जगह

android.util.Log.d(TAG, "$METHOD_NAME$: $content$");

साथ में

android.util.Log.d("$className$", "$METHOD_NAME$: $content$");

Android मेनू की छवि

तब दबायें एडिट वेरिएबल्स पर करें और क्लासनेम नाम कॉलम के बगल में एक्सप्रेशन कॉलम में क्लासनेम () दर्ज करें।Android मेनू 2 की छवि

अब जब आप शॉर्टकट टाइप logdकरेंगे तो यह डाल देगा

Log.d("CurrentClassName", "currentMethodName: ");

अब आपको TAG परिभाषित करने की आवश्यकता नहीं है।


1
यह एंड्रॉइड स्टूडियो का वास्तव में अच्छा उपयोग है और समस्या के लिए एक दिलचस्प दृष्टिकोण है, हालांकि एक ही समय में आप वास्तव में टीएजी चर के स्थान पर स्ट्रिंग कर रहे हैं, जिसका अर्थ है कि इसे बदलने के लिए आवश्यक होने पर थोड़ा बोझिल हो सकता है, है ना? हालांकि कार्यक्षमता दिखाने के लिए +1, धन्यवाद!
वॉयस

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

9

अगर आप इस प्रारूप में लॉग (फ़ाइल नाम। Java:XX) xx लाइन नंबर है, तो आप शॉर्टकट को उसी तरह लिंक कर सकते हैं जैसे कि कोई त्रुटि होने पर लिंक हो जाता है, मुझे इसमें सुधार करना पसंद है, इस तरह से मैं प्रश्न में लाइन पर सीधे जा सकता हूं बस logcat पर क्लिक करके

मैंने इसे अपने विस्तारित एप्लिकेशन के अंदर रखा है ताकि मैं हर दूसरी फ़ाइल में उपयोग कर सकूं

public static String getTag() {
    String tag = "";
    final StackTraceElement[] ste = Thread.currentThread().getStackTrace();
    for (int i = 0; i < ste.length; i++) {
        if (ste[i].getMethodName().equals("getTag")) {
            tag = "("+ste[i + 1].getFileName() + ":" + ste[i + 1].getLineNumber()+")";
        }
    }
    return tag;
}

स्क्रीनशॉट:


इसे प्यार करना, इसे "चोरी करना" और मेरे जवाब को अपडेट करना :)
यानिव

4
यह शायद अब अनुशंसित नहीं है क्योंकि टैग लंबाई अब 23 वर्णों तक सीमित है
क्लाउडियो रेडी

3

AndroidStudio में logtडिफ़ॉल्ट रूप से एक टेम्प्लेट होता है (आप logtटैब को टाइप कर सकते हैं और इसे कोड के एक साइनपेट तक विस्तारित कर सकते हैं)। मैं टीएजी परिभाषा को किसी अन्य वर्ग से चिपकाने से बचने के लिए इसका उपयोग करने की सलाह देता हूं और उस वर्ग को बदलने के लिए भूल जाता हूं जिसे आप संदर्भित कर रहे हैं। टेम्पलेट डिफ़ॉल्ट रूप से फैलता है

private static final String TAG = "$CLASS_NAME$"

पुराने वर्ग के नाम का उपयोग करने से बचने के बाद आप इसे बदल सकते हैं

private static final String TAG = $CLASS_NAME$.class.getSimpleName();

"एडिट वेरिएबल्स" बटन को चेक करना याद रखें और सुनिश्चित करें कि एक्सप्रेशन CLASS_NAMEका उपयोग करने के लिए वैरिएबल को परिभाषित किया गया है className()और "स्किप इफ डिफाइंड" चेक किया गया है।


2

मैंने स्टैटिक वैरिएबल, विधियों और वर्गों के नाम से एक वर्ग बनाया है S

निम्नलिखित लॉगिंग विधि है:

public static void L(Context ctx, Object s) {
    Log.d("CCC " + ctx.getClass().getName().replace(ctx.getPackageName(), ""), s.toString());
}

इसे किसी भी वर्ग में S.L(this, whaterver_object);The के रूप में कहा जाता हैgetClass().getName() भी पैकेज का नाम जोड़ देती है, इसलिए, मैं इसे बाहर को हटाने हूँ अनावश्यक रूप से लंबे समय से टैग करने से बचने के।

लाभ:

  1. उससे छोटा Log.d(TAG,
  2. इंट्री वैल्यू को उनके स्ट्रिंग में बदलने की आवश्यकता नहीं है। वास्तव में टाइप करने की आवश्यकता नहीं हैtoString
  3. हटाना मत भूलना Log.dकभी भी क्योंकि मुझे अभी विधि को हटाना है और सभी लॉग के स्थानों को लाल रंग से चिह्नित करना है।
  4. गतिविधि के शीर्ष पर TAG को परिभाषित करने की आवश्यकता नहीं है क्योंकि यह कक्षा का नाम लेता है।
  5. TAG में एक उपसर्ग है CCC(छोटा, टाइप करने के लिए आसान) ताकि एंड्रॉइड स्टूडियो में एंड्रॉइड मॉनिटर में केवल आपके लॉग को सूचीबद्ध करना आसान हो। कभी-कभी आप सेवाओं या अन्य वर्गों को एक साथ चला रहे हैं। यदि आपको अकेले गतिविधि नाम से खोजना है, तो आप ठीक से नहीं देख सकते हैं कि एक सेवा प्रतिक्रिया कब प्राप्त हुई और फिर आपकी गतिविधि से एक कार्रवाई हुई है। CCC जैसा उपसर्ग मदद करता है क्योंकि यह आपको उस गतिविधि के साथ कालानुक्रमिक रूप से लॉग करता है जिसमें यह हुआ था

1
महान समाधान! में इसे इस्तेमाल करता हूँ! लेकिन मैं प्रतिस्थापित Context ctxद्वारा Object ctxऔर ctx.getClass().getName().replace(ctx.getPackageName(), "")द्वारा ctx.getClass().getSimpleName()। इस तरह, मैं S.L(Object, Object)कहीं भी कॉल कर सकता हूं ( Fragmentएस में शामिल हैं जो Contextतत्काल के लिए विस्तार नहीं करते हैं )।
एंटोनियो विनीसियस मेनेजेस मेडेई ऑग

1

आप this.toString()उस विशिष्ट वर्ग के लिए एक विशिष्ट पहचानकर्ता का उपयोग कर सकते हैं जिसमें आप लॉग में प्रिंट करते हैं।


यह क्या toString()करता है पर निर्भर करता है महंगा हो सकता है।
टार

1

इन स्ट्रिंग्स को अपडेट करने की कीमत पर जब मैं तरीकों या नाम बदलने के तरीकों के बीच कोड ले जाता हूं, तो मुझे निम्नलिखित करना पसंद है। दार्शनिक रूप से भी टैग में "स्थान" या "संदर्भ" रखना बेहतर प्रतीत होता है, संदेश नहीं।

public class MyClass {

    // note this is ALWAYS private...subclasses should define their own
    private static final LOG_TAG = MyClass.class.getName();

    public void f() {
        Log.i(LOG_TAG + ".f", "Merry Christmas!");
    }

}

यहां लाभ यह है कि आप किसी एकल विधि को फ़िल्टर कर सकते हैं, भले ही सामग्री स्थिर न हो, उदा

Log.i(LOG_TAG + ".f", String.valueOf(new Random().nextInt()));

केवल दोष यह है कि जब मैं नाम बदलने है f()करने के लिएg() मेरे मन में है कि स्ट्रिंग रखने की जरूरत है। इसके अलावा, स्वचालित आईडीई रीफैक्टरिंग इन्हें पकड़ नहीं पाएगा।

थोड़ी देर के लिए मैं शॉर्ट क्लास नाम का उपयोग करने का प्रशंसक था, मेरा मतलब है LOG_TAG = MyClass.class.getSimpleName()। मैंने उन्हें लॉग में फ़िल्टर करना कठिन पाया क्योंकि वहाँ जाना कम था।


1

यह एक बहुत पुराना प्रश्न है, लेकिन यहां तक ​​कि जुलाई 2018 के लिए एक अद्यतन उत्तर के बारे में सोचा कि टिम्बर का उपयोग करना अधिक बेहतर है। सही लॉगिंग में प्रवेश करने के लिए, त्रुटियों और चेतावनियों को थर्ड पार्टी क्रैश लाइब्रेरी, जैसे कि फायरबेस या क्रैशलाइट्स को भेजा जा सकता है।

अनुप्रयोग को लागू करने वाले वर्ग में आपको इसे जोड़ना चाहिए:

@Override
public void onCreate() {
    super.onCreate();
    if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    } else {
        Timber.plant(new CrashReportingTree());
    }
}

/** A tree which logs important information for crash reporting. */
private static class CrashReportingTree extends Timber.Tree {
    @Override protected void log(int priority, String tag, String message, Throwable t) {
        if (priority == Log.VERBOSE || priority == Log.DEBUG) {
            return;
        }

        FakeCrashLibrary.log(priority, tag, message);

        if (t != null) {
            if (priority == Log.ERROR) {
                FakeCrashLibrary.logError(t);
            } else if (priority == Log.WARN) {
                FakeCrashLibrary.logWarning(t);
            }
        }
    }
}

टिंबर निर्भरता को मत भूलना।

implementation 'com.jakewharton.timber:timber:4.7.1'

0

उन उपयोगकर्ताओं के लिए जो इस प्रश्न पर जाते हैं:

private val TAG:String = this.javaClass.simpleName;

0

वे डिबग जानकारी दिखाने के लिए IOsched app 2019 के लिए टिम्बर का उपयोग करते हैं:

implementation 'com.jakewharton.timber:timber:4.7.1'

class ApplicationController: Application() {

override fun onCreate() {  
    super.onCreate()
    if(BuildConfig.DEBUG){
        Timber.plant(Timber.DebugTree())
    }
}   
// enables logs for every activity and service of the application
// needs to be registered in manifest like:  
 <application
    android:label="@string/app_name"
    android:name=".ApplicationController"
    ... >

प्रयोग

  Timber.e("Error Message") 
  // will print ->  D/MainActivity: Error Message

  Timber.d("Debug Message");
  Timber.tag("new tag").e("error message");

ध्यान दें कि यह लॉग केवल DEBUG राज्य के दौरान उपलब्ध कराता है और आपको Google Play पर लॉन्च के लिए मैन्युअल रूप से उन्हें हटाने के कार्य की सुविधा देता है -

जब ऐप को प्ले स्टोर पर रिलीज़ किया जाता है, तो हमें ऐप से सभी लॉग स्टेटमेंट को हटाने की आवश्यकता होती है, ताकि कोई भी एप्लिकेशन डेटा जैसे उपयोगकर्ता की जानकारी, छिपा हुआ एप्लिकेशन डेटा, ऑरल-टोकन लॉग-इन में सादे पाठ के रूप में उपयोगकर्ता के लिए उपलब्ध न हो

इस लेख की जाँच करें https://medium.com/mindorks/better-logging-in-android-using-timber-72e40cc2293d


-2

मैं आमतौर पर विधि नाम का उपयोग टैग के रूप में करता हूं, लेकिन थ्रेड से

String TAG = Thread.currentThread().getStackTrace()[1].getMethodName();

यह नए अपवाद से बचा जाता है।


-9
private static final String TAG = new RuntimeException().getStackTrace()[0].getClassName();

3
आप RuntimeExceptionवर्तमान वर्ग का नाम पाने के लिए नया ही क्यों बनायेंगे? बहुत बुरा।
asgs

यह है कि मैं अपनी लॉग प्रविष्टियों को कैसे टैग करता हूं, यह एकमात्र समाधान है जिसे मैं किसी प्रोजेक्ट से दूसरे वर्ग में कॉपी करते समय ठीक से रिफ्लेक्टर कर सकता हूं, तो क्यों नहीं। यदि आपके पास बेहतर और अधिक आरामदायक विचार हैं, तो मैं सुझावों के लिए खुला हूं।
अराइज

1
यदि आप जावा क्लास की फाइलों को एक स्थान से दूसरे स्थान पर कॉपी कर रहे हैं, तो बिना किसी नाम बदले, @incpi द्वारा प्रदान किया गया समाधान वह है जो आवश्यक है। अन्यथा, आप बस कर सकता है this.getClass().getName(), हालांकि आप के स्थिर गुंजाइश को दूर करने के लिए होता हैTAG
asgs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.