Log Level ในการพัฒนาแอปพลิเคชัน: ความหมาย ประเภทของระดับ และการกำหนดค่า

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-28 เวลาอ่าน: 8 นาที

Log Level — การจำแนกข้อความบันทึกตามระดับความรุนแรง ช่วยให้นักพัฒนาสามารถควบคุมปริมาณข้อมูลที่แสดงผลในขั้นตอนต่าง ๆ ของการทำงานของแอปพลิเคชัน ตามข้อมูลจาก Google Android Developers, 2024 การเลือกระดับการบันทึกที่ถูกต้องช่วยลดปริมาณล็อกในระบบ production ลง 85–95% และเร่งการวินิจฉัยข้อผิดพลาด แต่ละระดับมีหน้าที่ของตัวเอง — ตั้งแต่การดีบักในขั้นตอนการพัฒนาไปจนถึงการตรวจสอบความล้มเหลวร้ายแรงในระบบ production

ประเด็นสำคัญ

  • Log Level — มาตราส่วนความรุนแรงที่ได้มาตรฐานจาก Verbose (การดีบักโดยละเอียด) ถึง Error (ความล้มเหลวร้ายแรง)
  • Verbose และ Debug — ระดับสำหรับการพัฒนา ถูกปิดใช้งานในบิลด์ production เพื่อประสิทธิภาพ
  • Info — ข้อความแจ้งข้อมูลเกี่ยวกับเหตุการณ์สำคัญ: การเริ่มต้น การยืนยันตัวตน การนำทาง
  • Warn — คำเตือนเกี่ยวกับปัญหาที่อาจเกิดขึ้นซึ่งไม่ทำให้เกิดความล้มเหลวทันที
  • Error — ข้อผิดพลาดร้ายแรงที่ต้องการความสนใจและการวิเคราะห์ทันทีจากนักพัฒนา

Log Level คืออะไร?

Log Level เป็นคุณสมบัติของข้อความบันทึกแต่ละข้อความที่กำหนดความสำคัญและความเร่งด่วนในการประมวลผล แพลตฟอร์ม iOS และ Android สมัยใหม่รองรับมาตราส่วนแบบรวมตั้งแต่ 6–7 ระดับ: จากละเอียดที่สุด (Verbose/Trace) ถึงร้ายแรง (Error/Assert) การเลือกระดับจะกำหนดว่าข้อความจะถูกเขียนลงในล็อกภายใต้การกำหนดค่าแอปพลิเคชันปัจจุบันหรือไม่

แนวคิดของ Log Level ตั้งอยู่บนหลักการของ พีระมิดความรุนแรง: ยิ่งระดับสูงขึ้นเท่าใด ข้อความที่แสดงในระดับนั้นก็ยิ่งน้อยลงเท่านั้น ตามข้อมูลจาก Semaphore CI, 2024 ในแอปพลิเคชัน production การกระจายเป็นดังนี้: Info — 60% ของข้อความ, Warn — 25%, Error — 10%, Debug — 5% ข้อความ Verbose ควรถูกปิดใช้งานโดยสมบูรณ์ใน production

แต่ละแพลตฟอร์มใช้งาน Log Level ผ่าน API ของตัวเอง Android ใช้ android.util.Log กับเมธอด v(), d(), i(), w(), e() Apple ใช้ OSLog กับระดับ default, info, debug, error, fault ไลบรารีอย่าง Timber และ CocoaLumberjack เพิ่มฟังก์ชันการทำงานเพิ่มเติมเหนือ API มาตรฐานเหล่านี้

ตามข้อมูลจาก Google I/O 2023 การเลือก Log Level ที่ผิดเป็นสาเหตุของ 40% ของปัญหาด้านประสิทธิภาพใน production นักพัฒนาทิ้งล็อก Debug ไว้ในบิลด์เผยแพร่ ซึ่งนำไปสู่การเขียนดิสก์มากเกินไปและการระบายแบตเตอรี่เร็วขึ้น

ประเภทของระดับการบันทึก: จาก Verbose ถึง Assert

