Édipo da Silva Souza
Pattern
"Patterns are formalized best practices that the programmer must implement
themselves in the application."
Introduction to Spring Framework (Acesso em: 25/09/2013)
http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/overview.html

Anti-Patterns
"Design anti-patterns are 'obvious, but wrong, solutions to recurring problems'."
Budgen, D. (2003). Software design. Harlow, Eng.: Addison-Wesley. p. 225. ISBN 0-20172219-4.

"...common approaches to solving recurring problems that prove to be ineffective. These
approaches are called antipatterns."
Scott W. Ambler (1998). Process patterns: building large-scale systems using object
technology. Cambridge, UK: Cambridge University Press. p. 4. ISBN 0-521-64568-9.


Error - Usado quando o processo não pode continuar. Considerados intoleráveis
pelo sistema.






Warn - Para eventos críticos, porem onde o processo pode continuar mas com
cuidados extras.






Null Pointer Exception
Banco de Dados indisponível
Falha com conexão remota

Utilizando cache por falta de conexão
Em modo administrador
Usuário sem senha.

Info - Deve permitir que administrador ou usuários avançados entendam
rapidamente o que a aplicação esta fazendo ou acabou de fazer.



Caixa de supermercado. "Caixa NºX" fechou uma compra no valor "R$Y“.
[Fulano] comprou uma passagem de [lugar X] para [lugar Y]


Debug - Elementos referentes a desenvolvimento, mas que podem ser
relevantes quando.






Valores recebidos ao entrar em um método
Valor de saída do método
Mudança de valor de variável

Trace - Informações detalhadas para o desenvolvedor. Recomendado utilizar
somente fora do ambiente de produção.



Valores de variável em determinados pontos
Log apenas para saber se tal linha executou


Informações legíveis para meros mortais
entenderem o que se passa.
 Anti-Pattern
log.debug(“Classe Beta1 lançou exceção 0x55”);

 Pattern
log.debug(“Classe UsuárioDAO lançou exceção senhaException”);



Não há necessidade de verificar se determinado
nível esta habilitado, o framework já faz isso.
Utilize apenas em conjunto com ‘else’, caso haja
a necessidade de sempre registrar algo.
 Anti-Pattern
if(log.isDebugEnabled())
log.debug(“Cliente registrado com sucesso.”);

 Pattern

if(log.isDebugEnabled())
log.debug(“Itens no checkout: {}”, compra.getItens());
else
log.info(“Nº de Itens no checkout: {}”, compra.getItens().size());
Ver Ex.


Certifique-se de não tentar registrar em seu
log um Null Pointer Exception
 Pattern
log.debug("Cliente com sobrenome: {}", cliente.getSobrenome());


Utilize sempre em um único log, informação
e valor
 Anti-Pattern
log.debug(“Cliente registrado com sucesso.”);
log.debug(cliente.getId());

 Pattern
log.debug(“Cliente registrado com sucesso: {}”, cliente.getId());

Ver Ex.





Registre informações fáceis para humano e
máquina lerem seus logs.
O separador utilizado também é importante
para facilitar o trabalho de um parser. Prefira
utilizar vírgulas ou tabs para separar valores
no log.
Evite utilizar mais de uma linha em um log.
 Pattern
