[ANDROID] Timber Log : Library ตัวนี้ พี่ไม่ได้มาเล่นๆ


        Timber เป็น Library ที่ใช้ในการ Log ข้อมูล ที่พัฒนาโดยตา JakeWharton เจ้าเก่าของเรานี่เอง โดยจะเขียนครอบอยู่บน Android Log class ที่เราใช้กันประจำนั่นเอง หากนึกภาพไม่ออกก็หน้าตาประมาณนี้ครับ
Log.d("Tag", "This is Log Message.");
        และเนื่องจากการที่เขียนครอบอยู่บน Android Log class ปกตินั้น จึงทำให้ Timber มีการเรียกใช้งานคล้ายๆ กัน ประมาณนี้
Timber.d("This is Log Message.");
        หากลองมองดูดีๆ จะมีสิ่งหนึ่งที่ต่างกัน ... สิ่งนั้นก็ คือ "Tag" ได้หายไปนั่นเอง ซึ่งหนึ่งในข้อดี ของ Timber ก็คือไม่จำเป็นต้องสร้าง Tag เองเพราะ Library จะช่วยสร้าง Tag ให้จากชื่อ Class ที่ Log ถูกเรียกนั่นเอง สะดวกขึ้นเป็นกองเลย ว่ามั้ย? :)

มีอะไรที่ต่างจาก Android Log ธรรมดาอีก ??

        สำหรับ Timber นั้นมีข้อดีอยู่หลายๆ ข้อเลยทีเดียว (ไม่งั้นก็คงไม่คุ้มค่าที่จะใช้งานซักเท่าไร) ว่าแต่จะมีอะไรบ้าง? ลองมาดูภาพรวมกันก่อน
  1. ไม่ต้องสร้าง Tag เอง
  2. จัดการ Log Message ด้วย Formatter ได้เลย
  3. แสดง Log เฉพาะ Debug Mode
  4. สามารถใช้งานร่วมกับ "Crashlytics" ได้

จัดการ Log Message ด้วย Formatter ได้เลย

        ความสามารถนี้ก็ตามหัวข้อเลย คือ สามารถจัด Format ข้อความได้เหมือนเราใช้คำสั่ง String.format() ได้เลย ลองดูตัวอย่างจะเข้าใจง่ายขึ้น
String username = "Pop";
String logger = "Timber";
Timber.i("Hello '%s', This is Log form '%s'", username, logger);

// ผลลัพธ์ คือ Hello 'Pop', This is Log from 'Timber'

แสดง Log เฉพาะ Debug Mode

        โดยปกติ (เท่าที่ผมทราบ) ถ้าไม่ใช้ Library เราก็มักจะเขียน Class ขึ้นมาครอบ Android Log อีกที เป็น class LogUtils อะไรก็ว่ากันไป เพื่อที่จะทำการตรวจสอบว่าอยู่ใน Debug Mode หรือไม่ ตัวอย่างเช่น
public class LogUtils {
    public static void LogD(String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.d("Tag", "This is Log Message.");
        }
    }
    .
    .
    public static void LogE(String tag, String message) {
        if (BuildConfig.DEBUG) {
            Log.e("Tag", "This is Log Message.");
        }
    }
}
        ถามว่าวิธีนี้ผิดไหม? ก็คงตอบว่าไม่ผิดเพราะแต่ละคนอาจจะมีเหตุผลในการใช้งานต่างๆ กันออกไป สำหรับผม Timber ค่อนข้างจะตอบโจทย์ตรงนี้ (ขี้เกียจนั่นเอง)
        ลองมาดูวิธีการ Config กันซักหน่อย ซึ่งวิธีการก็ไม่ได้มีอะไรซับซ้อนเลย เพียงแค่ "เพิ่มคำสั่งลงไปใน Application class" ดังนี้
public class ExampleApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        if (BuildConfig.DEBUG) {
            Timber.plant(new DebugTree());
        }
    }
}
        หลังจาก Config เสร็จ ก็ทำการเรียกใช้งานคำสั่ง Timber ตามได้เลย (เหมือนกับ Android Log ปกติ แต่ไม่ต้องมี Tag) หรือจะไปประยุคต์ใช้กับค่าอื่นๆ ที่ไม่ใช่ BuildConfig ก็ได้นะครับ
Timber.d("Debug Log.");
Timber.i("Info Log.");
.
.
Timber.e("Error Log.");
        ** แต่สำหรับท่านที่คิดว่า Tag ที่ Timber สร้างให้ไม่สวยงามดั่งใจแล้วละก็ ท่านสามารถกำหนด Tag เองได้ ด้วยคำสั่ง
Timber.tag("Tag Nmae");

ยังไม่พอ!! สามารถใช้งานร่วมกับ "Crashlytics" ได้อีกด้วย

        Crashlytics คือหนึ่งในบริการของ Fabric ที่มีหน้าที่ในการเก็บ Crash และ Log ที่เกิดขึ้นบน Application ของเรา ซึ่งจะแจ้งเตือนผ่านทาง Email และหน้าเว็บ (คล้ายๆ CRASHES & ANRS บน Google Play Console) ทั้งนี้ขอแนะนำให้ไปอ่านข้อมูลเพิ่มเติมที่ ทำความรู้จัก Fabric โดยพี่เนย และ Crashlytics - ตรวจสอบ error ที่เกิดบน mobile application โดยคุณ Jarupath