Verbose (TRACE) — ระดับละเอียดที่สุด สงวนไว้สำหรับการพัฒนาโดยเฉพาะ ในระดับนี้ การคำนวณขั้นกลางทั้งหมด การวนซ้ำ และผลลัพธ์ของแต่ละขั้นตอนของอัลกอริทึมจะถูกแสดงผล บน Android ระดับนี้สอดคล้องกับ Log.v() บน iOS — OSLog ชนิด debug (ก่อน iOS 14 ใช้ os_trace)

Debug — ข้อความดีบักที่มีประโยชน์ระหว่างการพัฒนาและการทดสอบ ประกอบด้วยข้อมูลเกี่ยวกับสถานะของออบเจกต์สำคัญ ผลลัพธ์ของคำสั่ง SQL และพารามิเตอร์การเรียก API แตกต่างจาก Verbose ตรงที่ข้อความ Debug มีโครงสร้างและมีความหมายทางความหมาย บน iOS ระดับนี้สอดคล้องกับ OSLogType.debug

Info — ข้อความแจ้งข้อมูลเกี่ยวกับเหตุการณ์ปกติของแอปพลิเคชัน: การเริ่มต้น SDK, การยืนยันตัวตนสำเร็จ, การเปิดหน้าจอ, การรับข้อมูลจากเซิร์ฟเวอร์ ข้อความ Info ต้องไม่มี ข้อมูลส่วนบุคคลของผู้ใช้และควรปลอดภัยสำหรับการวิเคราะห์ใน production บน iOS ใช้ OSLogType.info บน Android — Log.i()

Warn — คำเตือนเกี่ยวกับปัญหาที่อาจเกิดขึ้น แอปพลิเคชันยังคงทำงานต่อไป แต่สถานการณ์ต้องการความสนใจ: ขนาดแคชใกล้ถึงขีดจำกัด, เวอร์ชัน API ที่ล้าสมัย, การตอบสนองเครือข่ายช้า, การลองเชื่อมต่อใหม่ บน Android — Log.w() บน iOS — OSLogType.default (สำหรับคำเตือน)

Error — ข้อผิดพลาดร้ายแรงที่แอปพลิเคชันไม่สามารถดำเนินการตามที่ร้องขอได้แต่ยังคงทำงานต่อไป: คำขอ API ล้มเหลว, การสูญเสียการเชื่อมต่อ, ข้อผิดพลาดในการเขียนฐานข้อมูล, การขาดสิทธิ์ บน iOS ใช้ OSLogType.error สำหรับข้อผิดพลาด บน Android — Log.e()

Assert (WTF) — ระดับสูงสุด บ่งบอกถึงสถานการณ์ที่ “ไม่สามารถเกิดขึ้นได้” ใช้สำหรับบันทึกบักที่ละเมิดกฎไม่แปรเปลี่ยนพื้นฐานของระบบ บน Android ข้อความ Assert จะไม่แสดงในบิลด์เผยแพร่ตามค่าเริ่มต้น บน iOS WTF (What a Terrible Failure) ถูกจัดการผ่าน OSLogType.fault

การใช้ Log Level บน Android

Android Log API — กลไกการบันทึกในตัวจากแพ็คเกจ android.util.Log มีเมธอดแบบสแตติก 6 เมธอด: Log.v(), Log.d(), Log.i(), Log.w(), Log.e() และ Log.wtf() แต่ละเมธอดรับ tag (สตริงระบุแหล่งที่มา) และ msg (ข้อความ)

kotlin
class UserRepository {
    companion object {
        private val TAG = "UserRepo"
    }

    suspend fun loadUser(id: String): User {
        Log.d(TAG, "กำลังโหลดผู้ใช้ด้วย id: $id")

        return try {
            val response = api.fetchUser(id)
            Log.i(TAG, "โหลดผู้ใช้สำเร็จ")
            response.toUser()
        } catch (e: Exception) {
            Log.e(TAG, "ไม่สามารถโหลดผู้ใช้: ${e.message}")
            throw e
        }
    }
}

