Como abordar a correção de um erro improdutível / que ocorre aleatoriamente?

11

Temos um site multilíngue no qual um bug foi descoberto há alguns dias. Ele exibia dados de outros idiomas em outro idioma e também a mistura de dados como idioma inglês foi selecionada, mas exibia dados de outros idiomas também na página e vice-versa. Ele está fazendo isso com pouca frequência, mas está presente no site. Passar pelo código também não ajuda, porque isso nem sempre ocorre.

Alguma sugestão para encontrar o problema em tempo hábil? Estou pedindo estratégias aqui.

maz3tt
fonte
4
começar a sondar o código para situações que permitirá que este bug acontecer (em vez de fazê-lo o contrário)
Imran Omar Bukhsh

Respostas:

20

O primeiro passo é tentar caracterizar o que pode causar esse tipo de problema. Como isso está relacionado à seleção do idioma correto para as seções do código, comece considerando o seguinte:

  • Como o idioma é detectado? É baseado em informações da solicitação HTTP? É baseado em informações da sessão? Ou em campos do banco de dados? Em essência, isso pode ser um problema relacionado a como o aplicativo seleciona o idioma de cada seção?
  • Como o idioma é exibido? Você está retirando de um arquivo de propriedades ou de um banco de dados? É possível que a referência ao idioma correto esteja se perdendo de alguma forma? O idioma misto que você vê sempre é o padrão para o site?
  • Existe uma correlação com o ambiente do cliente? Isso está relacionado ao primeiro marcador, mas vai um pouco mais longe. Eu tive problemas estranhos de renderização devido a proxies de cache a jusante. Normalmente, esses tipos de problemas são uma página inteira obsoleta ou que serve a página de uma pessoa para outros usuários (o que foi embaraçoso).
  • Você está usando um valor Thread Local? Se uma solicitação for tratada com mais de um thread, o valor local do thread terá informações diferentes com base no thread que está funcionando no momento. Em um ambiente de servidor da Web, você não pode assumir que o encadeamento no qual você iniciou o processamento será o mesmo encadeamento no qual você conclui o processamento - a menos que isso faça parte das especificações da sua plataforma. Os gravadores de servidor descobriram que, se reutilizarem um pequeno pool de threads e trabalharem em multiplex em pedaços, eles poderão lidar com mais solicitações simultaneamente. Mesmo se você tiver um encadeamento do início ao fim de uma solicitação, o servidor poderá multiplexar outras solicitações para esse encadeamento ao mesmo tempo. Em vez de locais de encadeamento, considere vincular esse valor aos atributos de solicitação ou sessão.

Agora, uma vez que você caracterizou as possibilidades do que pode dar errado, é hora para ter certeza de que os dados que você precisa para tentar descobrir o que fez de errado movimento.

  • Use registro profuso nas áreas problemáticas. Este é um lugar onde uma ferramenta como o Log4J ou o Log4Net pode realmente brilhar. Essa estrutura de registro, e outras similares, permitem que você aumente o registro para determinadas categorias, mantendo o ruído para todo o resto - tudo alterando um arquivo de configuração. Você deseja introduzir novas instruções de log para descobrir se o que você suspeita poderia ser o problema. Verifique também se seus logs de acesso HTTP têm todas as informações que você deseja sobre cada solicitação (cookies, parâmetros de cabeçalho http, etc.)
  • Tente simular o problema. Como isso acontece esporadicamente, como é a carga no servidor no momento em que ocorre? Você está sendo atingido por várias solicitações simultâneas de uma mistura de idiomas? Nesse caso, tente simular esse tipo de carga no seu ambiente de teste. Uma ferramenta semelhante ao JMeter pode ser o que você precisa. Você também deseja falsificar endereços IP para seus clientes falsos. Lembre-se de que os endereços IP são divididos em partes, para que você possa descobrir em que país / região o IP se baseia nos dois primeiros segmentos do endereço.
  • O problema será esporádico no ambiente de teste, mas à medida que você se restringe à sua causa real, pode distorcer os resultados para que isso aconteça com mais frequência do que na natureza. Além disso, você pode revisar com mais facilidade os arquivos de log e tentar aprender com eles.
  • É um processo iterativo, então seja paciente. Você precisa induzir o tipo de carga que você acha que irá reproduzir o erro, verificar os logs e refinar seus testes com base no que encontrar. O importante é identificar o problema , então resista ao desejo de fazer algumas correções simples que podem fazer com que o problema real aconteça com menos frequência.

Por fim, depois de restringir o problema ao ponto de saber como reproduzi-lo e o que o causa, escreva o menor teste automatizado possível para forçar o problema no código. Se você reduziu o problema a uma classe ou se um par de classes não estava funcionando corretamente corretamente, reproduza-o nesse nível. Você não precisa gerar 100 threads para fazer isso, basta fazer o menor teste que pode causar o problema 100% do tempo.

Agora você pode corrigi-lo e estar razoavelmente confiante de que não voltará a morder você novamente.

