ฉันจะเปิด / ปิดการใช้งานระดับการบันทึกใน Android ได้อย่างไร


149

ฉันมีคำสั่งการบันทึกจำนวนมากเพื่อตรวจแก้จุดบกพร่องตัวอย่างเช่น

Log.v(TAG, "Message here");
Log.w(TAG, " WARNING HERE");

ในขณะที่ปรับใช้แอปพลิเคชันนี้บนโทรศัพท์อุปกรณ์ฉันต้องการปิดการบันทึก verbose จากที่ฉันสามารถเปิด / ปิดการใช้งานการบันทึก


คำตอบ:


80

วิธีทั่วไปคือการสร้าง loglevel แบบ int และกำหนดระดับการดีบักตาม loglevel

public static int LOGLEVEL = 2;
public static boolean ERROR = LOGLEVEL > 0;
public static boolean WARN = LOGLEVEL > 1;
...
public static boolean VERBOSE = LOGLEVEL > 4;

    if (VERBOSE) Log.v(TAG, "Message here"); // Won't be shown
    if (WARN) Log.w(TAG, "WARNING HERE");    // Still goes through

หลังจากนั้นคุณสามารถเปลี่ยน LOGLEVEL สำหรับระดับผลลัพธ์การดีบักทั้งหมด


1
ดี แต่คุณจะปิดการใช้งาน DEBUG ในตัวอย่างของคุณได้อย่างไร แต่ยังคงแสดงคำเตือน ....
Andre Bossard

1
คำสั่ง if จะไม่จบลงด้วยรหัส. apk หรือไม่ ฉันคิดว่าเราต้องการ (โดยทั่วไป) ปิดการบันทึกเมื่อมีการปรับใช้แอปพลิเคชัน แต่คำสั่ง if จะไม่ถูกลบ
chessofnerd

2
ในตัวอย่างของคุณข้อความ DEBUG จะปรากฏขึ้นในขณะที่ WARN จะไม่แสดง ปกติคุณจะไม่ต้องการตรงกันข้าม
Sam

15
ใช้ BuildConfig.DEBUG แทนตัวแปรที่กำหนดเอง
hB0

1
@chessofnerd "ใน Java โค้ดใน if จะไม่ได้เป็นส่วนหนึ่งของรหัสที่คอมไพล์มันจะต้องคอมไพล์ แต่มันจะไม่ถูกเขียนไปยัง bytecode ที่คอมไพล์แล้ว" stackoverflow.com/questions/7122723/…
stoooops

197

เอกสาร Android กล่าวว่าต่อไปนี้เกี่ยวกับระดับการเข้าสู่ระบบ :

ไม่ควรรวบรวมข้อมูล verbose ลงในแอปพลิเคชันยกเว้นในระหว่างการพัฒนา บันทึกการดีบักจะถูกคอมไพล์ แต่ถูกตัดออกตอนรันไทม์ บันทึกข้อผิดพลาดคำเตือนและข้อมูลจะถูกเก็บไว้เสมอ

ดังนั้นคุณอาจต้องการที่จะต้องพิจารณาปอกบันทึกการบันทึกรายละเอียดงบออกอาจใช้ ProGuard ตามที่แนะนำในคำตอบอื่น

ตามเอกสารคุณสามารถกำหนดค่าการบันทึกบนอุปกรณ์การพัฒนาโดยใช้คุณสมบัติระบบ คุณสมบัติการเป็นชุดlog.tag.<YourTag>และมันควรจะตั้งค่าใดค่าหนึ่งต่อไปนี้: VERBOSE, DEBUG, INFO, WARN, ERROR, หรือ ASSERT ข้อมูลเพิ่มเติมเกี่ยวกับสิ่งนี้มีอยู่ในเอกสารประกอบสำหรับวิธีการSUPPRESSisLoggable()

คุณสามารถตั้งค่าคุณสมบัติชั่วคราวโดยใช้setpropคำสั่ง ตัวอย่างเช่น:

C:\android>adb shell setprop log.tag.MyAppTag WARN
C:\android>adb shell getprop log.tag.MyAppTag
WARN