การกรองตามระดับ ใน Android Logcat ทำผ่าน ADB: adb logcat *:E จะแสดงเฉพาะข้อความ Error ในบิลด์ production การเรียก Log.v() และ Log.d() ทั้งหมดจะถูกลบโดย ProGuard/R8 เมื่อเปิดใช้งานการย่อขนาด Log.i(), Log.w() และ Log.e() ยังคงอยู่ ดังนั้นจึงสำคัญที่จะไม่แสดงข้อมูลที่ละเอียดอ่อนผ่านเมธอดเหล่านี้

สำหรับการกรองแบบกำหนดเองในขณะรันไทม์ Android มี Log.isLoggable(tag, level) — เมธอดที่ตรวจสอบว่าระดับที่ระบุเปิดใช้งานสำหรับ tag ที่กำหนดหรือไม่ ซึ่งช่วยให้สามารถเปิดใช้งานการบันทึกโดยละเอียดแบบไดนามิกสำหรับโมดูลเฉพาะโดยไม่ต้องสร้างแอปพลิเคชันใหม่

การใช้ Log Level บน iOS และ macOS

OSLog — ระบบบันทึกแบบรวมของ Apple แทนที่ NSLog ที่เลิกใช้งานแล้ว OSLog มี 5 ระดับ: debug, info, default (notice), error และ fault ข้อได้เปรียบหลักคือ การบันทึกแบบมีโครงสร้าง พร้อมรองรับสตริงที่จัดรูปแบบและการกรองแบบไดนามิกผ่านคอนโซล

swift
import OSLog

let logger = Logger(
    subsystem: "com.example.app",
    category: "network"
)

func fetchData(from url: URL) {
    logger.debug("Starting request to \(url.absoluteString)")

    do {
        let data = try Data(contentsOf: url)
        logger.info("Received \(data.count) bytes")
    } catch {
        logger.error("Request failed: \(error.localizedDescription)")
    }
}

ระบบการกรอง ของ OSLog ทำงานในระดับระบบปฏิบัติการ ข้อความ Debug จะถูกเขียนเมื่อมีการเชื่อมต่อดีบักเกอร์หรือเมื่อเปิดใช้งานอาร์กิวเมนต์ -com.apple.CoreData.Logging.debug 1 เท่านั้น ข้อความ Info จะถูกรวบรวมในหน่วยความจำอุปกรณ์ (สูงสุด 512 KB) และเข้าถึงได้ผ่าน Console.app ข้อความ Error และ fault จะถูกเขียนอย่างต่อเนื่องและพร้อมสำหรับการรวบรวมผ่านระบบรายงานข้อขัดข้อง

คุณสมบัติสำคัญของ OSLog: สตริงที่จัดรูปแบบ พร้อมตัวยึดตำแหน่ง แทนที่จะใช้การแทรกสตริงแบบ Swift (ซึ่งถูกประเมินเสมอ โดยไม่คำนึงถึงระดับ) OSLog ใช้ รูปแบบ os_log กับ %{public}@ และ %{private}@ เพื่อแยกข้อมูลที่ละเอียดอ่อน พารามิเตอร์ส่วนตัวถูกปกปิดในล็อก production

Production vs Debug: วิธีการกำหนดค่าการกรองระดับ

กฎหลัก — ชุดระดับขั้นต่ำใน production: Info, Warn, Error, Assert Debug และ Verbose ต้องถูกปิดใช้งาน เหตุผลไม่ใช่เรื่องความปลอดภัยแต่เป็นประสิทธิภาพ: การเรียกบันทึกแต่ละครั้งใช้เวลา CPU ในการจัดรูปแบบสตริง แม้ว่าข้อความจะไม่ถูกแสดงผล

การจัดรูปแบบสตริงแบบขี้เกียจ

การเพิ่มประสิทธิภาพที่สำคัญ — อย่าใช้การแทรกสตริงในการเรียกบันทึก หากสตริงถูกสร้างขึ้นก่อนการเรียก log() เวลา CPU จะสูญเปล่าแม้ว่าระดับจะถูกปิดใช้งาน ใช้ การจัดรูปแบบแบบขี้เกียจ ผ่านแลมบ์ดาหรือเงื่อนไขป้องกัน

