Quais são alguns padrões e anti-padrões de log de aplicativos? [fechadas]

64

Recentemente, tive que investigar um problema de campo para o nosso aplicativo corporativo de grande porte. Fiquei horrorizado com os registros que tive que vasculhar na tentativa de encontrar o problema e, no final do dia, os logs não ajudaram a identificar / isolar o bug.

Nota: Eu entendo que nem todos os bugs podem ser descobertos através de logs. Isso não muda o fato de que os logs são horríveis.

Existem alguns problemas óbvios com o nosso registro que já podemos tentar corrigir. Eu não quero listar esses aqui e não posso simplesmente mostrar nossos arquivos de log para que você possa dar conselhos sobre o que fazer.

Em vez disso, a fim de avaliar o quão ruim estamos fazendo na frente de registro, eu gostaria de saber:

  1. Quais são algumas diretrizes , se houver, quando se trata de registrar para um aplicativo, especialmente um aplicativo grande.
  2. Existem padrões que devemos seguir ou antipadrões de que devemos estar cientes?
  3. Isso é importante para corrigir ou isso pode ser corrigido ou todos os arquivos de log são simplesmente enormes e você precisa de scripts suplementares para analisá-los?

Nota: usamos log4j.

    
por c_maker 04.10.2011 / 22:24
fonte

9 respostas

53

Alguns pontos que minha prática se mostraram úteis:

  • Mantenha todo o código de registro em seu código de produção. Possibilidade de habilitar logging mais / menos detalhado na produção, preferencialmente por subsistema e sem reiniciar seu programa.

  • Faça registros fáceis de analisar por grep e a olho nu. Atenha-se a vários campos comuns no início de cada linha. Identifique tempo, severidade e subsistema em todas as linhas. Formule claramente a mensagem. Torne cada mensagem de log fácil de mapear para sua linha de código-fonte.

  • Se ocorrer um erro, tente coletar e registrar o máximo de informações possível. Pode demorar muito, mas está tudo bem, porque o processamento normal falhou de qualquer maneira. Não ter que esperar quando a mesma condição ocorre na produção com um depurador conectado é inestimável.

Os registros são necessários principalmente para monitoramento e solução de problemas. Coloque-se no lugar de um solucionador de problemas e pense no tipo de registros que gostaria de ter quando algo errado está acontecendo ou aconteceu na calada da noite.

    
por 05.10.2011 / 01:20
fonte
27

Meu recurso público favorito para as diretrizes de registro são Melhores práticas do JCL do Apache .

Best practices for JCL are presented in two categories: General and Enterprise. The general principles are fairly clear. Enterprise practices are a bit more involved and it is not always as clear as to why they are important.

Enterprise best-practice principles apply to middleware components and tooling that is expected to execute in an "Enterprise" level environment. These issues relate to Logging as Internationalization, and fault detection. Enterprise requires more effort and planning, but are strongly encouraged (if not required) in production level systems. Different corporate enterprises/environments have different requirements, so being flexible always helps...

Apesar da segmentação do JCL, eles parecem ser genéricos o suficiente para serem adotados para o registro em geral.

  • Minhas "diretrizes" pessoais para o registro em log é que, no nível de depuração, tento tornar meus registros lidos como uma história - com lógica compreensível e detalhes suficientes (mas não sobrecarregados).

O anti-padrão mais famoso é provavelmente "engolir exceções" - basta procurar na Web por isso.

Quanto aos enormes arquivos de registro, na minha prática, esse era o caso normal. E sim, scripts complementares como você os chama e / ou ferramentas como Chainsaw também parecem normal para mim.

  • Acima não significa que você sempre deve colocar todos os logs em um arquivo enorme. Às vezes, pode ser útil gravar / copiar alguns logs para separar arquivos. Por exemplo, em meu projeto recente, pessoal de controle de qualidade pediu arquivos dedicados para dados de métricas e temporização e para relatórios breves sobre as operações do sistema. Eles disseram que se beneficiariam disso e o dev o fez (o benefício do arquivo de relatórios breves acabou sendo significativo).