หรือคุณสามารถระบุได้ในไฟล์ '/data/local.prop' ดังนี้

log.tag.MyAppTag=WARN

รุ่นที่ใหม่กว่า Android ปรากฏว่าจำเป็นต้องให้ /data/local.prop อ่านได้เท่านั้น ไฟล์นี้จะถูกอ่านในเวลาบูตดังนั้นคุณจะต้องรีสตาร์ทหลังจากอัปเดต หาก/data/local.propเป็นโลกที่เขียนได้ก็อาจจะถูกละเว้น

สุดท้ายคุณก็สามารถตั้งค่าให้โปรแกรมโดยใช้วิธีการSystem.setProperty()


4
ฉันมีประสบการณ์แบบเดียวกัน API ของเอกสารนั้นค่อนข้างชัดเจนว่ามันทำงานอย่างไรและดูเหมือนว่าจะพูดถึงandroid.util.Configค่าคงที่ส่วนใหญ่ที่เลิกใช้แล้ว ค่าฮาร์ดโค้ดที่ระบุในเอกสาร API นั้นไม่มีประโยชน์เนื่องจากค่าเหล่านี้ (ตามที่คาดคะเน) จะแตกต่างกันไปตามบิลด์ ดังนั้นเส้นทาง ProGuard จึงเป็นทางออกที่ดีที่สุดสำหรับเรา
Christopher Orr

3
คุณเคยโชคดีไหมในการกำหนดค่าการบันทึก Android โดยใช้ไฟล์ /data/local.prop วิธี setprop หรือด้วย System.setProperty ฉันมีปัญหาเล็กน้อยในการรับ Log.isLoggable (TAG, VERBOSE) เพื่อกลับมาเป็นจริงสำหรับฉัน
seanoshea

2
ฉันได้รับการดีบัก Android แล้ว เคล็ดลับคือเมื่อคุณเรียกบางอย่างเช่น Log.d ("xyz") ข้อความจะถูกเขียนไปยัง logcat แม้ว่าการดีบักจะถูกปิดการใช้งานสำหรับตัวบันทึก ซึ่งหมายความว่าการกรองโดยทั่วไปเกิดขึ้นหลังจากเขียน หากต้องการกรองข้อมูลบางอย่างเช่น Log.isLoggable (TAG, Log.VERBOSE)) {Log.v (TAG "ข้อความบันทึกของฉัน"); } มันจำเป็น. นี่เป็นเรื่องที่ค่อนข้างน่าเบื่อ ฉันใช้ slf4j-android เวอร์ชันดัดแปลงเพื่อรับสิ่งที่ฉันต้องการ
phreed

2
@Dave คุณเคยได้รับวิธี local.prop ทำงานอย่างถูกต้อง ฉันยังไม่สามารถทำงานนี้ได้ฉันได้สร้างรายการ log.tag.test = INFO แล้วลองเปลี่ยนเป็นรัน setprop log.tag.test SUPPRESS จากเชลล์ adb และไม่เปลี่ยนแปลงอะไรเลย การใช้ System.getProperty และ System.setProperty ก็ไม่ได้ทำอะไรเลย ต้องการรับการอัปเดตจากคุณ ขอบคุณ
jjNford

2
+1 สำหรับความคิดเห็น "เอกสาร API ค่อนข้างชัดเจนว่ามันควรทำงานอย่างไร"
อลัน

90

วิธีที่ง่ายที่สุดคือการรัน JAR ที่คอมไพล์ด้วยProGuardก่อนการปรับใช้ด้วยการกำหนดค่าเช่น:

-assumenosideeffects class android.util.Log {
    public static int v(...);
}

นั่นจะ - นอกเหนือจากการเพิ่มประสิทธิภาพ ProGuard อื่น ๆ - ลบคำสั่งบันทึก verbose ใด ๆ โดยตรงจาก bytecode


มันมีไฟล์ log.property ใด ๆ ที่เราสามารถกำหนดการตั้งค่า
d-man

