Entendendo o Logging

Este artigo aborda o processo de log, incluindo padrões de log, diretrizes de nível, classes, propósitos e aproximações de várias pilhas.

Padrões de registro

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

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

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

Embora cada um desses padrões tenha 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 RFC 5424 Gravidade 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ção deve ser tomada 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 de informação Log.i INFO
7 Depurar Mensagens no nível de depuração Log.d CONFIG , FINE
- - Mensagens detalhadas Log.v FINER / FINEST

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

Diretrizes de nível de registro

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

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

ERROR Esses logs são sempre mantidos.
WARN Esses logs são sempre mantidos.
INFO Esses logs 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ção deve ser tomada 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 no nível de depuração

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

Registro de aplicativos

O log 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 log, 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 permanecem nas reinicializações também. 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 de 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 são diferentes. Uma política explícita deve ser definida e seguida para aplicativos (especialmente aplicativos de sistema) para decidir como os tipos de compilação e as expectativas de versão afetam 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:

Classe Objetivo
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 sistemas
android.util.Slog Registro da estrutura da plataforma

Figura 6: Classes e propósitos 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 de EventLog são mapeados para as entradas no arquivo event.logtags em /system/etc/event-log-tags .

Log Nativo

O login 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 logger geral do sistema. O Android usa a biblioteca liblog para log geral do sistema.

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

[Sublog Buffer ID] LOG [Log Level ID]

RLOGD , por exemplo, corresponde a [Radio log buffer ID] LOG [Debug Level] . Os principais wrappers de 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 de liblog .

O Android tem interfaces de nível superior para registro que são favorecidas em relação ao uso direto liblog , como visto abaixo:

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

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

Aproximações de várias pilhas

Devido às diferenças de granularidade e intenção de nível, não há correspondências claras ou exatas de 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 de 1:1:

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

Figura 9: Nível de erro no registro Java padrão versus registro no Android.

Em casos como esse, 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 obter um guia aproximado para mensagens de camada, 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 registro e os detalhes aceitáveis ​​devem ser tratados como parte da análise de segurança e privacidade antes do lançamento.