Entendendo o Logging

Este artigo aborda o processo de registro em log, incluindo padrões de registro, diretrizes de nível, classes, finalidades e aproximações multistack.

Padrões de registro

O login no Android é complexo devido à combinação de padrões usados ​​que são combinados no logcat . Os principais padrões utilizados são detalhados abaixo:

Fonte Exemplos Orientação em nível de pilha
RFC 5424 (padrão syslog ) Kernel Linux, muitos aplicativos Unix Kernel, daemons do sistema
android.util.Log Estrutura Android + registro de aplicativos Estrutura Android e aplicativo de sistema
java.util.logging.Level Log geral em Java aplicativo que não é do sistema

Figura 1: Padrões de nível de log.

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

Nível RFC 5424 Gravidade RFC 5424 Descrição da RFC 5424 android.util.Log java.util.logging.Level
0 Emergência O sistema está inutilizável Log.e / Log.wtf SEVERE
1 Alerta Ações devem ser tomadas 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 Aviso Condições de aviso Log.w WARNING
5 Perceber Normal, mas significativo Log.w WARNING
6 Informações Mensagens informativas Log.i INFO
7 Depurar Mensagens em nível de depuração Log.d CONFIG , FINE
- - Mensagens detalhadas Log.v FINER / FINEST

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

Diretrizes em nível de registro

Existem diretrizes fornecidas para cada padrão de registro. O nível de log escolhido segue o padrão apropriado usado, como usar o padrão syslog para desenvolvimento do kernel.

Os pedidos em nível de log, do menor para o maior, são mostrados 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 logs são compilados, mas removidos em tempo de execução.
VERBOSE Esses logs nunca são compilados em um aplicativo, exceto durante o desenvolvimento.

Figura 3: android.util.Log

CONFIG Nível de mensagem para mensagens de configuração estática
FINE Nível de mensagem fornecendo 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 indicando uma falha grave
WARNING Nível de mensagem indicando um possível problema

Figura 4: java.util.Logging.Level .

0 Emergência O sistema está inutilizável
1 Alerta Ações devem ser tomadas imediatamente
2 Crítico Condições críticas
3 Erro Condições de erro
4 Aviso Condições de aviso
5 Perceber Condição normal, mas significativa
6 Informativo Mensagens informativas
7 Depurar Mensagens em nível de depuração

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

Registro de aplicativos

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 logs podem ser ajustados em tempo 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. Existem variantes persistentes que também permanecem durante as reinicializações. Veja abaixo:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

As verificações Log#isLoggable deixam rastros de log no código do aplicativo. Os sinalizadores booleanos DEBUG ignoram os rastreamentos de log usando otimizações do compilador definidas como false , conforme mostrado abaixo:

private final static boolean DEBUG = false;

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

O registro pode ser removido por APK por meio dos conjuntos de regras do ProGuard pelo R8 em tempo de compilação. O exemplo a seguir remove tudo abaixo do registro no nível INFO 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 lidar com vários tipos de compilação de aplicativos (por exemplo, compilações de desenvolvimento versus compilações de lançamento) em que se espera que o código subjacente seja o mesmo, mas os níveis de log permitidos sejam diferentes. Uma política explícita deve ser definida e seguida para aplicativos (particularmente aplicativos de sistema) para decidir como os tipos de construção e as expectativas de lançamento impactam a saída do log.

Log do sistema no Android Runtime (ART)

Existem várias classes disponíveis para aplicativos e serviços do sistema:

Aula Propósito
android.telephony.Rlog Registro de rádio
android.util.Log Registro geral de aplicativos
android.util.EventLog Log de eventos de diagnóstico do integrador de sistema
android.util.Slog Log da estrutura da plataforma

Figura 6: Classes e finalidades de log do sistema disponíveis.

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

Registro nativo

O log em C/C++ segue o padrão syslog com syslog (2) correspondente ao syslog do kernel Linux que controla o buffer printk e syslog (3) correspondente ao criador de logs geral do sistema. O Android usa a biblioteca liblog para registro geral do sistema.

liblog fornece wrappers para os grupos de sublogs usando o seguinte formato de macro:

[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 de wrapper Funções de exemplo
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 superior para registro que são preferidas ao uso direto liblog , conforme visto abaixo:

Biblioteca Uso
async_safe Biblioteca apenas para registro em ambientes seguros com sinal assíncrono
libbase Biblioteca de registro em log que fornece uma interface de fluxo C++ para registro em log, semelhante ao registro em log no estilo Google (glog). libbase pode ser usado em projetos externos e está disponível em aplicativos que usam libbase_ndk .

Figura 8: Bibliotecas de log de nível superior.

Aproximações Multistack

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

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

Figura 9: Nível de erro no log Java padrão vs. log do Android.

Em casos como este, use o padrão individual para determinar qual nível aplicar.

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

Segurança e privacidade

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

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

Da mesma forma, certos detalhes são considerados confidenciais, mesmo que não sejam explicitamente identificáveis ​​pessoalmente.

Por exemplo, embora as informações de fuso horário não sejam consideradas pessoalmente identificáveis, elas fornecem uma indicação da localização aproximada de um usuário.

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

Registros de dispositivos

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

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