1
การลอกบรรทัดออกโดยใช้ proguard หมายความว่าการติดตามสแต็กของคุณจากการผลิตอาจไม่สอดคล้องกับรหัสของคุณ
larham1

3
@ larham1: ProGuard ทำหน้าที่ใน bytecode ดังนั้นฉันคิดว่าการลบการโทรเพื่อบันทึกจะไม่เปลี่ยนแปลงข้อมูลเมตาของหมายเลขโทรศัพท์ในตัว
Christopher Orr

19
โปรดพิจารณาสิ่งนี้ - แม้ว่าการเรียก Log.v () ที่แท้จริงจะถูกตัดออกอาร์กิวเมนต์จะยังคงได้รับการประเมิน ดังนั้นหากคุณมีวิธีการโทรที่มีราคาแพงเช่น Log.v (TAG, generateLog ()) อาจทำให้ประสิทธิภาพการทำงานของคุณแย่ลงหากอยู่ในเส้นทางรหัสร้อน แม้แต่สิ่งที่ต้องการ toString () หรือ String.format () ก็มีความสำคัญ
Błażej Czapp

4
@GaneshKrishnan ไม่นั่นไม่ใช่เรื่องจริง การเรียก Log.v () ถูกปล้น แต่โดยค่าเริ่มต้นการเรียกเมธอดเพื่อสร้างสตริงจะไม่ถูกลบ ดูคำตอบนี้จากผู้เขียน ProGuard: stackoverflow.com/a/6023505/234938
Christopher Orr

18

ฉันใช้เส้นทางง่ายๆ - การสร้างคลาส wrapper ที่ใช้ประโยชน์จากรายการตัวแปรตัวแปร

 public class Log{
        public static int LEVEL = android.util.Log.WARN;


    static public void d(String tag, String msgFormat, Object...args)
    {
        if (LEVEL<=android.util.Log.DEBUG)
        {
            android.util.Log.d(tag, String.format(msgFormat, args));
        }
    }

    static public void d(String tag, Throwable t, String msgFormat, Object...args)
    {
        if (LEVEL<=android.util.Log.DEBUG)
        {
            android.util.Log.d(tag, String.format(msgFormat, args), t);
        }
    }

    //...other level logging functions snipped

1
อย่างที่ฉันได้กล่าวไปแล้ว ฉันใช้ slf4j-android เวอร์ชันดัดแปลงเพื่อใช้เทคนิคนี้
phreed

3
มีความกังวลอย่างมากเกี่ยวกับเรื่องนี้ดูstackoverflow.com/questions/2446248/…
OneWorld

10

วิธีที่ดีกว่าคือการใช้ SLF4J API + บางส่วนของการใช้งาน

สำหรับแอปพลิเคชัน Android คุณสามารถใช้สิ่งต่อไปนี้:

  1. Android Loggerเป็นการนำ SLF4J ที่มีน้ำหนักเบา แต่ใช้งานง่าย (<50 Kb)
  2. LOGBack เป็นการนำมาใช้ที่มีประสิทธิภาพและปรับให้เหมาะสมที่สุด แต่ขนาดของมันประมาณ 1 Mb
  3. อื่น ๆ ตามรสนิยมของคุณ: slf4j-android, slf4android

2
บน Android คุณต้องใช้logback-android(เนื่องจากlogbackไม่เข้ากัน) logback-android-1.0.10-1.jarคือ 429 KB ซึ่งไม่เลวร้ายนักเมื่อพิจารณาคุณสมบัติที่มีให้ แต่นักพัฒนาส่วนใหญ่จะใช้ Proguard เพื่อปรับแต่งแอปพลิเคชันของตนให้ดีที่สุดอยู่ดี
tony19

นี่ไม่ช่วยให้คุณประหยัดหากใช้คำสั่งเพื่อตรวจสอบระดับการบันทึกก่อนเข้าสู่ระบบ ดูstackoverflow.com/questions/4958860/…
เวิลด์

8

คุณควรใช้

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
        Log.v(TAG, "my log message");
    }

