Bài viết này trình bày quy trình ghi nhật ký, bao gồm các tiêu chuẩn nhật ký, nguyên tắc về cấp độ, các lớp, mục đích và các phép tính gần đúng nhiều ngăn xếp.
Tiêu chuẩn về nhật ký
Việc ghi nhật ký trong Android rất phức tạp do sự kết hợp của các tiêu chuẩn được dùng và kết hợp trong logcat
. Sau đây là thông tin chi tiết về các tiêu chuẩn chính được sử dụng:
Nguồn | Ví dụ | Hướng dẫn về cấp độ ngăn xếp |
---|---|---|
RFC 5424 (syslog tiêu chuẩn) |
Nhân Linux, nhiều ứng dụng Unix | Kernel, system daemons |
android.util.Log |
Khung Android + ghi nhật ký ứng dụng | Khung Android và ứng dụng hệ thống |
java.util.logging.Level |
Ghi nhật ký chung trong Java | ứng dụng không phải là ứng dụng hệ thống |
Hình 1: Các tiêu chuẩn về cấp độ nhật ký.
Mặc dù mỗi tiêu chuẩn này đều có cấu trúc cấp độ tương tự nhau, nhưng chúng khác nhau về độ chi tiết. Sau đây là các giá trị tương đương gần đúng giữa các tiêu chuẩn:
Cấp độ RFC 5424 | Mức độ nghiêm trọng theo 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 | Bạn phải hành động 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 | Điều kiện lỗi | Log.e |
SEVERE |
4 | Cảnh báo | Điều kiện cảnh báo | Log.w |
WARNING |
5 | Lưu ý | Bình thường nhưng đáng kể | Log.w |
WARNING |
6 | Nút thông tin | Thông báo 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 báo chi tiết | Log.v |
FINER / FINEST |
Hình 2: syslog
, Android và các cấp độ ghi nhật ký Java.
Nguyên tắc về cấp độ nhật ký
Có các nguyên tắc hiện hành cho từng tiêu chuẩn nhật ký. Cấp nhật ký đã chọn tuân theo tiêu chuẩn thích hợp đang được sử dụng, chẳng hạn như sử dụng tiêu chuẩn syslog
để phát triển hạt nhân.
Thứ tự cấp nhật ký, từ ít nhất đến nhiều nhất, được minh hoạ trong 3 hình dưới đây:
ERROR |
Những nhật ký này luôn được lưu giữ. |
WARN |
Những nhật ký này luôn được lưu giữ. |
INFO |
Những nhật ký này luôn được lưu giữ. |
DEBUG |
Những nhật ký này được biên dịch nhưng bị xoá vào 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 quá trình phát triển. |
Hình 3: android.util.Log
CONFIG |
Cấp độ thông báo cho thông báo về 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 một thông báo theo dõi có độ chi tiết cao |
INFO |
Cấp độ thông báo cho thông báo thông tin |
SEVERE |
Cấp thông báo cho biết lỗi nghiêm trọng |
WARNING |
Cấp độ thông báo cho biết vấn đề có thể xảy ra |
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 | Bạn phải hành động ngay lập tức |
2 | Quan trọng | Điều kiện quan trọng |
3 | Lỗi | Điều kiện lỗi |
4 | Cảnh báo | Điều kiện cảnh báo |
5 | Lưu ý | Tình trạng bình thường nhưng đáng kể |
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
Tính năng ghi nhật ký có chọn lọc được thực hiện bằng TAG
theo lớp android.util.Log
bằng cách sử dụng Log#isLoggable
, như minh hoạ bên dưới:
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 để cung cấp một cấp độ ghi nhật ký được chọn như minh hoạ bên dưới:
adb shell setprop log.tag.FOO_TAG VERBOSE |
---|
Các thuộc tính log.tag.*
sẽ được đặt lại khi khởi động lại. Ngoài ra, còn có các biến thể cố định vẫn giữ nguyên sau khi khởi động lại. Xem bên dưới:
adb shell setprop persist.log.tag.FOO_TAG VERBOSE |
---|
Log#isLoggable
kiểm tra các dấu vết nhật ký còn lại trong mã ứng dụng. Cờ boolean DEBUG
bỏ qua các dấu vết nhật ký bằng cách sử dụng các chế độ 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; |
---|
Bạn có thể xoá tính năng ghi nhật ký trên cơ sở từng APK thông qua các quy tắc ProGuard bằng cách R8
tại thời gian biên dịch. Ví dụ sau đây sẽ xoá mọi nội dung bên dưới hoạt động ghi nhật ký cấp INFO
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 hữu ích khi xử lý nhiều loại bản dựng ứng dụng (ví dụ: bản dựng phát triển so với bản phát hành) trong đó mã cơ bản dự kiến sẽ giống nhau, nhưng các cấp độ nhật ký được phép lại khác nhau. Bạn phải đặt và tuân theo một chính sách rõ ràng cho các ứng dụng (đặc biệt là ứng dụng hệ thống) để quyết định cách các loại bản dựng và kỳ vọng phát hành ảnh hưởng đến đầu ra nhật ký.
Ghi nhật ký hệ thống trong Android Runtime (ART)
Có một số lớp có sẵn cho các ứng dụng và dịch vụ hệ thống:
Lớp học | Mục đích |
---|---|
android.telephony.Rlog |
Ghi nhật ký radio |
android.util.Log |
Ghi nhật ký chung về ứng dụng |
android.util.EventLog |
Ghi nhật ký sự kiện chẩn đoán của 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 nhật ký hệ thống và mục đích có sẵn.
Mặc dù android.util.Log
và android.util.Slog
sử dụng cùng một tiêu chuẩn cấp độ nhật ký, nhưng Slog
là một lớp @hide
mà chỉ nền tảng mới có thể sử dụng. Các cấp EventLog
được liên kết với các mục trong tệp 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
, trong đó syslog
(2) tương ứng với syslog
của nhân Linux kiểm soát vùng đệm printk
và syslog
(3) tương ứng với trình ghi nhật ký hệ thống chung. Android sử dụng thư viện 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 cách sử dụng biểu mẫu macro sau:
[Sublog Buffer ID] LOG [Log Level ID] |
Ví dụ: RLOGD
tương ứng với [Radio log buffer ID] LOG [Debug Level]
.
Sau đây là các trình bao bọc liblog
chính:
Lớp trình bao bọc | Ví dụ về hàm |
---|---|
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ó các giao diện cấp cao hơn để ghi nhật ký, được ưu tiên hơn việc sử dụng trực tiếp liblog
, như bạn thấy bên dưới:
Thư viện | Cách sử dụng |
---|---|
async_safe |
Thư viện chỉ để ghi nhật ký từ các môi trường an toàn cho 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ư tính năng ghi nhật ký theo kiểu của Google (glog). libbase có thể dùng được trong cả dự án bên ngoài và 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.
Xấp xỉ nhiều ngăn xếp
Do sự khác biệt về mức độ chi tiết và ý định cấp độ, nên không có sự so khớp rõ ràng hoặc chính xác giữa các tiêu chuẩn ghi nhật ký khác nhau. Ví dụ: các cấp java.util.logging.Level
và android.util.Log
cho nhật ký lỗi không khớp 1:1:
java.util.Logging.Level | android.util.Log |
---|---|
NGHIÊM TRỌNG | Log.wtf |
NGHIÊM TRỌNG | Log.e |
Hình 9: Cấp độ lỗi trong hoạt động ghi nhật ký Java tiêu chuẩn so với hoạt động ghi nhật ký Android.
Trong những trường hợp như thế này, hãy sử dụng từng tiêu chuẩn để xác định cấp độ cần á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 cần sử dụng cho mỗi thành phần. Để biết hướng dẫn sơ bộ về việc nhắn tin theo cấp, hãy xem Hình 2.
Bảo mật và quyền riêng tư
Không ghi nhật ký Thông tin nhận dạng cá nhân (PII). Trong đó có những thông tin như:
- Địa chỉ email
- Số điện thoại
- Tên
Tương tự, một số thông tin nhất định được coi là nhạy cảm ngay cả khi không phải là thông tin nhận dạng cá nhân một cách rõ ràng.
Ví dụ: mặc dù thông tin về múi giờ không được coi là thông tin nhận dạng cá nhân, nhưng thông tin này cho biết vị trí ước chừng của người dùng.
Chính sách nhật ký và các thông tin chi tiết chấp nhận được phải được xử lý trong quá trình đánh giá bảo mật và 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ị, kể cả khi sử dụng android.permission.READ_LOGS
, sẽ bị hạn chế:
- Nếu một ứng dụng ở chế độ nền yêu cầu cấp 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ừ phi ứng dụng:
- Chia sẻ UID hệ thống.
- Sử dụng một 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 cấp quyền truy cập vào nhật ký thiết bị, 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 đó.