บน Android เมธอด Log.isLoggable() ทำหน้าที่นี้ บน OSLog รองรับสตริงที่จัดรูปแบบดั้งเดิมพร้อมตัวยึดตำแหน่ง Timber สำหรับ Android แก้ปัญหาผ่าน timber.log.Tree พร้อมตรวจสอบระดับภายในทรี

การเปลี่ยนระดับแบบไดนามิกทันที

Remote Log Level — แนวทางปฏิบัติที่ระดับการบันทึกถูกควบคุมจากเซิร์ฟเวอร์ผ่าน Firebase Remote Config หรือบริการที่คล้ายกัน หากเกิดข้อผิดพลาดซับซ้อนใน production นักพัฒนาสามารถ เปิดใช้งานการบันทึก Debug จากระยะไกล สำหรับโมดูลเฉพาะบนอุปกรณ์ของกลุ่มผู้ใช้ที่เลือก

ตามข้อมูลจาก Firebase, 2024 แนวทางนี้ลดเวลาในการวินิจฉัยบักที่พบได้ยากลง 60% และช่วยให้เห็นภาพรวมของปัญหาโดยไม่ต้องติดตั้งบิลด์ดีบัก ข้อจำกัดหลัก — การบันทึกจะเปิดใช้งานเมื่อเริ่มต้นแอปพลิเคชันครั้งถัดไปหลังจากได้รับการกำหนดค่าเท่านั้น

การกรองอัตโนมัติตามประเภทบิลด์

BuildConfig.DEBUG บน Android และ #if DEBUG บน Swift เป็นกลไกการคอมไพล์แบบมีเงื่อนไขมาตรฐานที่ปิดใช้งานระดับดีบักในบิลด์เผยแพร่ สำหรับสถาปัตยกรรมที่สะอาด ขอแนะนำให้ย้ายการเลือก Log Level ไปยัง คอนเทนเนอร์ DI หรือโรงงาน logger เพื่อไม่ให้ทำให้ตรรกะทางธุรกิจรกด้วยคำสั่งแบบมีเงื่อนไข

แนวทางปฏิบัติที่ดีที่สุดในการเลือกระดับการบันทึก

กฎข้อแรก — การเรียกบันทึกแต่ละครั้งควรตอบคำถาม “ใคร, อะไร, เมื่อไหร่” ใคร — คอมโพเนนต์หรือโมดูล (tag บน Android, category บน iOS) อะไร — เหตุการณ์เฉพาะหรือการเปลี่ยนแปลงสถานะ เมื่อไหร่ — ประทับเวลาที่ถูกเพิ่มโดยอัตโนมัติโดยระบบบันทึก

กฎข้อที่สอง — อย่าบันทึกข้อมูลที่ละเอียดอ่อนผ่าน Info และสูงกว่า รหัสผ่าน โทเค็น อีเมล หมายเลขโทรศัพท์ พิกัดทางภูมิศาสตร์ที่แม่นยำ — ห้ามโดยเด็ดขาดในล็อกใด ๆ ที่เข้าสู่ production หากจำเป็นให้ใช้การปกปิด: “email: us***@example.com”

กฎข้อที่สาม — ระดับ Warn เป็นความรับผิดชอบของนักพัฒนา Error — ของทีม Warn หมายถึง “ที่นี่มีปัญหาที่อาจเกิดขึ้น จับตาดูไว้” Error หมายถึง “ที่นี่มีปัญหา แก้ไขมัน” อย่าใช้ Error สำหรับสถานการณ์ที่คาดไว้และถูกจัดการแล้ว (เช่น ข้อผิดพลาด API 404)