2
วิธีการกำหนดค่าผลลัพธ์ของ isLoggable? debug และ verbose ไม่สามารถล็อกได้เมื่อ isDebugable ถูกตั้งค่าเป็นเท็จในไฟล์ Manifest?
เวิลด์

5

การแยกการบันทึกด้วย proguard (ดูคำตอบจาก @Christopher) นั้นง่ายและรวดเร็ว แต่มันทำให้การติดตามสแต็กจากการผลิตไม่ตรงกันกับแหล่งที่มาหากมีการบันทึกการดีบักในไฟล์

นี่เป็นเทคนิคที่ใช้ระดับการบันทึกที่แตกต่างกันในการพัฒนากับการผลิตโดยสมมติว่า proguard ใช้ในการผลิตเท่านั้น มันรับรู้การผลิตโดยดูว่า proguard เปลี่ยนชื่อคลาสที่กำหนดหรือไม่ (ในตัวอย่างฉันใช้ "com.foo.Bar" - คุณจะแทนที่ด้วยชื่อคลาสที่ผ่านการรับรองซึ่งคุณรู้ว่าจะถูกเปลี่ยนชื่อโดย proguard)

เทคนิคนี้ใช้ประโยชน์จากการบันทึกทั่วไป

private void initLogging() {
    Level level = Level.WARNING;
    try {
        // in production, the shrinker/obfuscator proguard will change the
        // name of this class (and many others) so in development, this
        // class WILL exist as named, and we will have debug level
        Class.forName("com.foo.Bar");
        level = Level.FINE;
    } catch (Throwable t) {
        // no problem, we are in production mode
    }
    Handler[] handlers = Logger.getLogger("").getHandlers();
    for (Handler handler : handlers) {
        Log.d("log init", "handler: " + handler.getClass().getName());
        handler.setLevel(level);
    }
}


3

มีการแทนที่แบบดรอปอินเล็กน้อยสำหรับคลาสบันทึกการทำงานของ android - https://github.com/zserge/log

โดยทั่วไปสิ่งที่คุณต้องทำคือการทดแทนการนำเข้าจากไปandroid.util.Log trikita.log.Logจากนั้นในApplication.onCreate()initalizer ของคุณหรือในบางตรวจสอบคงที่BuilConfig.DEBUGหรือธงอื่น ๆ และใช้Log.level(Log.D)หรือLog.level(Log.E)เปลี่ยนระดับการบันทึกน้อยที่สุด คุณสามารถใช้Log.useLog(false)เพื่อปิดการบันทึกได้เลย


2

อาจจะเป็นคุณสามารถดูนี้เข้าสู่ระดับการขยาย: https://github.com/dbauduin/Android-Tools/tree/master/logs

ช่วยให้คุณสามารถควบคุมการบันทึกได้ดี ตัวอย่างเช่นคุณสามารถปิดการใช้งานบันทึกทั้งหมดหรือเพียงแค่บันทึกของแพคเกจหรือคลาสบางอย่าง

ยิ่งไปกว่านั้นมันเพิ่มฟังก์ชั่นที่มีประโยชน์บางอย่าง (เช่นคุณไม่จำเป็นต้องผ่านแท็กสำหรับแต่ละบันทึก)


2

ฉันสร้าง Utility / Wrapper ซึ่งแก้ปัญหานี้ + ปัญหาทั่วไปอื่น ๆ เกี่ยวกับการบันทึก

ยูทิลิตีการดีบักที่มีคุณสมบัติต่อไปนี้:

  • คุณสมบัติปกติที่มีให้ในคลาส Log ห่อหุ้มโดยLogMode s
  • วิธีการบันทึกการเข้า - ออก: สามารถปิดได้โดยสวิตช์
  • Selective Debugging: Debug คลาสเฉพาะ
  • การวัดเวลาดำเนินการ: วัดเวลาดำเนินการสำหรับแต่ละวิธีรวมถึงเวลารวมที่ใช้กับวิธีการทั้งหมดของชั้นเรียน

