Tìm hiểu về việc ghi nhật ký

Bài viết này đề cập đến quy trình ghi nhật ký, bao gồm tiêu chuẩn nhật ký, nguyên tắc về cấp độ, lớp, mục đích và phép tính gần đúng nhiều ngăn xếp.

Ghi nhật ký các tiêu chuẩn

Việc ghi nhật ký trong Android rất phức tạp do sự kết hợp các tiêu chuẩn được sử dụng được kết hợp trong logcat. Dưới đây là các tiêu chuẩn chính được sử dụng:

Nguồn Ví dụ Hướng dẫn cấp ngăn xếp
RFC 5424 (syslog chuẩn) Nhân hệ điều hành Linux, nhiều ứng dụng Unix Kernel, trình nền hệ thống
android.util.Log Khung Android + ghi nhật ký ứng dụng ứng dụng hệ thống và khung Android
java.util.logging.Level Ghi nhật ký chung trong Java ứng dụng không phải hệ thống

Hình 1: Các tiêu chuẩn ở cấp độ nhật ký.

Mặc dù mỗi tiêu chuẩn trong số này có cấu trúc cấp độ tương tự nhau, nhưng chúng khác nhau về độ chi tiết. Giá trị tương đương gần đúng của các tiêu chuẩn như sau:

Cấp độ RFC 5424 Mức độ nghiêm trọng RFC 5424 Nội dung mô tả RFC 5424 android.util.Log java.util.logging.level
0 Khẩn cấp Hệ thống không sử dụng được Log.e / Log.wtf SEVERE
1 Cảnh báo Hành động phải được thực hiện ngay lập tức Log.e / Log.wtf SEVERE
2 Quan trọng Điều kiện quan trọng Log.e / Log.wtf SEVERE
3 Lỗi Các điều kiện về lỗi Log.e SEVERE
4 Thông báo nhắc nhở Điều kiện cảnh báo Log.w WARNING
5 Thông báo Bình thường nhưng đáng kể Log.w WARNING
6 Thông tin Nhắn tin thông tin Log.i INFO
7 Gỡ lỗi Thông báo ở cấp độ gỡ lỗi Log.d CONFIG, FINE
- - Thông điệp chi tiết Log.v FINER/FINEST

Hình 2: Cấp độ ghi nhật ký syslog, Android và Java.

Nguyên tắc về cấp độ nhật ký

Hiện có các nguyên tắc dành cho từng tiêu chuẩn nhật ký. Nhật ký đã chọn sẽ tuân theo tiêu chuẩn thích hợp đang được sử dụng, chẳng hạn như sử dụng syslog để phát triển nhân.

Các đơn đặt hàng ở cấp độ nhật ký, từ thấp nhất đến nhiều nhất, được thể hiện trong ba hình dưới đây:

ERROR Các nhật ký này luôn được lưu giữ.
WARN Các nhật ký này luôn được lưu giữ.
INFO Các nhật ký này luôn được lưu giữ.
DEBUG Các nhật ký này được biên dịch nhưng bị xoá trong thời gian chạy.
VERBOSE Các nhật ký này không bao giờ được biên dịch thành một ứng dụng ngoại trừ trong phát triển ứng dụng.

Hình 3: android.util.Log

CONFIG Cấp thông báo cho thông báo cấu hình tĩnh
FINE Cấp thông báo cung cấp thông tin theo dõi
FINER Cho biết một thông báo theo dõi khá chi tiết
FINEST Cho biết thông báo theo dõi quá chi tiết
INFO Cấp độ tin nhắn của thông báo cung cấp thông tin
SEVERE Mức thông báo cho biết đã xảy ra lỗi nghiêm trọng
WARNING Cấp độ tin nhắn cho biết sự cố tiềm ẩn

Hình 4: java.util.Logging.Level.