http://techcrunch.com/2011/10/13/crashlytics-a-crash-reporting-solution-for-mobile-developers-raises-1-million/

สำหรับการใช้งาน Crashlytics เบื้องต้น ง่ายๆ เลยก็คือใส่โค้ดต่อไปนี้ใน Application class
Fabric.with(this, new Crashlytics());
หรือหากต้องการให้ Tracking เฉพาะ Production ให้เปลี่ยนเป็นโค้ดนี้แทน
CrashlyticsCore core = new CrashlyticsCore.Builder()
        .disabled(BuildConfig.DEBUG)
        .build();
Fabric.with(this, new Crashlytics.Builder().core(core).build());

        เพียงเท่านี้หากมี Crash เกิดขึ้น Crashlytics ก็จะส่งข้อมูลเข้า Server โดยที่เราสามารถเข้าไปดูข้อมูลได้ผ่านเว็บไซต์ Fabric และถ้าหากต้องการที่จะให้ส่งข้อมูลอื่นๆ ก็สามารถทำได้ด้วยคำสั่ง
// Log caught exceptions
Crashlytics.logException(exception);

// กำหนดค่าที่จะแสดงใน Issue Log ด้วย Key Value ที่ต้องการ
Crashlytics.setInt("key", "value");
Crashlytics.setString("key", "value");
        คำถามที่ตามมา คือ ถ้าต้องการให้แสดง Log และส่งข้อมูลไปยัง Crashlytics ด้วยต้องทำยังไง คำตอบของคำถาม คือ Timber นั่นเอง :D

Timber + Crashlytics

        การใช้งาน Crashlytics ร่วมกับ Timber จะต้องทำการสร้าง Class ที่ extentd Timber.Tree ขึ้นมาเพื่อทำการ Config ค่าต่างๆ ดังนี้
public class CrashlyticsTree extends Timber.Tree {
    private static final String CRASHLYTICS_KEY_PRIORITY = "priority";
    private static final String CRASHLYTICS_KEY_TAG      = "tag";
    private static final String CRASHLYTICS_KEY_MESSAGE  = "message";

    @Override
    protected void log(int priority, @Nullable String tag, @Nullable String message, @Nullable Throwable t) {

        // ยกเว้นการทำงานเมื่อเป็น Log.VERBOSE, Log.DEBUG, Log.INFO
        if (priority == Log.VERBOSE || priority == Log.DEBUG || priority == Log.INFO) {
            return;
        }

        // สั่งให้ Crashlytics ทำการส่งข้อมูล
        Crashlytics.setInt(CRASHLYTICS_KEY_PRIORITY, priority);
        Crashlytics.setString(CRASHLYTICS_KEY_TAG, tag);
        Crashlytics.setString(CRASHLYTICS_KEY_MESSAGE, message);

        if (t == null) {
            Crashlytics.logException(new Exception(message));
        } else {
            Crashlytics.logException(t);
        }
    }
}

สุดท้าย คือ ทำการเรียกใช้งานใน Application class
public class ExampleApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        // เรียกใช้งาน Crashlytics
        CrashlyticsCore core = new CrashlyticsCore.Builder()
            .disabled(BuildConfig.DEBUG)
            .build();
        Fabric.with(this, new Crashlytics.Builder().core(core).build());

        // แสดง Log เฉพาะ Debug Mode
        if (BuildConfig.DEBUG) {
            Timber.plant(new Timber.DebugTree());
        }

        // รวมพลัง Timber กับ Crashlytics เข้าด้วยกัน
        Timber.plant(new CrashlyticsTree());
    }
}

        เมื่อทำการ Config เรียบร้อยแล้ว เมื่อเราเรียกใช้งาน Timber ให้ทำการแสดงผล Log ก็จะเป็นการบอกให้ Crashlytics ส่งข้อมูลไปในตัว ยอดเยี่ยมไปเลยใช่ไหมหละ ヾ(●⌒∇⌒●)ノ
        หลังจากที่ได้เห็นคุณงามความดีของ Timber แล้ว ก็คงเริ่มที่จะอยากเอามาใช้กันแล้วหละสิ แต่ก่อนจะเรียกใช้งานอย่าลืมเพิ่ม Dependency เข้าไปด้วยนะครับ
compile 'com.jakewharton.timber:timber:4.1.1'

***สำหรับ min SDK version ต่ำกว่า 15 เนื่องจาก Timber กำหนด min SDK ไว้ที่ version 15 ทำให้ Project ที่ใช้ต่ำกว่านั้น ต้องเพิ่มโค้ดลงไปใน AndroidManifest ดังนี้
<uses-sdk tools:overrideLibrary="timber.log"/>

ลิงค์อ้างอิง

JakeWharton Github  : Timber
Bloco.io : Timber for logging
Blog.xmartlabs.com :  Android logging with Crashlytics and Timber
Nuuneoi.com : ทำความรู้จัก Fabric
Lordgift.in.th : Crashlytics - ตรวจสอบ error ที่เกิดบน mobile application

Teeranai.P

Developer ตัวน้อยๆ ที่หลงใหลในโลกของการพัฒนา Software. รักการเขียนโปรแกรมเป็นอันดับ 2 รองลงมาจากการนอน