วิธีใช้?

  • รวมชั้นเรียนในโครงการของคุณ
  • ใช้เหมือนที่คุณใช้วิธี android.util.Log เพื่อเริ่มต้นด้วย
  • ใช้คุณสมบัติบันทึกการเข้า - ออกโดยการโทรไปยังรายการ entry_log () - exit_log () ที่จุดเริ่มต้นและสิ้นสุดของวิธีการในแอปของคุณ

ฉันได้พยายามที่จะทำให้เอกสารประกอบตัวเองน่าพอใจ

ข้อเสนอแนะเพื่อปรับปรุงยูทิลิตี้นี้ยินดีต้อนรับ

ใช้งาน / แบ่งปันได้ฟรี

ดาวน์โหลดได้จากGitHub


2

นี่คือทางออกที่ซับซ้อนมากขึ้น คุณจะได้รับการติดตามแบบเต็มสแต็กและเมธอด toString () จะถูกเรียกใช้เฉพาะเมื่อจำเป็น (ประสิทธิภาพ) คุณลักษณะ BuildConfig.DEBUG จะเป็นเท็จในโหมดการผลิตดังนั้นบันทึกการติดตามและการดีบักทั้งหมดจะถูกลบออก คอมไพเลอร์ฮอตสปอตมีโอกาสที่จะลบการโทรออกเพราะปิดคุณสมบัติคงที่ขั้นสุดท้าย

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import android.util.Log;

public class Logger {

    public enum Level {
        error, warn, info, debug, trace
    }

    private static final String DEFAULT_TAG = "Project";

    private static final Level CURRENT_LEVEL = BuildConfig.DEBUG ? Level.trace : Level.info;

    private static boolean isEnabled(Level l) {
        return CURRENT_LEVEL.compareTo(l) >= 0;
    }

    static {
        Log.i(DEFAULT_TAG, "log level: " + CURRENT_LEVEL.name());
    }

    private String classname = DEFAULT_TAG;

    public void setClassName(Class<?> c) {
        classname = c.getSimpleName();
    }

    public String getClassname() {
        return classname;
    }

    public boolean isError() {
        return isEnabled(Level.error);
    }

    public boolean isWarn() {
        return isEnabled(Level.warn);
    }

    public boolean isInfo() {
        return isEnabled(Level.info);
    }

    public boolean isDebug() {
        return isEnabled(Level.debug);
    }

    public boolean isTrace() {
        return isEnabled(Level.trace);
    }

    public void error(Object... args) {
        if (isError()) Log.e(buildTag(), build(args));
    }

    public void warn(Object... args) {
        if (isWarn()) Log.w(buildTag(), build(args));
    }

    public void info(Object... args) {
        if (isInfo()) Log.i(buildTag(), build(args));
    }

    public void debug(Object... args) {
        if (isDebug()) Log.d(buildTag(), build(args));
    }

    public void trace(Object... args) {
        if (isTrace()) Log.v(buildTag(), build(args));
    }

    public void error(String msg, Throwable t) {
        if (isError()) error(buildTag(), msg, stackToString(t));
    }

    public void warn(String msg, Throwable t) {
        if (isWarn()) warn(buildTag(), msg, stackToString(t));
    }

    public void info(String msg, Throwable t) {
        if (isInfo()) info(buildTag(), msg, stackToString(t));
    }

    public void debug(String msg, Throwable t) {
        if (isDebug()) debug(buildTag(), msg, stackToString(t));
    }

    public void trace(String msg, Throwable t) {
        if (isTrace()) trace(buildTag(), msg, stackToString(t));
    }

    private String buildTag() {
        String tag ;
        if (BuildConfig.DEBUG) {
            StringBuilder b = new StringBuilder(20);
            b.append(getClassname());

            StackTraceElement stackEntry = Thread.currentThread().getStackTrace()[4];
            if (stackEntry != null) {
                b.append('.');
                b.append(stackEntry.getMethodName());
                b.append(':');
                b.append(stackEntry.getLineNumber());
            }
            tag = b.toString();
        } else {
            tag = DEFAULT_TAG;
        }
    }