0 Khẩn cấp Hệ thống không sử dụng được
1 Cảnh báo Hành động phải được thực hiện ngay lập tức
2 Quan trọng Điều kiện quan trọng
3 Lỗi Các điều kiện về lỗi
4 Thông báo nhắc nhở Điều kiện cảnh báo
5 Thông báo Tình trạng bình thường nhưng nghiêm trọng
6 Thông tin Thông báo thông tin
7 Gỡ lỗi Thông báo ở cấp độ gỡ lỗi

Hình 5: RFC 5424 – Phần 6.2.1.

Ghi nhật ký ứng dụng

Việc ghi nhật ký có chọn lọc được thực hiện với lớp TAG của android.util.Log bằng cách sử dụng Log#isLoggable, như minh hoạ dưới đây:

if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) {
 Log.v("FOO_TAG", "Message for logging.");
}

Bạn có thể điều chỉnh nhật ký trong thời gian chạy để chọn cấp độ ghi nhật ký như minh hoạ bên dưới:

adb shell setprop log.tag.FOO_TAG VERBOSE

Các thuộc tính log.tag.* được đặt lại khi khởi động lại. Có các biến thể cố định vẫn tồn tại qua các lần khởi động lại. Hãy xem mục bên dưới:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

Quy trình kiểm tra Log#isLoggable để lại dấu vết nhật ký trong mã ứng dụng. Boolean (logic) Cờ DEBUG bỏ qua dấu vết nhật ký bằng cách sử dụng tính năng tối ưu hoá trình biên dịch được đặt thành false, như minh hoạ dưới đây:

private final static boolean DEBUG = false;

… If (DEBUG) { Log.v("FOO_TAG", "Extra debug logging."); }

Bạn có thể xoá việc ghi nhật ký trên cơ sở mỗi tệp APK thông qua tập hợp quy tắc ProGuard chậm nhất vào R8 tại thời gian biên dịch. Ví dụ sau đây sẽ xoá mọi nội dung ở cấp độ dưới INFO ghi nhật ký cho android.util.Log:

# This allows proguard to strip isLoggable() blocks containing only <=INFO log
# code from release builds.
-assumenosideeffects class android.util.Log {
  static *** i(...);
  static *** d(...);
  static *** v(...);
  static *** isLoggable(...);
}
-maximumremovedandroidloglevel 4

Điều này rất hữu ích khi xử lý nhiều loại bản dựng ứng dụng (cho ví dụ: bản dựng phát triển so với bản phát hành) trong đó mã cơ bản là dự kiến sẽ giống nhau, nhưng cấp độ nhật ký được phép là khác nhau. Từ khóa chính sách phải được đặt và tuân thủ đối với ứng dụng (đặc biệt là hệ thống ứng dụng) để quyết định cách loại bản dựng và nhật ký tác động của kỳ vọng phát hành đầu ra.

Ghi nhật ký hệ thống trong Android Runtime (ART)

Có một số lớp có sẵn cho hệ thống ứng dụng và dịch vụ:

Lớp Mục đích
android.telephony.Rlog Ghi nhật ký đài
android.util.Log Ghi nhật ký ứng dụng chung
android.util.EventLog Ghi nhật ký sự kiện chẩn đoán của trình tích hợp hệ thống
android.util.Slog Ghi nhật ký khung nền tảng

Hình 6: Các lớp và mục đích hiện có của nhật ký hệ thống.

Mặc dù android.util.Logandroid.util.Slog sử dụng cùng một cấp độ nhật ký tiêu chuẩn, Slog là một lớp @hide mà chỉ nền tảng mới sử dụng được. EventLog cấp độ được liên kết với các mục nhập trong event.logtags trong /system/etc/event-log-tags.

Ghi nhật ký gốc

Việc ghi nhật ký trong C/C++ tuân theo tiêu chuẩn syslog với syslog(2) tương ứng với nhân hệ điều hành Linux syslog kiểm soát vùng đệm printksyslog(3) tương ứng với trình ghi nhật ký hệ thống chung. Android sử dụng liblog để ghi nhật ký hệ thống chung.