log.debug(“Horário requisitado: {} ({})", new Date(ttl), ttl);
// Horário requisitado: Wed Apr 28 20:14:12 CEST 2010 (1272478452437)


Defina um padrão para seus logs
(Ex: data, level, thread, nome, mensagem)
 Pattern
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %-5level [%thread][%logger{0}] %m%n</pattern>
</encoder>
</appender>
Exemplo de definição de padrão no LogBack.

Ver Ex.


Registrar parâmetros recebidos e valor de
retorno para métodos importantes.
 Pattern
public String fazerAlgo(String a, int b, double c){
log.debug("iniciando fazerAlgo com a={}, b={} e c={}, a, b, c);
//processa várias coisas
log.debug("saindo de fazerAlgo com {}", resultado);
}


Caso sua exceção não faça o tratamento e
apenas relançe aquela exceção, fazer log
pode resultar em stackTrace duplicado.
 Anti-Pattern
}catch (Exception e){
log.error("IO exception", e);
throw new MyCustomException(e);
}

Ver Ex.


Não instanciar logger passando a classe como
String.
 Anti-Pattern
private final static Logger LOGGER = LoggerFactory.getLogger("com.ess.Usuario");

 Pattern
private final static Logger LOGGER = LoggerFactory.getLogger(Usuario.class);


Não instanciar o logger dentro de cada método,
crie uma instancia somente para a classe toda.
 Anti-Pattern
public void metodo() {
Logger logger = LoggerFactory.getLogger(Foo.class);
logger.info(“ok!");
}

 Pattern

private final static Logger LOGGER = LoggerFactory.getLogger(Vai.class);

public void metodo() {
LOGGER.info(“ok");
}


Interagir com sistemas externos pode resultar
num objeto de tamanho inesperado. Quando
em produção evitar logs excessivos.
 Pattern
Collection< Usuario> usuarios = //...
if(log.isDebugEnabled())
log.debug(“Usuários: {}", usuarios );
else
log.info(" Usuários size: {}", usuarios.size());

Ver Ex.


Registre todo o stacktrace ao fazer um log
dentro de uma excessão.
 Anti-Pattern
} catch (Exception e) {
LOGGER.error(“Algo errado occurreu.");
// ou: LOGGER.error(e.getMessage());
}

 Pattern
} catch (Exception e) {
LOGGER.error(" Algo errado occurreu.", e);
// ou: LOGGER.error(e.getMessage(), e);
}




Camada abstrata de log é diferente de framework de
log, um framework normalmente implementa uma
camada abstrata de log.
Certifique-se fazer os import da camada abstrata, pois
caso precise trocar de framework não será preciso
modificar o código, basta substituir os arquivos jar.
 Anti-Pattern
import com.logback.Logger;
import com.logback.LoggerFactory;

 Pattern
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


Além de questões de armazenamento de
transferência de arquivos enormes, diferentes
usuários possuem diferentes necessidades,
principalmente em questões temporais.
 Suporte pode trabalhar melhor com logs semanais.
 Marketing poderia preferir logs diários para decisões

estratégicas ágeis.
 Contabilidade prefere manter logs anuais.
 Setor financeiro trabalha melhor com registros mensais.
 http://www.javacodegeeks.com/2011/01/10-tips-proper-application-

logging.html
 http://rolf-engelhard.de/2013/03/logging-anti-patterns-part-i/
 http://rolf-engelhard.de/2013/04/logging-anti-patterns-part-ii/
 http://gojko.net/2006/12/09/logging-anti-patterns/
“Um log difícil de ler e de interpretar é o
mesmo que log nenhum.”

Édipo S.S.
Fortaleza
2013

Logging Patterns & Anti-Patterns

  • 1.
  • 2.
    Pattern "Patterns are formalizedbest practices that the programmer must implement themselves in the application." Introduction to Spring Framework (Acesso em: 25/09/2013) http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/overview.html Anti-Patterns "Design anti-patterns are 'obvious, but wrong, solutions to recurring problems'." Budgen, D. (2003). Software design. Harlow, Eng.: Addison-Wesley. p. 225. ISBN 0-20172219-4. "...common approaches to solving recurring problems that prove to be ineffective. These approaches are called antipatterns." Scott W. Ambler (1998). Process patterns: building large-scale systems using object technology. Cambridge, UK: Cambridge University Press. p. 4. ISBN 0-521-64568-9.
  • 3.
     Error - Usadoquando o processo não pode continuar. Considerados intoleráveis pelo sistema.     Warn - Para eventos críticos, porem onde o processo pode continuar mas com cuidados extras.     Null Pointer Exception Banco de Dados indisponível Falha com conexão remota Utilizando cache por falta de conexão Em modo administrador Usuário sem senha. Info - Deve permitir que administrador ou usuários avançados entendam rapidamente o que a aplicação esta fazendo ou acabou de fazer.   Caixa de supermercado. "Caixa NºX" fechou uma compra no valor "R$Y“. [Fulano] comprou uma passagem de [lugar X] para [lugar Y]
  • 4.
     Debug - Elementosreferentes a desenvolvimento, mas que podem ser relevantes quando.     Valores recebidos ao entrar em um método Valor de saída do método Mudança de valor de variável Trace - Informações detalhadas para o desenvolvedor. Recomendado utilizar somente fora do ambiente de produção.   Valores de variável em determinados pontos Log apenas para saber se tal linha executou
  • 5.
     Informações legíveis parameros mortais entenderem o que se passa.  Anti-Pattern log.debug(“Classe Beta1 lançou exceção 0x55”);  Pattern log.debug(“Classe UsuárioDAO lançou exceção senhaException”);
  • 6.
      Não há necessidadede verificar se determinado nível esta habilitado, o framework já faz isso. Utilize apenas em conjunto com ‘else’, caso haja a necessidade de sempre registrar algo.  Anti-Pattern if(log.isDebugEnabled()) log.debug(“Cliente registrado com sucesso.”);  Pattern if(log.isDebugEnabled()) log.debug(“Itens no checkout: {}”, compra.getItens()); else log.info(“Nº de Itens no checkout: {}”, compra.getItens().size()); Ver Ex.
  • 7.
     Certifique-se de nãotentar registrar em seu log um Null Pointer Exception  Pattern log.debug("Cliente com sobrenome: {}", cliente.getSobrenome());
  • 8.
     Utilize sempre emum único log, informação e valor  Anti-Pattern log.debug(“Cliente registrado com sucesso.”); log.debug(cliente.getId());  Pattern log.debug(“Cliente registrado com sucesso: {}”, cliente.getId()); Ver Ex.
  • 9.
       Registre informações fáceispara humano e máquina lerem seus logs. O separador utilizado também é importante para facilitar o trabalho de um parser. Prefira utilizar vírgulas ou tabs para separar valores no log. Evite utilizar mais de uma linha em um log.  Pattern log.debug(“Horário requisitado: {} ({})", new Date(ttl), ttl); // Horário requisitado: Wed Apr 28 20:14:12 CEST 2010 (1272478452437)
  • 10.
     Defina um padrãopara seus logs (Ex: data, level, thread, nome, mensagem)  Pattern <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} %-5level [%thread][%logger{0}] %m%n</pattern> </encoder> </appender> Exemplo de definição de padrão no LogBack. Ver Ex.
  • 11.
     Registrar parâmetros recebidose valor de retorno para métodos importantes.  Pattern public String fazerAlgo(String a, int b, double c){ log.debug("iniciando fazerAlgo com a={}, b={} e c={}, a, b, c); //processa várias coisas log.debug("saindo de fazerAlgo com {}", resultado); }
  • 12.
     Caso sua exceçãonão faça o tratamento e apenas relançe aquela exceção, fazer log pode resultar em stackTrace duplicado.  Anti-Pattern }catch (Exception e){ log.error("IO exception", e); throw new MyCustomException(e); } Ver Ex.
  • 13.
     Não instanciar loggerpassando a classe como String.  Anti-Pattern private final static Logger LOGGER = LoggerFactory.getLogger("com.ess.Usuario");  Pattern private final static Logger LOGGER = LoggerFactory.getLogger(Usuario.class);
  • 14.
     Não instanciar ologger dentro de cada método, crie uma instancia somente para a classe toda.  Anti-Pattern public void metodo() { Logger logger = LoggerFactory.getLogger(Foo.class); logger.info(“ok!"); }  Pattern private final static Logger LOGGER = LoggerFactory.getLogger(Vai.class); public void metodo() { LOGGER.info(“ok"); }
  • 15.
     Interagir com sistemasexternos pode resultar num objeto de tamanho inesperado. Quando em produção evitar logs excessivos.  Pattern Collection< Usuario> usuarios = //... if(log.isDebugEnabled()) log.debug(“Usuários: {}", usuarios ); else log.info(" Usuários size: {}", usuarios.size()); Ver Ex.
  • 16.
     Registre todo ostacktrace ao fazer um log dentro de uma excessão.  Anti-Pattern } catch (Exception e) { LOGGER.error(“Algo errado occurreu."); // ou: LOGGER.error(e.getMessage()); }  Pattern } catch (Exception e) { LOGGER.error(" Algo errado occurreu.", e); // ou: LOGGER.error(e.getMessage(), e); }
  • 17.
      Camada abstrata delog é diferente de framework de log, um framework normalmente implementa uma camada abstrata de log. Certifique-se fazer os import da camada abstrata, pois caso precise trocar de framework não será preciso modificar o código, basta substituir os arquivos jar.  Anti-Pattern import com.logback.Logger; import com.logback.LoggerFactory;  Pattern import org.slf4j.Logger; import org.slf4j.LoggerFactory;
  • 18.
     Além de questõesde armazenamento de transferência de arquivos enormes, diferentes usuários possuem diferentes necessidades, principalmente em questões temporais.  Suporte pode trabalhar melhor com logs semanais.  Marketing poderia preferir logs diários para decisões estratégicas ágeis.  Contabilidade prefere manter logs anuais.  Setor financeiro trabalha melhor com registros mensais.
  • 19.
     http://www.javacodegeeks.com/2011/01/10-tips-proper-application- logging.html  http://rolf-engelhard.de/2013/03/logging-anti-patterns-part-i/ http://rolf-engelhard.de/2013/04/logging-anti-patterns-part-ii/  http://gojko.net/2006/12/09/logging-anti-patterns/
  • 20.
    “Um log difícilde ler e de interpretar é o mesmo que log nenhum.” Édipo S.S. Fortaleza 2013