    private String build(Object... args) {
        if (args == null) {
            return "null";
        } else {
            StringBuilder b = new StringBuilder(args.length * 10);
            for (Object arg : args) {
                if (arg == null) {
                    b.append("null");
                } else {
                    b.append(arg);
                }
            }
            return b.toString();
        }
    }

    private String stackToString(Throwable t) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(500);
        baos.toString();
        t.printStackTrace(new PrintStream(baos));
        return baos.toString();
    }
}

ใช้แบบนี้:

Loggor log = new Logger();
Map foo = ...
List bar = ...
log.error("Foo:", foo, "bar:", bar);
// bad example (avoid something like this)
// log.error("Foo:" + " foo.toString() + "bar:" + bar); 

1

ในสถานการณ์การบันทึกที่ง่ายมากซึ่งคุณเพียงแค่พยายามเขียนถึงคอนโซลในระหว่างการพัฒนาเพื่อการดีบั๊กมันอาจจะง่ายที่สุดในการค้นหาและแทนที่ก่อนที่การผลิตของคุณจะสร้างและแสดงความคิดเห็นเกี่ยวกับการเรียก Log หรือระบบทั้งหมด out.println

ตัวอย่างเช่นสมมติว่าคุณไม่ได้ใช้ "บันทึก" ที่ใดก็ตามนอกการเรียก Log.d หรือ Log.e ฯลฯ คุณสามารถทำการค้นหาและแทนที่ในโซลูชันทั้งหมดเพื่อแทนที่ "Log" ด้วย "// Log." เพื่อแสดงความคิดเห็นการบันทึกการโทรทั้งหมดของคุณหรือในกรณีของฉันฉันใช้ System.out.println ทุกที่ดังนั้นก่อนที่จะไปผลิตฉันจะทำการค้นหาแบบเต็มและแทนที่ "System.out.println" และแทนที่ด้วย "//System.out.println"

ฉันรู้ว่ามันไม่เหมาะและมันจะดีถ้าความสามารถในการค้นหาและคอมเม้นท์การโทรไปที่ Log และ System.out.println ถูกสร้างขึ้นใน Eclipse แต่จนกระทั่งเกิดขึ้นวิธีที่ง่ายที่สุดและเร็วที่สุดและดีที่สุดในการทำเช่นนี้คือ เพื่อแสดงความคิดเห็นโดยการค้นหาและแทนที่ หากคุณทำเช่นนี้คุณไม่ต้องกังวลเกี่ยวกับหมายเลขบรรทัดการติดตามสแต็กที่ไม่ตรงกันเนื่องจากคุณกำลังแก้ไขซอร์สโค้ดและคุณไม่ได้เพิ่มโอเวอร์เฮดใด ๆ โดยตรวจสอบการกำหนดค่าระดับบันทึก ฯลฯ


1

ในแอพของฉันฉันมีคลาสที่ล้อมคลาส Log ซึ่งมีบูลีน var แบบคงที่เรียกว่า "state" ตลอดรหัสของฉันฉันตรวจสอบค่าของตัวแปร "สถานะ" โดยใช้วิธีการคงที่ก่อนที่จะเขียนลงในบันทึก ฉันมีวิธีการแบบคงที่เพื่อตั้งค่าตัวแปร "สถานะ" ซึ่งรับรองว่าค่านั้นเป็นเรื่องปกติสำหรับทุกกรณีที่สร้างโดยแอป ซึ่งหมายความว่าฉันสามารถเปิดใช้งานหรือปิดใช้งานการบันทึกทั้งหมดสำหรับแอพในการโทรครั้งเดียว - แม้ว่าแอพจะทำงานอยู่ก็ตาม มีประโยชน์สำหรับการโทรติดต่อสนับสนุน ... หมายความว่าคุณต้องติดกับปืนเมื่อทำการดีบั๊กและไม่ต้องใช้คลาสบันทึกมาตรฐาน ...