PS. Em relação aos antipadrões, outros que vêm à mente são "inundações" e mensagens sem sentido.

  • Eu chamo de flooding quando vejo várias mensagens semelhantes provenientes de um loop com muitas iterações. Para mim, a inundação é irritante o suficiente para tentar me livrar dela quando eu a detecto no código-fonte. Geralmente, o aprimoramento requer alguma arte - porque, bem, as coisas que acontecem dentro do loop podem ser interessantes. Quando não tenho tempo para melhorar ainda mais, tento pelo menos alterar o nível de registro dessas mensagens para o mais baixo, para facilitar a filtragem.

  • Mensagens sem sentido parecem ser lixo bastante popular. Eles parecem inofensivos quando lidos no código-fonte - eu acho que é preciso passar pela dificuldade de analisar a saída de depuração parecida com ...

    step #1
    step #2
    step #3
    

    ... para apreciar profundamente sua fealdade inerente. Minha heurística favorita para detectar esse tipo de problema no nível do código-fonte (proposta pelo colega em um dos meus projetos anteriores) é calcular o número de ocorrências de símbolo de espaço em literais de string usados no registro. Na minha experiência, os espaços zero garantem basicamente que a declaração de registro é sem sentido, um espaço também é um bom indicador do problema em potencial.

por 04.10.2011 / 22:41
fonte
27

Eu trabalho com sistemas críticos de segurança em tempo real e a criação de log é muitas vezes a única maneira de pegar bugs raros que aparecem uma vez em uma lua azul a cada 53 terça-feira quando é lua cheia, se você me entende. Isso faz com que você fique obcecado com o assunto, então eu peço desculpas agora se começar a fazer espuma na boca. O seguinte foi escrito para logs de depuração de código nativo, mas a maior parte também é aplicável ao mundo gerenciado ...

Use arquivos de log de texto. Parece óbvio, mas algumas pessoas tentam gerar arquivos de log binários: isso é simplesmente idiota porque não preciso procurar uma ferramenta de leitura quando estou em campo. Além disso, se o texto e a depuração forem detalhados, há uma boa chance de o engenheiro de campo ler o arquivo e diagnosticar o problema sem precisar voltar para mim. Todo mundo ganha.

Eu projeto sistemas que são capazes de registrar praticamente tudo, mas eu não ligo tudo por padrão. As informações de depuração são enviadas para uma caixa de diálogo de depuração oculta que marca a data e a saída para uma caixa de listagem (limitada a cerca de 500 linhas antes da exclusão) e a caixa de diálogo permite interrompê-la, salvá-la em um arquivo de log ou desviá-la para um depurador conectado. Esse desvio me permite ver a saída de depuração de vários aplicativos todos perfeitamente serializados, o que pode ser um salva-vidas às vezes. Eu usei para usar os níveis de registro numérico (quanto mais alto você definir o nível, mais você capturará):

off
errors only
basic
detailed
everything

mas isso é inflexível demais - à medida que você se aproxima de um bug, é muito mais eficiente ser capaz de se concentrar exatamente no que precisa, sem ter que percorrer toneladas de detritos, e pode ser um tipo específico de transação ou operação que causa o erro. Se isso exige que você ligue tudo, você está apenas fazendo o seu próprio trabalho mais difícil. Você precisa de algo mais refinado.

Então, agora estou no processo de alternar para o log com base em um sistema de sinalização. Tudo o que é registrado tem um sinalizador detalhando que tipo de operação é, e há um conjunto de caixas de seleção que me permitem definir o que é registrado. Normalmente, essa lista é assim:

#define DEBUG_ERROR          1
#define DEBUG_BASIC          2
#define DEBUG_DETAIL         4
#define DEBUG_MSG_BASIC      8
#define DEBUG_MSG_POLL       16
#define DEBUG_MSG_STATUS     32
#define DEBUG_METRICS        64
#define DEBUG_EXCEPTION      128
#define DEBUG_STATE_CHANGE   256
#define DEBUG_DB_READ        512
#define DEBUG_DB_WRITE       1024
#define DEBUG_SQL_TEXT       2048
#define DEBUG_MSG_CONTENTS   4096

Este sistema de registro é fornecido com a versão release , ativado e salvando no arquivo por padrão. É tarde demais para descobrir que você deveria ter logado APÓS o bug ter ocorrido, se esse bug só ocorrer uma vez a cada seis meses em média e você não tiver como reproduzi-lo. O log que funciona apenas com compilações de depuração é apenas. avião. mudo.

O software geralmente vem com ERROR, BASIC, STATE_CHANGE e EXCEPTION ligados, mas isso pode ser alterado no campo através do diálogo de depuração (ou uma configuração do registro / ini / cfg, onde essas coisas são salvas).

