Pregunta

Como muchos usuarios de log4j, a menudo tenemos un registro de nivel de depuración que es costoso evaluar. Así que guardamos esos casos con código como:

if( _logger.isDebugEnabled )
  _logger.debug("Interesting, my foojes are goofed up: " + getFullDetails())

Sin embargo, eso es más feo que una simple llamada _logger.debug, y algunas veces el programador no se da cuenta de que la evaluación podría ser costosa.

Parece que debería ser bastante simple escribir un programa que tome un archivo compilado y proteja todas las llamadas _logger.debug con el cheque isDebugEnabled. Es probable que estemos dispuestos a aceptar que la sobrecarga adicional de la comprobación es DebugEnabled en todos los casos.

¿Alguien ha intentado este enfoque o ha realizado un procesamiento posterior similar de un frasco?

¿Fue útil?

Solución

¿Ha visto AspectJ ? Esto admite aspectos que utilizan el tejido de código de bytes y puede interceptar en un archivo .jar previamente compilado .

Otros consejos

En lugar de buscar modificar el archivo, buscaría una solución usando Instrumentación Bytecode . El problema será identificar las partes del código que desea ajustar dentro de un .isDebugEnabled () : tendrá que identificar los objetos que solo se usan para las invocaciones de log4j.

Creo que una buena solución sería que el código sería eficiente como es .

Considera que log4j está en desuso. Su propio autor lo dejó como está, para evitar romper la compatibilidad, pero creó uno nuevo, SLF4J ( http: // www .slf4j.org / ). Proporciona tanto una fachada como una implementación, de acuerdo con la distinción commons-logging / log4j, pero sin los defectos de cada uno ...

Creo que, en este nuevo servicio de registro, puede enviar parámetros de Objeto al registro, y que el nivel se evalúa antes de convertir los Objetos (a Cadena o de otra manera). La idea es utilizar una cadena de formato y parámetros.


Nuestro código no usa slf4j, pero tenemos métodos de utilidad que hacen exactamente eso. Se codifica aproximadamente de la siguiente manera (de la memoria):

    public enum LogLevel {
       FATAL, ERROR, WARNING, INFO, DEBUG;

       public void log(Logger logger, String format, Object... parameters) {
         if (isEnabled(logger)) {
            logImpl(logger, String.format(format, parameters));
         }
       }
       public boolean isEnabled(Logger logger) {
         switch(this) {
           case WARNING : return logger.isWarningEnabled();
           case INFO : return logger.isInfoEnabled();
           case DEBUG : return logger.isDebugEnabled();
           default: return true;
         }
       }
       private void logImpl(Logger logger, String message) {
         switch(this) {
           case WARNING : logger.warn(message);
           // other cases
         }
       }
    }

Se utiliza como:

     public void myMethod(Object param) {
       LogLevel.WARNING.log(LOGGER, "What is my message ....", "myMethod", param);
     }

ACTUALIZACIÓN : si necesita llamar a un método en el registro ...

  • Una posibilidad es usar el método toString . Esto es apropiado si su registro es 'técnico' , y se usará también al depurar.

  • Si su registro es más funcional (no está dirigido al desarrollador), sugiero que defina una interfaz (es funcional en este caso, por lo que es útil proporcionar un significado) :

    public interface Detailable { // the name could also suggest logging?
      String getFullDetails();
    }
    

    Implemente esa interfaz en cualquier objeto que deba pasarse como objeto de registro, con un cálculo complejo para construir el registro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top