นอกจากนี้ยังมีประโยชน์ (สะดวก) ที่ Java ตีความบูลีน var เป็นเท็จหากยังไม่ได้รับการกำหนดค่าซึ่งหมายความว่าจะสามารถทิ้งเป็นเท็จได้จนกว่าคุณจะต้องเปิดการบันทึก :-)


1

เราสามารถใช้คลาสLogในส่วนประกอบท้องถิ่นของเราและกำหนดวิธีการเป็น v / i / e / d ตามความต้องการของเราสามารถโทรติดต่อเพิ่มเติมได้
ตัวอย่างที่แสดงด้านล่าง

    public class Log{
        private static boolean TAG = false;
        public static void d(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.d(enable_tag, message+args);
        }
        public static void e(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.e(enable_tag, message+args);
        }
        public static void v(String enable_tag, String message,Object...args){
            if(TAG)
            android.util.Log.v(enable_tag, message+args);
        }
    }
    if we do not need any print(s), at-all make TAG as false for all else 
    remove the check for type of Log (say Log.d).
    as 
    public static void i(String enable_tag, String message,Object...args){
    //      if(TAG)
            android.util.Log.i(enable_tag, message+args);
    }

ข้อความที่นี่มีไว้สำหรับstringและและargsเป็นค่าที่คุณต้องการพิมพ์


0

สำหรับฉันมันมักจะมีประโยชน์ที่จะสามารถตั้งค่าระดับการบันทึกที่แตกต่างกันสำหรับแต่ละแท็ก

ฉันใช้คลาส wrapper ง่าย ๆ นี้:

public class Log2 {

    public enum LogLevels {
        VERBOSE(android.util.Log.VERBOSE), DEBUG(android.util.Log.DEBUG), INFO(android.util.Log.INFO), WARN(
                android.util.Log.WARN), ERROR(android.util.Log.ERROR);

        int level;

        private LogLevels(int logLevel) {
            level = logLevel;
        }

        public int getLevel() {
            return level;
        }
    };

    static private HashMap<String, Integer> logLevels = new HashMap<String, Integer>();

    public static void setLogLevel(String tag, LogLevels level) {
        logLevels.put(tag, level.getLevel());
    }

    public static int v(String tag, String msg) {
        return Log2.v(tag, msg, null);
    }

    public static int v(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.VERBOSE) {
                return -1;
            }
        }
        return Log.v(tag, msg, tr);
    }

    public static int d(String tag, String msg) {
        return Log2.d(tag, msg, null);
    }

    public static int d(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.DEBUG) {
                return -1;
            }
        }
        return Log.d(tag, msg);
    }

    public static int i(String tag, String msg) {
        return Log2.i(tag, msg, null);
    }

    public static int i(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.INFO) {
                return -1;
            }
        }
        return Log.i(tag, msg);
    }

    public static int w(String tag, String msg) {
        return Log2.w(tag, msg, null);
    }

    public static int w(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.WARN) {
                return -1;
            }
        }
        return Log.w(tag, msg, tr);
    }

    public static int e(String tag, String msg) {
        return Log2.e(tag, msg, null);
    }

    public static int e(String tag, String msg, Throwable tr) {
        if (logLevels.containsKey(tag)) {
            if (logLevels.get(tag) > android.util.Log.ERROR) {
                return -1;
            }
        }
        return Log.e(tag, msg, tr);
    }

}

ตอนนี้เพียงแค่ตั้งค่าระดับบันทึกต่อ TAG ที่จุดเริ่มต้นของแต่ละชั้นเรียน:

Log2.setLogLevel(TAG, LogLevels.INFO);

0

อีกวิธีหนึ่งคือการใช้แพลตฟอร์มการบันทึกที่มีความสามารถในการเปิดและปิดการบันทึก สิ่งนี้สามารถให้ความยืดหยุ่นอย่างมากในบางครั้งแม้ในแอปที่ใช้งานจริงซึ่งควรเปิดบันทึกและปิดซึ่งขึ้นอยู่กับปัญหาที่คุณมีตัวอย่างเช่น:

  • คนตัดไม้
  • Shipbook (ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนแพ็คเกจนี้)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.