Entender a geração de registros

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

Padrões de registro

A geração de registro no Android é complexa devido à combinação de padrões usados combinados em logcat. Confira abaixo os principais padrões usados:

Fonte Exemplos Orientações sobre o nível da pilha
RFC 5424 (syslog padrão) Kernel do Linux, muitos apps Unix Kernel e daemons do sistema
android.util.Log Framework do Android + geração de registros do app 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. As equivalências aproximadas entre os padrões são as seguintes:

Nível do RFC 5424 Gravidade do RFC 5424 RFC 5424 Description (em inglês) 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 medidas 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 aviso Log.w WARNING
5 Aviso Normal, mas significativo Log.w WARNING
6 Informações Mensagens informativas Log.i INFO
7 Depuração Mensagens no 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 que está sendo usado, como o padrão syslog para desenvolvimento de kernel.

As ordens de nível de registro, da menor para a 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 momento da execução.
VERBOSE Esses registros nunca são compilados em um app, exceto durante o desenvolvimento.

Figura 3:android.util.Log

CONFIG Nível da 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 muito 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 medidas imediatamente
2 Crítico Condições críticas
3 Erro Condições de erro
4 Alerta Condições de aviso
5 Aviso Condição normal, mas significativa
6 Informativo Mensagens informativas
7 Depuração Mensagens no nível de depuração

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

Geração de registros de apps

A geração de registros seletiva é realizada 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 momento da 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 também permanecem após reinicializações. Confira abaixo:

adb shell setprop persist.log.tag.FOO_TAG VERBOSE

As verificações de Log#isLoggable deixam rastros de registro no código do app. As flags DEBUG booleanas ignoram os rastros de registro 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 usando as regras do ProGuard por R8 no momento da compilação. O exemplo a seguir remove tudo abaixo do nível de registro 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 processar vários tipos de build de app (por exemplo, builds de desenvolvimento e de lançamento), em que o código principal é esperado ser o mesmo, mas os níveis de registro permitidos são diferentes. Uma política explícita precisa ser definida e seguida para apps (principalmente apps do sistema) para decidir como os tipos de build e as expectativas de lançamento afetam a saída do registro.

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

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

Classe Finalidade
android.telephony.Rlog Geração de registros de rádio
android.util.Log Geração de registros de apps gerais
android.util.EventLog Geração de registros 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 disponíveis de registros do sistema.

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) correspondente ao syslog do kernel do Linux que controla o buffer printk e syslog(3) correspondente ao registrador geral do sistema. O Android usa a biblioteca liblog para registros gerais do sistema.

O liblog fornece wrappers para os grupos de sublogs usando o seguinte formulário 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 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 que são preferidas em relação ao uso direto de liblog, conforme mostrado abaixo:

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

Figura 8:bibliotecas de registros de nível superior.

Aproximações de várias pilhas

Devido a diferenças na granularidade e na intenção do 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 registros de erros não são uma correspondência 1:1:

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

Figura 9. Nível de erro no registro Java padrão em comparação com o registro do 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 um guia aproximado de mensagens de nível, 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 fornecem uma indicação do local aproximado de um usuário.

A política de registro e os detalhes aceitáveis precisam ser tratados como parte da análise 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 solicitar 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 do sistema nativo (UID < APP_UID).
    • Usa DropBoxManager
    • Acessando apenas o buffer do 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 de acesso.