Apresentacao log

954 views

Published on

  • Be the first to comment

  • Be the first to like this

Apresentacao log

  1. 1. E exceções ! Autor: Pedro H. F. S. Diniz Grupo de GIS, Tecgraf
  2. 2. Sobre esta apresentaçãoLogs ● O que é e porque é importante ● Níveis de log ● Appenders ● Onde e quando devemos logar ● Estudo de caso ● Ferramentas que usamos hoje? ● Tem coisa melhor? ● Log assíncrono? ● Boas práticas sobre o nosso código
  3. 3. Sobre esta apresentaçãoExceção● O que é?● Tipos de exceção● Classificação● Quando lançar?● Quando tratar?● Boas práticas● Fique Atento!
  4. 4. O que é● É a história de vida do sistema● É uma instrução do código que grava informações de execução em algum lugar (email, arquivo, jms, banco de dados, etc..)● É a melhor maneira de se identificar um problema em produção● É uma ferramenta para realizar auditoria no sistema● É a ferramenta mais eficaz para que o cliente consiga rodar a manter a aplicação sem a intervenção dos desenvolvedores
  5. 5. Porque é importantePense que sua aplicação agora está fora do ambiente de desenvolvimento -não está mais rodando na sua ide favorita e muito menos disponível paradebug.É nessa hora que você irá percebeber a importância dos logs. Depois de lerinúmeras linhas de log tentando identificar o que há de errado na aplicaçãovocê vai entender que não é uma tarefa trivial.Daí você se pergunta: com toda a minha experiência e conhecimento, é isso oque eu estou destinado a fazer? Encontrar uma agulha em um palheiro delogs?Ou no nosso caso, delegando para o cliente (como na petrobras por exemplo),que possui uma equipe de suporte e manutenção que igualmente nosamaldiçoa pela gratificante e entediante tarefa!Ou pior ainda, ter que levar até o cliente os arquitetos do software e fazer elesse involverem, enquanto eles pensam a cada minuto como é um erro gastar oseu tempo e habilidade com isso.
  6. 6. Níveis de logEm geral são: - Trace - Debug - Info - Warning - Error -Fatal
  7. 7. Níveis de logTraceTraça toda entrada e saída de método, indicando os parâmetros. Geralmente só é ativadatemporariamente. O que diferencia esse nível do nível debug é que em produção o trace quase nuncaprecisa ser utilizado.public int sumNumbers(int first, int second){ log.trace("sumNumbers({},{})", first, second); return first+second;}DebugGrava todo e qualquer event ocom informações importantes sobre o funcionamento da aplicação.Geralmente é ativada em produção para ajudar os desenvolvedores com informações extras.public int sumNumbers(int first, int second){ log.debug("sumNumbers() returned {}", first+second); return first+second;}
  8. 8. Níveis de logInfoInforma que algum evento importante da aplicação foi concluído. Em um mundo ideal, tantoadministradores como usuários avançados deveriam ser capazes de entender o que a aplicação estáfazendo através desses logspublic String importXml(String url){ String xml = null; Connection connection = null; log.info("connecting to {}", url); connection = connectToUrl(url); log.info("importing xml"); xml = importXml(connection); log.info("xml imported successfully"); return xml;}WarningMensagem indicando que embora o processo possa continuar, algo está fora do esperado a atençãodeverá ser redobrada. Ex.while ((nextLine = reader.readNext()) != null) { if (!StringUtil.toString(nextLine).trim().isEmpty()) { readLine(nextLine); } else { logger.warn("Foi lida uma linha em branco do csv, remova linhas sem conteúdo."); }}
  9. 9. Níveis de logErrorAlgum problema intolerável aconteceu, que precisa ser investigado imediatamente. Nenhum sistemadeve tolerar eventos desse nível. Ex. NullPointerException, Connectionif (!FTPReply.isPositiveCompletion(reply)) { client.disconnect(); logger.error("FTP server refused connection. Reply was {}", reply); return false;}FatalEventos severos que impedem o funcionamento do aplicação. Após esse erro a aplicaçãopossivelmente irá parar de responder.try { new GlobalsatDriverFtp().run();} catch (Exception e) { logger.fatal("Error running GlobalsatDriver: ", e); e.printStackTrace();}
  10. 10. Níveis de logTrace x DebugO trace deve ser usado apenas para indicar em qual método o sistema está passando, enquanto odebug indica estados do sistema. O trace não deve indicar valor de variáveis.Se existe a possibilidade de usar esse log em produção então não é trace. O trace é utilizado quaseque exclusivamente em ambiente de desenvolvimento somente.
  11. 11. Níveis de logDebug x InfoO debug contém informações pertinentes ao desenvolvedor do sistema.O Info contém informações pertinentes aos usuários do sistema, auditores, equipe de suporte,desenvolvedores e outros...
  12. 12. Níveis de logInfo x WarningO Info indica etapas do sistema que não requerem intervenção do usuário nem do desenvolvedor. Emgeral são apenas informações sobre o que está acontecendo por trás dos panos.O Warning indica que ocorreu um comportamento inesperado, e embora o sistema possa continuargeralmente espera-se investigação do ocorrido.
  13. 13. Níveis de logWarning x ErrorO Warning indica que ocorreu um comportamento inesperado mas mesmo assim o sistemaconseguiu continuar. Seria interessante por parte do desenvolvedor corrigir o problema.O Error indica que ocorreu um comportamento inesperado no código em execução e o sistema nãoconseguiu continuar. O desenvolvedor precisa corrigir o problema.
  14. 14. Níveis de logError x FatalO Error indica que um bloco de código foi abortado e não pôde continuar.O Fatal indica que o sistema foi abortado e não pôde continuar.
  15. 15. AppendersCommon Appenders FileAppender - Escreve os logs em um arquivo RollingFileAppender - Estende o FileAppender permitindo backups a medida que o arquivoatinge um tamanho limite DailyRollingFileAppender - Estende o FileAppender para que o roll em arquivo possa serdefinido por alguma frequência dada pelo usuário. ConsoleAppender - Escreve os logs no System.out ou System.errorNetwork Appenders SocketAppender - Envia os logs para um log server remoto SocketHubAppender - Envia os logs para um conjunto de log servers remotos JMSAppender - Publica logs em um tópico JMS. NTEventLogAppender - Registra log no sistema de eventos do sistema operacional
  16. 16. AppendersSpecial Appenders AsyncAppender - Faz com que um appender seja asincrono, permitindo que a aplicaçãocontinue a rodar independentemente. ExternallyRolledFileAppender - Permite que o sistema escuta uma porta do computador e aoreceber mensagem execute um rollover no log. JDBCAppender - Salva os logs em um banco de dados LF5Appender - Envia log para o console de uma aplicação java em swing. NullAppender - Útil para testes internos ou benchmarking SMTPAppender - Envia e-mail quando o log especificado for lançado pelo sistema. SyslogAppender - Envia os logs para um syslog daemon remoto. TelnetAppender - Envia log pelo telnet WriterAppender - WriterAppender anexa eventos de log a um Write ou OutputStreamdependendo da escolha do usuário.
  17. 17. Onde e quando devemos logarPrimeiro: identifique o público alvo ● Auditores ● Transações que envolvem dinheiro ● Equipe de suporte ao sistema dentro do cliente (TI Petrobras) ● Segurança, detectar ataques de DoS, etc.. ● FacilitarSegundo: identifique para onde irá o log ● Arquivo (desenvolvedores) ● Jms ● Email (Segurança) ● Banco de dados (auditoria) ● ETC...Por último: ● Se interessa ao público alvo, identifique o nível em que o log se adequa e logue!
  18. 18. Estudo de CasoComo todo log é uma história, no nosso caso iremos contar uma história dos Simpsons
  19. 19. Estudo de CasoO diretor da escola ligou para Marge e avisou que Bart anda matando aula. Ele disse que na semanapassada Bart faltou 2 vezes e que isso é preocupante pois suas notas não estão boas.Marge preocupada, teve uma idéia de como descobrir o que estava acontecendo para mandar Bartde volta à escola.
  20. 20. Estudo de CasoMarge deu de presente um novo relógio para o Bart, e sem que ele saiba, o relógio irá enviar para oemail da Marge um log com uma foto do local e posição gps de onde ele está a cada minuto.
  21. 21. Estudo de CasoBart, feliz com seu novo relógio do Krusty, cola o relogio antes de dormir e o relógio começa afuncionar.Assim que Bart acorda de manhã para ir à escola o relógio faz seu primeiro log ((info))Esse log é importante pois indica se Bart está com problema para acordar no horário.
  22. 22. Estudo de CasoApós tomar seu café da manhã, Bart sai de casa para ir para a escola.Nesse momento o relógio faz mais um log ((info))Esse log será importante pois indica se ele se atrasa para pegar o ônibus ou sai no horário certo.
  23. 23. Estudo de CasoAo invés de pegar o ônibus, bart vai para a escola de skate.O relógio mais uma vez faz um log com foto ((warn))Esse log será importante pois indica que algo não está indo conforme o esperado, embora não sejanecessariamente um problema.
  24. 24. Estudo de CasoA cada rua que Bart passa, o relógio realiza mais logs ((trace)).O cada casa que o Bart passa o relógio faz log ((debug)) novamente , indicando quem mora na casa.Esse log será importante pois indica que ele passou na casa do Milhouse. Agora a mudança de rotinafaz começa a fazer sentido.
  25. 25. Estudo de CasoComo Bart passa pela escola e segue em frente o sistema realiza mais um log ((error)).Esse log é fundamental, o objetivo é a escola se ela não parou então algo está errado. Isso não podeacontecer.
  26. 26. Estudo de CasoApós passar pela escola Bart para em frente a um show de rock. Nesse momento o relógio faz maisum log ((fatal)).Esse log é o log final, de fato Bart não foi para escola. Agora não faz mais sentido fazer log, Margeprecisará intervir.
  27. 27. Estudo de CasoConclusão:O log precisa contar uma história. E essa história precisa estar clara para que quem lê consigaentender não só os acontecimentos, mas a sua importância, como corrigi-los e como evitá-los.
  28. 28. Ferramentas que usamos hoje?Aqui no Tecgraf usamos apenas o Log4j (1.2.x) ● Ferramenta para java criada pela apache. ● Foi quem primeiro definiu padrões de log em java ● A versão 1.x apesar de estável não é mais ativamente desenvolvida ● Em geral todo log é feito concatenando strings. Ex. log.error("Fulano "+x+" disse "+y) ● Para debug usa-se if(logger.isDebugEnabled()), toda vez. ● Tem bons appenders.Commons login (JCL) ● Jakarta Commons logging. ● Não faz log, apenas define um façade para apis de log. ● Apesar de estável não é mais ativamente desenvolvida ● É muito comum encontrarmos essa biblioteca causando problemas de classloader em servidores.
  29. 29. Tem coisa melhor?LOGBack ● Ferramenta java criada pelo desenvolvedor do Log4j 1.x ● Permitir mudar o nível de log sem reiniciar a aplicação ● É o novo padrão em log ● Todos recomendam logback ao invés de log4j 1.x ● Mais rápida que o log4j 1.x ● Já foi criado pensando no sl4j ● Melhor recuperação em falhas de I/O ● Mais e melhores opções de filtro ● Indica no log em que jar está a classe que gerou a exceção ● Não usa concatenação de string para log. Ex. log.error("Fulano {} disse {}", x, y); ● Não precisa de if(logger.isDebugEnabled()); ● Tem bons appenders ● Permite agrupar logs para que sejam exibidos em ordem ● Permite separar log por usuário do sistema ou outra variável qualquerslf4j ● Ferramenta java criada pelo desenvolvedor do Log4j 1.x ● Não faz log, apenas define um façade para apis de log. ● Todos recomendam slf4j ao invés de commons-logging ● Até a apache utiliza o slf4j ● Possui um jcl-over-slf4j para não criar conflito com o jcl e redirecionar para o slf4j ● Possui um log4j-over-slf4j para não criar conflito com o log4j e redirecionar para o slf4j ● Possui um sl4j migrator tool que migra automaticamente o seu código de log4j para sl4j
  30. 30. Tem coisa melhor?Log4j (2.x.beta) ● Ferramenta para java criada pela apache. ● Substitui e o log4j 1.x ● Foi criada para ter tudo o que o logback tem. ● Resolve alguns problemas de arquitetura do logback ● Oferece mais funcionalidades que o logback ● As chances são de que ela seja o novo padrão, ao invés do logback
  31. 31. Log asíncrono?● Acaba sendo mais rápido para a aplicação● Faz log sem bloquear o código principal ● Especialmente eficaz em aplicações multithread uma vez que váriasthreads precisarão escrever no mesmo arquivo● Extremamente recomendável quando a aplicação tem um número elevado de logs.● Não é suportado em containers J2EE, para esses caso usa-se o JMSAppender
  32. 32. Boas práticas sobre o nosso códigoO catch foi criado para tratar exceções e não para fazer log. Neste caso o idealseria propagar a exceção.catch (Exception e) { logger.error("", e); return false;}
  33. 33. Boas práticas sobre o nosso códigoPor utilizarmos o log4j 1.x nosso logs são cheios de contaneção. Devemosatualizar a nossa biblioteca para usar novas versão de log e evitar esseoverhead desnecessário.if (v == null || DatabaseConstants.VEHICLE_STATUS_INACTIVE.equals(v.getStatus())) { logger.info("Discarding planning " + plannedTrip.getPlanningNumber() + ". Vehicle " + plate + " is not registered or inactive."); return true;}
  34. 34. Boas práticas sobre o nosso códigoUse logs enxutos. O ideal é que cada mensagem de log não passe de umalinha de texto.PS: Repare que novamente a exceção não é tratada.catch (InvalidParameterException e) { logger.warn(buildVDBDocWarnMessage(meta.getCanonicalName()), e);}
  35. 35. Boas práticas sobre o nosso códigoRepare que a concatenação de strings também faz com que a leitura do logganhe complexidade.catch (IOException e) { logger.error("Error while creating the bean" + clazz + " / " + metadataName + " in" + getClass().getSimpleName(), e);}catch(Exception e){ logger.error("Login denied for user "+user.getLogin());}
  36. 36. Boas práticas sobre o nosso códigoCatch de Exception não pode ser feito:Primeiro porque você não sabe que erro é esse portanto não tem como tratarSegundo porque você impede o recibemto da exceção para quem sabe tratá-la.PS: Mais uma vez a exceção não é tratada e se perde no códigotry{ client.disconnect();}catch(Exception e){ logger.error(e);}
  37. 37. Boas práticas sobre o nosso códigoNão acesse variáveis dentro das mensagens de log, elas podem estar nulas.A última coisa que faltava é o sistema parar de responder pq houveNullPointerException ao criar uma mensagem de log._logger.trace("Ended task " + task.getName() + " (progress rate = " + _currentProgressRate +"%)");try {processingService.saveResults(getUserContext(), env);} catch (IOException e) {LOGGER.error("Error saving processing results for moving object: " + moCache.getMovingObject().getIdentifier(), e);throw e;}_logger.debug("created start node id " + startNode.getId());
  38. 38. Boas práticas sobre o nosso códigoParábens para o nosso código que usou corretamente o if(debug).if (debug) {logger.debug("andAnyAttributeLocation()-" + clause);}
  39. 39. Boas práticas sobre o nosso códigoPena que não é sempre assim, a maior parte do nosso código não usa o if(debug).Esse tipo de overhead pode ser evitado se usarmos o LogBack ou slf4j.PS: Utilize logs de no máximo uma linha.PS: Não acesse variáveis dentro das mensagensString debugLine = "Received httpData Version: " + getVersionNumber() + "- deviceId: "+ id[0] + ", cont: " + cont + ", time: "+ sessionTime.getTime() + ", httpData: " +msgsDebug;if (!hasInvalidCharacters(debugLine)){ logger.debug(debugLine);}else{ logger.debug("Recebida requisição que contém caracteres inválidos.");}
  40. 40. Boas práticas sobre o nosso códigoEmbora muito comumn, fazer catch de RuntimeException não é uma boaprática.Se o seu código tem muito tratamento de RuntimeException isso é um sinal deque ele não está estável.try{ connect();}catch(NullPointerException npe){ logger.error("Erro ao conectar", npe);}
  41. 41. Dúvidas?
  42. 42. Exceção em JAVA
  43. 43. O que é?● É um aviso indicando que o código em execução encontrou um comportamento impeditivo com o qual ele não sabe lidar.● É uma subclasse de "java.lang.Throwable".● Contém informações sobre o comportamento encontrado para que o código no topo da hierarquia possa tratá-lo ou seguir por outro caminho.
  44. 44. Tipos de exceção
  45. 45. ClassificaçãoChecked ExceptionsSão subclasses de Exception. Representam exceções onde o desenvolvedor consegue se recuperar.Embora indiquem um comportamento inesperado, não são necessariamente um erro e não impedemo sistema de continuar.Ex. FileNotFoundException, ParseException , ...Unchecked ExceptionsSão subclasses de Error ou RuntimeException. Representam o inverso das Checked Exceptions.Quando essas exceções ocorrem elas indicam que existe um erro no código e o sistema ou bloco decódigo não pode continuar.Geralmente essas exceções fazem com que o sistema seja desligado.Ex. NullPointerException, StackOverflowError, OutOfMemoryError, NoClassDefFoundError,IllegalArgumentException
  46. 46. ClassificaçãoPorque vemos mais classes que herdam de Exception do que Error ou RuntimeException?Não vemos muitas classes que herdam de Error porque por convenção somente a JVM pode criar elançar classes que herdam de Error.Não vemos muitas classes que herdam de RuntimeException porque, como elas não precisam serdeclaradas, o sistema não fica preparado para que ela aconteça.Relatos de desenvolvedores que usaram bastante RuntimeExceptions, explicam que todas as vezesque a aplicação entrava em produção apareciam erros graves que bloqueavam o sistema.O que provavelmente já teria sido tratado e não bloquearia o sistema se tivesse sido declaradocorretamente no throws.Na comunidade Java há quem diga que os sistemas deveriam apenas usar apenas Exception, e queRuntimeException e Error deveriam ser exclusivos da JVM.
  47. 47. Quando lançar?THROW EARLY catch lateQuanto mais informação houver no stack trace, melhor. Portanto ao invés de deixar exceções comoNullpointerException acontecerem em locais pouco informativos, detecte o problema e lance aexceção onde se encontra o verdadeiro problema.public void readPreferences(String filename) throws IllegalArgumentException{ if (filename == null) { throw new IllegalArgumentException("filename is null"); } //if //...perform other operations... InputStream in = new FileInputStream(filename); //...read the preferences file...}
  48. 48. Quando tratar?throw early CATCH LATEA exceção deve ser lançada o suficiente para que quem tem mais informação possa tratá-la. Um erromuito comum é tratar a exceção assim que ela acontece, impedindo que o sistema trate-a da maneiraapropriada. Propague a exceção para quem pode tratá-la.public void readPreferences(String filename){ //... InputStream in = null; // NÂO FAÇA ISSO!!! try{ in = new FileInputStream(filename); }catch (FileNotFoundException e) { logger.log(e); return; } in.read(...); //...}
  49. 49. Boas práticasValide argumentos quando necessárioMas também não precisa fazer isso em todos os métodos!Valide os inputs nos métodos que já originaram bugs, assim você irá evitar que esses bugs ocorramnovamente.if ( null == variable || variable.isEmpty()){ throw new NullPointerException("the variable cannot be null at this point");}
  50. 50. Boas práticasEvite grandes blocos de try catchSepare os try catch por escopo, assim o código fica mais fácil de entender e cada bloco irá pegasapenas as exceções pertinentes a tarefas pontuais. Considere dividi-los em métodos diferentes.try{ s = pegarNomeDoArquivo(); f = lerArquivo(s); v = validarArquivo(f);}catch(FileNotFoundException fne){}try{ x = fazerParseDoArquivo(f); z = modificarXml()}catch(ParseException pe){}
  51. 51. Boas práticasSe não vai tratar, propague!Não faça catch em exceções apenas para encher log. O catch foi feito para tratar exceções e não parafazer log. Dessa forma você inpedirá que a exceção seja tratada por quem sabe como tratá-la.try{ s = pegarNomeDoArquivo(); f = lerArquivo(s); v = validarArquivo(f);}catch(Exception e){ log.error("Error ao ler arquivo", e);}
  52. 52. Boas práticasCuidado para não engulir exceçõesNo bloco abaixo caso aconteça um FileNotFoundException veremos apenas um NullPointerExceptiongerado pelo descuidado finally. O correto seria verificar se "input" é nulo no finally.InputStream input = null; try{ input = new FileInputStream("myFile.txt"); //do something with the stream } catch(IOException e){ throw new WrapperException(e); } finally { try{ input.close(); } catch(IOException e){ throw new WrapperException(e); } }
  53. 53. Boas práticasEnriqueça as exceções lançadasAproveite a propagação das exceções para enriquecê-laspublic void parseXml(String filePath) throws ParseException, IOException{ try{ File f = leArquivo(filePath); fazParse(f); }catch(IOException ioe){ throw new IOException("Parse falhou pois arquivo não existe {}", filePath, ioe); }}public File leArquivo(String filePath) throws IOException{ //Irá gerar uma exceção return new File(filePath);}
  54. 54. Fique atento!No JAVA 7 haverá uma nova forma de tratar exceçõesPara evitar o uso do try catch dentro do finally o java 7 criou o try-with-resources. Assim qualquer classe queherde de java.lang.AutoCloseable é fechada pela java automaticamente no try catchTry-with-resourcesANTIGO NOVOOldResource res = null; try { try(NewResource res = new NewResource("Res1 closing")){ res = new OldResource(); res.doSomeWork("Listening to podcast"); res.doSomeWork("Writing"); } catch(Exception e){ } catch (Exception e) { System.out.println("Exception"); System.out.println("Exception"); } } finally{ try { res.close(); } catch (Exception e) { System.out.println("Exception"); }}
  55. 55. Dúvidas?
  56. 56. Referências● http://architects.dzone.com/articles/high-performance-and-smarter● http://www.javacodegeeks.com/2011/01/10-tips-proper-application-logging.html● http://javarevisited.blogspot.com.br/2011/05/top-10-tips-on-logging-in-java.html● http://www.allapplabs.com/log4j/log4j_appenders.htm● http://logback.qos.ch/manual/appenders.html● http://www.javaworld.com/javaworld/jw-05-2004/jw-0510-logging.html?page=3● http://c2.com/cgi/wiki?LoggingBestPractices● https://wiki.base22.com/display/btg/Java+Logging+Standards+and+Guidelines● http://runjva.appspot.com/logging101/index.html● http://programmers.stackexchange.com/questions/112402/what-are-some-patterns-and-anti-patterns-of-application-logging● http://gojko.net/2006/12/09/logging-anti-patterns/● http://today.java.net/article/2006/04/04/exception-handling-antipatterns● http://www.wikijava.org/wiki/10_best_practices_with_Exceptions● http://tutorials.jenkov.com/java-exception-handling/index.html● http://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html

×