กฎข้อที่สี่ — ความสอดคล้อง ทั้งโครงการควรใช้ข้อตกลงการตั้งชื่อแบบรวมสำหรับ tag และหมวดหมู่ ขอแนะนำ ClassName.methodName สำหรับ tag Android และ module.subsystem สำหรับ category iOS ซึ่งช่วยให้กรองล็อกตามคอมโพเนนต์ได้อย่างรวดเร็ว

กฎข้อที่ห้า — ทดสอบล็อกของคุณ ในการทดสอบหน่วย ตรวจสอบว่าเรียก Log Level ที่ถูกต้องในสถานการณ์เฉพาะ มี ไลบรารีจำลองการบันทึก สำหรับจุดประสงค์นี้: Mockito สำหรับ Android, Cuckoo สำหรับ iOS การตรวจสอบระดับในการทดสอบป้องกันการรั่วไหลของข้อความดีบักสู่ production

คำถามที่พบบ่อย

จะเกิดอะไรขึ้นหากทิ้งล็อก Debug ไว้ใน production?

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

ควรใช้ Log Level ใดในการบันทึกคำขอเครือข่าย?

Debug — สำหรับเนื้อหาคำขอและการตอบกลับ ส่วนหัว และรหัสสถานะ Info — สำหรับข้อเท็จจริงของการดำเนินการคำขอ (URL, เมธอด, ระยะเวลา) Error — สำหรับคำขอที่ล้มเหลวด้วยรหัส 4xx/5xx อย่าใช้ Verbose สำหรับล็อกเครือข่ายใน production

OSLogType.default แตกต่างจาก OSLogType.info อย่างไร?

OSLogType.default (ระดับ notice) — ข้อความสำคัญปานกลาง ถูกบันทึกในล็อกระบบและมองเห็นได้ใน Console.app OSLogType.info — ข้อความทางเทคนิค ไม่ถูกบันทึกถาวร สามารถใช้ได้เฉพาะระหว่างการทำโปรไฟล์เชิงรุกผ่าน Instruments

ProGuard จัดการกับการเรียก Log บน Android อย่างไร?

R8/ProGuard ลบ Log.v() และ Log.d() เมื่อเปิดใช้งานการย่อขนาดในบิลด์เผยแพร่ Log.i(), Log.w() และ Log.e() ถูกเก็บรักษาไว้ สำหรับการลบล็อกทั้งหมดโดยสมบูรณ์ จำเป็นต้องมีกฎแบบกำหนดเอง -assumenosideeffects class android.util.Log พร้อมระบุทุกระดับ

ทุกเมธอดควรบันทึกจุดเริ่มต้นและจุดสิ้นสุดของตนหรือไม่?

ไม่ — การบันทึกมากเกินไปทำให้ความสามารถในการอ่านและประสิทธิภาพลดลง บันทึกการเข้าใช้เฉพาะในเมธอดที่ซับซ้อนหรือไม่พร้อมกัน สำหรับเมธอดแบบซิงโครนัส ล็อกเดียวที่จุดส่งคืนหรือข้อผิดพลาดก็เพียงพอแล้ว ใช้ระดับ Debug สำหรับการติดตามการเรียก

สรุป

  • Log Level — มาตราส่วนความรุนแรงจาก Verbose ถึง Assert ที่กำหนดการมองเห็นของข้อความบันทึกแต่ละข้อความ
  • Verbose และ Debug — มีไว้สำหรับการพัฒนาและต้องถูกปิดใช้งานในบิลด์ production
  • Info — เหตุการณ์สำคัญของแอปพลิเคชัน ปลอดภัยสำหรับการวิเคราะห์ production
  • Warn — ปัญหาที่อาจเกิดขึ้นซึ่งไม่ต้องการการแก้ไขทันที
  • Error — ความล้มเหลวร้ายแรงที่ต้องการการแทรกแซงจากทีมพัฒนา
  • Android Log API ใช้ tag + level; OSLog บน iOS ใช้ subsystem + category + level
  • การจัดรูปแบบแบบขี้เกียจ และการคอมไพล์แบบมีเงื่อนไขเป็นเทคนิคสำคัญในการเพิ่มประสิทธิภาพการบันทึกใน production

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม