Entender a geração de registros

Este artigo aborda o processo de geração de registros, incluindo padrões, diretrizes de nível, classes, finalidades e aproximações de várias pilhas.

Padrões de registro

A geração de registros no Android é complexa devido à combinação de padrões usados no logcat. Os principais padrões usados estão detalhados abaixo:

Fonte Exemplos Orientação sobre o nível da pilha
RFC 5424 (padrão syslog) Kernel do Linux, muitos apps Unix Kernel, daemons do sistema
android.util.Log Estrutura do Android + geração de registros de apps Framework do Android e app do sistema
java.util.logging.Level Registro geral em Java app que não é do sistema

Figura 1:padrões de nível de registro.

Embora cada um desses padrões tenha uma construção de nível semelhante, eles variam em granularidade. Os equivalentes aproximados entre os padrões são os seguintes:

Nível RFC 5424 Gravidade da RFC 5424 Descrição da RFC 5424 android.util.Log java.util.logging.Level
0 Emergência O sistema não pode ser usado Log.e / Log.wtf SEVERE
1 Alerta É necessário tomar uma ação imediatamente Log.e / Log.wtf SEVERE
2 Crítico Condições críticas Log.e / Log.wtf SEVERE
3 Erro Condições de erro Log.e SEVERE
4 Alerta Condições de alerta Log.w WARNING
5 Aviso Normal, mas significativo Log.w WARNING
6 Informações Mensagens informativas Log.i INFO
7 Depuração Mensagens de nível de depuração Log.d CONFIG, FINE
- - Mensagens detalhadas Log.v FINER / FINEST

Figura 2:níveis de registro do syslog, do Android e do Java.

Diretrizes de nível de registro

Há diretrizes para cada padrão de registro. O nível de registro escolhido segue o padrão apropriado em uso, como o syslog para desenvolvimento de kernel.

As ordens de nível de registro, do menor para o maior, são mostradas nas três figuras abaixo:

ERROR Esses registros são sempre mantidos.
WARN Esses registros são sempre mantidos.
INFO Esses registros são sempre mantidos.
DEBUG Esses registros são compilados, mas removidos no tempo de execução.
VERBOSE Esses registros nunca são compilados em um app, exceto durante o desenvolvimento.

Figura 3: android.util.Log

CONFIG Nível de mensagem para mensagens de configuração estática
FINE Nível da mensagem que fornece informações de rastreamento
FINER Indica uma mensagem de rastreamento bastante detalhada.
FINEST Indica uma mensagem de rastreamento altamente detalhada.
INFO Nível de mensagem para mensagens informativas
SEVERE Nível de mensagem que indica uma falha grave.
WARNING Nível da mensagem que indica um possível problema

Figura 4:java.util.Logging.Level.

0 Emergência O sistema não pode ser usado
1 Alerta É necessário tomar uma ação imediatamente
2 Crítico Condições críticas
3 Erro Condições de erro
4 Alerta Condições de alerta
5 Aviso Condição normal, mas significativa
6 Informativo Mensagens informativas
7 Depuração Mensagens de nível de depuração

Figura 5:RFC 5424 - Seção 6.2.1.

Geração de registros de apps

O registro seletivo é realizado com TAG pela classe android.util.Log usando Log#isLoggable, conforme mostrado abaixo:

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

Os registros podem ser ajustados no ambiente de execução para fornecer um nível selecionado de registro, conforme mostrado abaixo:

adb shell setprop log.tag.FOO_TAG VERBOSE

As propriedades log.tag.* são redefinidas na reinicialização. Há variantes persistentes que permanecem mesmo após reinicializações. Confira abaixo:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

As verificações do Log#isLoggable deixam rastros de registros no código do app. Flags booleanas DEBUG ignoram rastreamentos de registros usando otimizações de compilador definidas como false, conforme mostrado abaixo:

private final static boolean DEBUG = false;

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

O registro em log pode ser removido por APK usando conjuntos de regras do ProGuard por R8 no tempo de compilação. O exemplo a seguir remove tudo abaixo do nível INFO de geração de registros para 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

Isso é útil para processar vários tipos de build de app (por exemplo, builds de desenvolvimento x builds de lançamento), em que o código subjacente deve ser o mesmo, mas os níveis de registro permitidos são diferentes. Uma política explícita precisa ser definida e seguida para que os apps (principalmente os de sistema) decidam como os tipos de build e as expectativas de lançamento afetam a saída de registros.

Geração de registros do sistema no Android Runtime (ART)

Há várias classes disponíveis para apps e serviços do sistema:

Turma Finalidade
android.telephony.Rlog Geração de registros de rádio
android.util.Log Geração de registros gerais de apps
android.util.EventLog Registro de eventos de diagnóstico do integrador de sistemas
android.util.Slog Geração de registros do framework da plataforma

Figura 6:classes e finalidades de registros do sistema disponíveis.

Embora android.util.Log e android.util.Slog usem os mesmos padrões de nível de registro, Slog é uma classe @hide que só pode ser usada pela plataforma. Os níveis de EventLog são mapeados para as entradas no arquivo event.logtags em /system/etc/event-log-tags.

Geração de registros nativa

A geração de registros em C/C++ segue o padrão syslog, com syslog(2) correspondendo ao kernel do Linux syslog que controla o buffer printk, e syslog(3) correspondendo ao registrador geral do sistema. O Android usa a biblioteca liblog para geração de registros gerais do sistema.

O liblog fornece wrappers para os grupos de subregistros usando a seguinte macro forma:

[Sublog Buffer ID] LOG [Log Level ID]

RLOGD, por exemplo, corresponde a [Radio log buffer ID] LOG [Debug Level]. Os principais wrappers liblog são os seguintes:

Classe wrapper Exemplos de funções
log_main.h ALOGV, ALOGW
log_radio.h RLOGD, RLOGE
log_system.h SLOGI, SLOGW

Figura 7:wrappers liblog.

O Android tem interfaces de nível mais alto para registro em log que são preferíveis ao uso direto de liblog, como mostrado abaixo:

Biblioteca Uso
async_safe Biblioteca apenas para geração de registros em ambientes assíncronos e seguros para sinais.
libbase Biblioteca de geração de registros que fornece uma interface de stream C++ para geração de registros, semelhante à geração de registros no estilo do Google (glog). A libbase pode ser usada em projetos externos e está disponível em apps que usam libbase_ndk.

Figura 8:bibliotecas de registro de nível mais alto.

Aproximações de várias pilhas

Devido a diferenças na granularidade e no nível de intenção, não há correspondências claras ou exatas de diferentes padrões de geração de registros. Por exemplo, os níveis java.util.logging.Level e android.util.Log para registros de erros não são uma correspondência 1:1:

java.util.Logging.Level android.util.Log
SEVERA Log.wtf
SEVERA Log.e

Figura 9:nível de erro no registro padrão do Java x registro do Android.

Nesses casos, use o padrão individual para determinar qual nível aplicar.

Durante o desenvolvimento do sistema com vários componentes de nível de pilha, siga a Figura 1 para determinar qual padrão usar por componente. Para um guia aproximado de mensagens por níveis, siga a Figura 2.

Segurança e privacidade

Não registre informações de identificação pessoal (PII). Isso inclui detalhes como:

  • Endereços de e-mail
  • Números de telefone
  • Nomes

Da mesma forma, alguns detalhes são considerados sensíveis mesmo que não sejam explicitamente de identificação pessoal.

Por exemplo, embora as informações de fuso horário não sejam consideradas de identificação pessoal, elas indicam a localização aproximada de um usuário.

A política de registros e os detalhes aceitáveis precisam ser tratados como parte da revisão de segurança e privacidade antes do lançamento.

Registros do dispositivo

O acesso a todos os registros do dispositivo, incluindo o uso de android.permission.READ_LOGS é restrito:

  • Se um app em segundo plano pedir acesso a todos os registros do dispositivo, a solicitação será negada automaticamente, a menos que o app:
    • Compartilha o UID do sistema.
    • Usa um processo nativo do sistema (UID < APP_UID).
    • Usa DropBoxManager
    • Acessa apenas o buffer de registro de eventos.
    • Usa a API EventLog.
    • Usa testes instrumentados.
  • Se um app em primeiro plano com READ_LOGS solicitar acesso aos registros do dispositivo, o sistema vai pedir que o usuário aprove ou negue a solicitação.