Berin Loritsch
fonte
10

O bug não é irreprodutível. Você ainda não descobriu como reproduzi-lo ainda.

Nenhum bug é aleatório, a menos que você esteja lançando uma exceção com base no valor de retorno de alguma instrução Random ().

Eu sei que isso pode parecer semântica, mas é reconfortante mentalmente contar isso para si mesmo.

É muito difícil e frustrante descobrir como reproduzir um bug que só acontece por causa de condições complexas de corrida ou algo assim.

Quanto à forma de encontrá-lo, eu ativaria / adicionaria alguns logs ao aplicativo em locais que pudessem fornecer mais informações.

Em seguida, diga às pessoas que estão vendo o bug (sejam Devs, controle de qualidade, usuários finais) que reportem assim que o veem com o horário em que ocorreu e, em seguida, consulte seus logs. Peça-lhes outras informações, assim como o bug só pode ocorrer devido à interação de vários sistemas diferentes ou devido a uma condição de corrida

Espero que você seja capaz de encontrar uma pista.

Gilles
fonte
mesmo chamadas aleatórias () não são verdadeiramente aleatórias, a menos que sejam derivadas de um gerador de ruído branco de hardware. Eles são psuedo-random, o que significa que os números são matematicamente distribuídos na ordem mais aleatória possível. Mas se você começar com o mesmo valor "semente", obterá a mesma resposta sempre.
Berin Loritsch
1
@Berin: eu sei.
Gilles
+1 em "você ainda não descobriu como reproduzi-lo". Todos os bugs têm uma causa raiz ou não aconteceriam.
Mike S
1
Ele não precisa ser desativado de forma aleatória (), coisas que dependem do tempo, especialmente aquelas que envolvem acesso inadequado a um recurso compartilhado, pode ser muito difícil de reproduzir.
Loren Pechtel
2
@ Gilles: Exceto que eles podem não ser determinísticos em qualquer coisa que você possa medir razoavelmente. (Say, exatamente quando alguma outra tarefa liberou da fatia de tempo.)
Loren Pechtel
5

Você pode tentar encontrar lugares no seu código onde reconheça que o problema ocorreu (parâmetros inconsistentes em um método, por exemplo), adicionar as verificações ao seu código e permitir que eles adicionem informações extras ao log de depuração (como um rastreamento de pilha, objetos adicionado à sessão etc.)

Fazendo isso com um pouco de sorte, você pode capturar informações sobre as ocorrências e deduzir o caminho de volta ao problema.

rsp
fonte
2

A automação deve ajudar, se forem os mesmos passos para reproduzir que às vezes falham, automatize isso e coloque-o em um loop. Execute 50.000 vezes e é muito provável que ocorra.

Kieren Johnstone
fonte
O evento não é aleatório, apenas parece aleatório. Isso pode fazer com que apareça, mas fornecerá muito pouca informação sobre o motivo de sua aparição.
21411 Josh K
1
@ Josh - Se ele não conseguir reproduzi-lo, pode ser uma boa maneira de fazer isso e obter um rastreamento de pilha com símbolos de depuração, por exemplo. I figura que é um grande primeiro passo - vê-lo em primeira mão
Kieren Johnstone
Você está assumindo que há uma pilha e que ela pode ser obtida. Ele não nos forneceu nenhuma informação técnica sobre o aplicativo ou sobre como é acessível para depuração nesse tipo de carga. Esta não é uma estratégia de depuração , mas sim com um martelo, tentando capturar o momento exato em que quebra.
21711 Josh K
@ Josh - minha experiência no mundo real me diz que a coisa mais valiosa na investigação / correção de um bug é vê-lo em primeira mão. Se é algo com o tempo que você pode ver, um rastreamento de pilha, algo nos logs ou qualquer outra coisa. Sempre que possível, ter problemas aparentemente aleatórios testados em loop me levou até lá muito rapidamente. Se você tiver uma idéia diferente, publique-a como resposta pelo amor de Deus - este é um método válido e uma resposta válida.
Kieren Johnstone
Discordo e acredito que a resposta de Berin é a maneira correta de resolver isso.
11139 Josh K
1

tente encontrar padrões para definir as condições que causam esse problema. Isso deve indicar as seções do seu código que falham (ou se comportam de maneira inconsistente).

jwenting
fonte
Sem brincadeira ..............
theringostarrs
0

Você consegue detectar quando o problema está ocorrendo? Nesse caso, você pode despejar informações com segurança sobre o estado do sistema nesse momento?

Se a resposta para essas duas perguntas for afirmativa, instrumente seu código para registrar o máximo de informações possível quando o erro realmente ocorrer e aguarde.

Isso não substitui o que os outros sugeriram (você ainda precisará raciocinar sobre como o código pode entrar no estado que está vendo), mas desde que não seja possível reproduzir o bug à vontade, é uma boa idéia não desperdiçar as ocasiões em que aparece.

jimwise
fonte