liblog cung cấp trình bao bọc cho các nhóm nhật ký phụ bằng macro sau biểu mẫu:

[Sublog Buffer ID] LOG [Log Level ID]

Ví dụ: RLOGD tương ứng với [Radio log buffer ID] LOG [Debug Level]. Các trình bao bọc liblog chính như sau:

Lớp trình bao bọc Hàm ví dụ
log_main.h ALOGV, ALOGW
log_radio.h RLOGD, RLOGE
log_system.h SLOGI, SLOGW

Hình 7: Trình bao bọc liblog.

Android có giao diện cấp cao hơn để ghi nhật ký được ưu tiên hơn so với giao diện trực tiếp Mức sử dụng liblog, như minh hoạ dưới đây:

Thư viện Cách sử dụng
async_safe Thư viện chỉ dùng để ghi nhật ký từ các môi trường an toàn tín hiệu không đồng bộ
libbase Thư viện ghi nhật ký cung cấp giao diện luồng C++ để ghi nhật ký, tương tự như Ghi nhật ký kiểu Google (glog). libbase dùng được trong cả hai dự án bên ngoài và dùng được trong các ứng dụng dùng libbase_ndk.

Hình 8: Thư viện nhật ký cấp cao hơn.

Ước tính nhiều ngăn xếp

Do sự khác biệt về mức độ chi tiết và ý định theo cấp, không có khớp chính xác các tiêu chuẩn ghi nhật ký khác nhau. Ví dụ: Các cấp java.util.logging.Levelandroid.util.Log đối với nhật ký lỗi không phải là Kết quả 1:1:

java.util.Logging.level android.util.Log
BỎ QUA Log.wtf
BỎ QUA Log.e

Hình 9: Mức độ lỗi khi ghi nhật ký Java chuẩn so với Android ghi nhật ký.

Trong những trường hợp như thế này, hãy sử dụng tiêu chuẩn riêng để xác định cấp cần sẽ áp dụng.

Trong quá trình phát triển hệ thống với nhiều thành phần cấp ngăn xếp, hãy làm theo Hình 1 để xác định tiêu chuẩn sử dụng cho mỗi thành phần. Để biết giá trị gần đúng hướng dẫn về thông báo theo bậc, hãy thực hiện theo Hình 2.

Bảo mật và quyền riêng tư

Đừng ghi lại Thông tin nhận dạng cá nhân (PII). Chiến dịch này bao gồm các thông tin chi tiết như:

  • Địa chỉ email
  • Số điện thoại
  • Tên

Tương tự, một số chi tiết nhất định được coi là nhạy cảm ngay cả khi không có thể nhận dạng cá nhân một cách rõ ràng.

Ví dụ: mặc dù thông tin múi giờ không được coi là thông tin nhận dạng cá nhân, nó cho biết vị trí gần đúng của người dùng.

Chính sách nhật ký và các chi tiết được chấp nhận phải được xử lý như một phần của quá trình bảo mật và đánh giá quyền riêng tư trước khi phát hành.

Nhật ký thiết bị

Quyền truy cập vào toàn bộ nhật ký thiết bị, bao gồm cả việc sử dụng android.permission.READ_LOGS bị hạn chế:

  • Nếu một ứng dụng ở chế độ nền yêu cầu quyền truy cập vào toàn bộ nhật ký thiết bị, thì yêu cầu đó sẽ tự động bị từ chối trừ khi ứng dụng:
    • Chia sẻ UID hệ thống.
    • Sử dụng quy trình hệ thống gốc (UID < APP_UID).
    • Sử dụng DropBoxManager
    • Chỉ truy cập vào vùng đệm nhật ký sự kiện.
    • Sử dụng API EventLog.
    • Sử dụng kiểm thử đo lường.
  • Nếu một ứng dụng ở nền trước có READ_LOGS yêu cầu quyền truy cập vào nhật ký thiết bị, thì hệ thống sẽ nhắc người dùng phê duyệt hoặc từ chối yêu cầu truy cập.