В этой статье рассматривается процесс ведения журнала, включая стандарты ведения журнала, руководящие принципы уровней, классы, цели и многостековые приближения.
Стандарты бревен
Ведение логов в Android затруднено из-за сочетания различных стандартов, объединенных в logcat
. Основные используемые стандарты подробно описаны ниже:
Источник | Примеры | Руководство на уровне стека |
---|---|---|
RFC 5424 (стандарт syslog ) | Ядро Linux, множество приложений Unix | Ядро, системные демоны |
android.util.Log | Android Framework + ведение журнала приложений | Android-фреймворк и системное приложение |
java.util.logging.Level | Общее ведение журнала в Java | несистемное приложение |
Рисунок 1: Стандарты уровня журнала.
Хотя все эти стандарты имеют схожую структуру уровней, они различаются по степени детализации. Примерные эквиваленты для всех стандартов следующие:
Уровень RFC 5424 | RFC 5424 Серьезность | Описание RFC 5424 | android.util.Log | java.util.logging.Level |
---|---|---|---|---|
0 | Чрезвычайная ситуация | Система непригодна к использованию | Log.e / Log.wtf | SEVERE |
1 | Тревога | Необходимо принять немедленные меры. | Log.e / Log.wtf | SEVERE |
2 | Критический | Критические состояния | Log.e / Log.wtf | SEVERE |
3 | Ошибка | Ошибочные состояния | Log.e | SEVERE |
4 | Предупреждение | Предупреждающие условия | Log.w | WARNING |
5 | Уведомление | Нормально, но значительно | Log.w | WARNING |
6 | Информация | Информационные сообщения | Log.i | INFO |
7 | Отлаживать | Сообщения уровня отладки | Log.d | CONFIG , FINE |
- | - | Подробные сообщения | Log.v | FINER / FINEST |
Рисунок 2: уровни ведения журнала syslog
, Android и Java.
Рекомендации по уровню журнала
Для каждого стандарта ведения журнала существуют свои рекомендации. Выбранный уровень ведения журнала соответствует используемому стандарту, например, стандарту syslog
для разработки ядра.
Порядки уровней журнала, от наименьшего к наибольшему, показаны на трех рисунках ниже:
ERROR | Эти журналы всегда сохраняются. |
WARN | Эти журналы всегда сохраняются. |
INFO | Эти журналы всегда сохраняются. |
DEBUG | Эти журналы компилируются, но удаляются во время выполнения. |
VERBOSE | Эти журналы никогда не компилируются в приложение, за исключением периода разработки. |
Рисунок 3: android.util.Log
CONFIG | Уровень сообщений для сообщений статической конфигурации |
FINE | Уровень сообщения, предоставляющий информацию для отслеживания |
FINER | Указывает на довольно подробное сообщение об отслеживании. |
FINEST | Указывает на очень подробное сообщение об отслеживании. |
INFO | Уровень сообщения для информационных сообщений |
SEVERE | Уровень сообщения, указывающий на серьезную неисправность |
WARNING | Уровень сообщения, указывающий на потенциальную проблему |
Рисунок 4: java.util.Logging.Level
.
0 | Чрезвычайная ситуация | Система непригодна к использованию |
1 | Тревога | Необходимо принять немедленные меры. |
2 | Критический | Критические состояния |
3 | Ошибка | Ошибочные состояния |
4 | Предупреждение | Предупреждающие условия |
5 | Уведомление | Нормальное, но значимое состояние |
6 | Информационный | Информационные сообщения |
7 | Отлаживать | Сообщения уровня отладки |
Рисунок 5: RFC 5424
— Раздел 6.2.1 .
Ведение журнала приложений
Выборочное ведение журнала выполняется с помощью TAG
класса android.util.Log
с использованием Log#isLoggable
, как показано ниже:
if (Log.isLoggable("FOO_TAG", Log.VERBOSE)) { Log.v("FOO_TAG", "Message for logging."); } |
---|
Журналы можно настраивать во время выполнения, чтобы обеспечить выбранный уровень протоколирования, как показано ниже:
adb shell setprop log.tag.FOO_TAG VERBOSE |
---|
Свойства log.tag.*
сбрасываются при перезагрузке. Существуют также постоянные варианты, которые сохраняются при перезагрузках. См. ниже:
adb shell setprop persist.log.tag.FOO_TAG VERBOSE |
---|
Проверки Log#isLoggable
оставляют следы журнала в коде приложения. Булевы флаги DEBUG
обходят следы журнала, используя оптимизации компилятора, которым присвоено значение false
, как показано ниже:
private final static boolean DEBUG = false; |
---|
Журналирование можно удалить для каждого APK-файла с помощью наборов правил ProGuard в R8
во время компиляции. Следующий пример удаляет всё ниже уровня INFO
для 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 |
---|
Это полезно для обработки различных типов сборок приложений (например, сборок для разработки и сборок для выпуска), где предполагается, что базовый код будет одинаковым, но допустимые уровни ведения журнала будут разными. Для приложений (особенно системных) необходимо установить и соблюдать явную политику, определяющую, как типы сборок и ожидаемые релизы влияют на вывод журнала.
Ведение журнала системы в среде выполнения Android (ART)
Существует несколько доступных классов для системных приложений и служб:
Сорт | Цель |
---|---|
android.telephony.Rlog | Радиолог |
android.util.Log | Общее ведение журнала приложений |
android.util.EventLog | Ведение журнала диагностических событий системного интегратора |
android.util.Slog | Ведение журнала фреймворка платформы |
Рисунок 6: Доступные классы и цели системного журнала.
Хотя android.util.Log
и android.util.Slog
используют одни и те же стандарты уровней журналирования, Slog
— это класс @hide
, доступный только платформе. Уровни EventLog
сопоставляются с записями в файле event.logtags
в /system/etc/event-log-tags
.
Собственная регистрация
Ведение журнала в C/C++ соответствует стандарту syslog
, где syslog
(2) соответствует syslog
ядра Linux, управляющему буфером printk
, а syslog
(3) соответствует общему системному журналу. В Android для общего системного журналирования используется библиотека liblog
.
liblog
предоставляет оболочки для групп подлогов, используя следующую форму макроса:
[Sublog Buffer ID] LOG [Log Level ID] |
Например, RLOGD
соответствует [Radio log buffer ID] LOG [Debug Level]
. Основные обёртки liblog
следующие:
Класс-обертка | Примеры функций |
---|---|
log_main.h | ALOGV , ALOGW |
log_radio.h | RLOGD , RLOGE |
log_system.h | SLOGI , SLOGW |
Рисунок 7: оболочки liblog
.
В Android имеются интерфейсы более высокого уровня для ведения журнала, которые более предпочтительны, чем прямое использование liblog
, как показано ниже:
Библиотека | Использование |
---|---|
async_safe | Библиотека только для регистрации в асинхронно-сигнально-безопасных средах |
libbase | Библиотека журналирования, которая предоставляет потоковый интерфейс C++ для журналирования, аналогичный журналированию в стиле Google (glog). libbase может использоваться как во внешних проектах, так и в приложениях, использующих libbase_ndk . |
Рисунок 8: Библиотеки журналов более высокого уровня.
Многостековые приближения
Из-за различий в детализации и предназначении уровней, чёткого и точного соответствия между различными стандартами журналирования не существует. Например, уровни java.util.logging.Level
и android.util.Log
для журналов ошибок не соответствуют друг другу в точности:
java.util.Logging.Level | android.util.Log |
---|---|
СЕРЬЕЗНЫЙ | Log.wtf |
СЕРЬЕЗНЫЙ | Log.e |
Рисунок 9: Уровень ошибок при стандартном ведении журнала Java и ведении журнала Android.
В подобных случаях используйте индивидуальный стандарт, чтобы определить, какой уровень применять.
При разработке системы с несколькими уровнями стека компонентов следуйте рисунку 1, чтобы определить, какой стандарт использовать для каждого компонента. Примерное руководство по обмену сообщениями между уровнями см. на рис. 2.
Безопасность и конфиденциальность
Не регистрируйте персональные данные (PII). К ним относятся следующие сведения:
- Адреса электронной почты
- Номера телефонов
- Имена
Аналогичным образом, некоторые данные считаются конфиденциальными, даже если они не позволяют явно идентифицировать личность.
Например, хотя информация о часовом поясе не считается персонально идентифицируемой, она дает представление о приблизительном местоположении пользователя.
Политика ведения журнала и приемлемые сведения должны быть обработаны в рамках проверки безопасности и конфиденциальности перед выпуском.
Журналы устройства
Доступ ко всем журналам устройства, в том числе с использованием android.permission.READ_LOGS
, ограничен:
- Если приложение в фоновом режиме запрашивает доступ ко всем журналам устройства, запрос автоматически отклоняется, если только приложение:
- Использует общий системный UID.
- Использует собственный системный процесс (
UID
<APP_UID
). - Использует
DropBoxManager
. - Доступ только к буферу журнала событий.
- Использует API
EventLog
. - Использует инструментальные тесты.
- Если приложение на переднем плане с
READ_LOGS
запрашивает доступ к журналам устройства, система предлагает пользователю одобрить или отклонить запрос на доступ.