Ah, e uma coisa - meu sistema de depuração gera um arquivo por dia. Suas necessidades podem ser diferentes. Mas certifique-se de que seu código de depuração inicie todos os arquivos com a data, versão do código que você está executando e, se possível, algum marcador para o ID do cliente, localização do sistema ou o que for. Você pode obter uma mistura de arquivos de log vindos do campo, e você precisa de um registro do que veio de onde e qual versão do sistema que eles estavam executando, que está nos dados em si, e você não pode confiar no cliente. / engenheiro de campo para lhe dizer qual versão eles têm - eles podem apenas dizer-lhe qual versão eles pensam que eles têm. Pior, eles podem relatar a versão exe que está no disco, mas a versão antiga ainda está em execução porque eles se esqueceram de reinicializar após a substituição. Faça seu código dizer você mesmo.

Por último, você não quer que seu código gere seus próprios problemas, então coloque uma função timer para limpar os arquivos de log depois de tantos dias ou semanas (apenas verifique a diferença entre o tempo agora e a hora da criação do arquivo). Isso é aceitável para um aplicativo de servidor que é executado o tempo todo, em um aplicativo do lado do cliente que você pode obter com a limpeza de dados antigos quando você inicializa. Normalmente, depois de 30 dias, em um sistema sem visitas frequentes de engenheiros, talvez você precise deixar mais tempo. Obviamente, isso depende do tamanho dos arquivos de log também.

    
por 06.10.2011 / 00:42
fonte
11

Registre a exceção apenas uma vez!

Um dos pontos problemáticos mais comuns que eu notei é registrar e relançar uma exceção. Como resultado, os arquivos de log contêm as mesmas exceções várias vezes em vários níveis de pilha.

    
por 05.10.2011 / 19:44
fonte
5

Aqui está um antipadrão: Criando duas dúzias de campos "genéricosvariaveis" em uma tabela de banco de dados para rastrear qualquer coisa concebível e, em seguida, ter 88 (e contando) diferentes valores enum para diferentes tipos de logs.

    
por 05.10.2011 / 19:08
fonte
4

Minha experiência com registros é melhor: mas seja consistente o suficiente para torná-lo filtrável por máquina e seja capaz de configurar um nível de gravidade para cada componente de seu aplicativo individualmente.

Além disso, é muito difícil prever qual registro você precisará para encontrar um bug futuro. A maioria dos lugares óbvios para registrar erros é corrigida antes de o produto sair pela porta. Não é incomum que o resultado de um relatório de bug seja que você acabou de adicionar o registro para ajudar a diagnosticar se isso acontecer novamente.

    
por 05.10.2011 / 00:51
fonte
2

Algumas notas do lado operacional da casa aqui:

1) Verifique se os logs são configuráveis localmente, de preferência com uma ferramenta não mais pesada que um editor de texto. Na maioria das vezes, não queremos obter logging no nível do TRACE, mas adoramos poder ativá-lo.

2) Se possível, certifique-se de que os logs podem ser lidos com uma ferramenta não mais pesada que um editor de texto. Nada é pior do que ter que ir em uma busca de ferramenta em uma hora estranha quando o sistema de produção está falhando.

    
por 06.10.2011 / 01:14
fonte
1

De minha própria experiência trabalhando com aplicativos da Web:

(& considerando o armazenamento é muito barato agora)

  • Registre o máximo possível de informações disponíveis (no momento).
  • Eu sempre incluo DateTime.Now nas minhas sequências de log.
  • Eu sempre (se for possível) registre o tempo de duração de alguma "ação" específica.
  • Seja consistente com suas sequências de log. Desde sempre eu uso esse tipo de padrão:

    • "[Info X] [Informação Y] [Informação Z] [etc.]"
por 05.10.2011 / 09:49
fonte
1

Além do stacktrace, registre o estado atual do aplicativo e a entrada.

Software é determinístico, esses dois geralmente são a única coisa que você precisa para reproduzir o bug. Armazenar o estado completo pode, em alguns casos, ser problemático, portanto, maneiras de reproduzir o estado atual, por exemplo, entradas anteriores, também são boas.

É claro que mais dados são sempre melhores, mas no mínimo esses dois são um bom começo para as falhas mais fáceis.

    
por 05.10.2011 / 21:38
fonte

Tags