15 buenos consejos para la impresión de diarios

prefacio

Hola a todos, soy un niño pequeño que recoge caracoles . ¡ El registro es una buena ayuda para localizar problemas rápidamente y es una herramienta poderosa para romper y tirar el bote ! Es muy importante imprimir bien el registro. Hoy, hablemos de 15 buenas sugerencias para la impresión de registros ~

  • Número público: niño recogiendo caracoles

1. Elija el nivel de registro apropiado

Hay cinco niveles de registro comunes, a saber, error, advertencia, información, depuración y seguimiento. En el desarrollo diario, debemos elegir el nivel de registro apropiado, no solo imprima la información al revés ~

  • error: registro de errores, que se refiere a un error relativamente grave que afecta el negocio normal y requiere monitoreo de configuración de operación y mantenimiento ;
  • advertir: registro de advertencia, error general, tiene poco impacto en el negocio, pero requiere atención de desarrollo ;
  • info: registro de información, que registra información clave para la resolución de problemas, como el tiempo de llamada, los parámetros de entrada y salida, etc.;
  • depuración: datos de tiempo de ejecución en lógica clave para desarrollar DEBUG;
  • rastro: la información más detallada, generalmente esta información solo se registra en el archivo de registro.

2. El registro debe imprimir los parámetros de entrada y salida del método.

No necesitamos imprimir muchos registros, solo imprima un registro válido que pueda localizar rápidamente el problema . ¡Un registro efectivo es una herramienta poderosa para tirar el bote!

¿Cuáles son los registros válidos y críticos ? Por ejemplo, cuando ingrese el método, imprima los parámetros de entrada . Luego, cuando el método regresa, imprime los parámetros y devuelve el valor . Para los parámetros de entrada, generalmente es información clave como userId o bizSeq . Por ejemplo:

public String testLogMethod(Document doc, Mode mode){
   log.debug(“method enter param:{}”,userId);
   String id = "666";
   log.debug(“method exit param:{}”,id);
   return id;
}
复制代码

3. Elija el formato de registro apropiado

El formato de registro ideal debe incluir la información más básica: como la marca de tiempo actual (normalmente con una precisión de milisegundos), el nivel de registro , el nombre del subproceso , etc. El registro de inicio de sesión se puede configurar así:

<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> 
复制代码

Si nuestro formato de registro ni siquiera registra la hora actual, ¿entonces ni siquiera sabemos la hora de la solicitud ?

4. Cuando encuentre condiciones como si... más..., intente imprimir el registro en la primera línea de cada rama

Cuando encuentre condiciones como if...else... o switch , puede imprimir el registro en la primera línea de la rama, de modo que al solucionar problemas, puede usar el registro para determinar qué rama ingresó y el la lógica del código es más clara y también es más fácil solucionar problemas.

Ejemplo normal:

if(user.isVip()){
  log.info("该用户是会员,Id:{},开始处理会员逻辑",user,getUserId());
  //会员逻辑
}else{
  log.info("该用户是非会员,Id:{},开始处理非会员逻辑",user,getUserId())
  //非会员逻辑
}
复制代码

5. Cuando el nivel de registro es relativamente bajo, realice el juicio de cambio de registro

Para niveles de registro más bajos, como rastreo/depuración, se debe realizar un juicio de cambio de nivel de registro.

Ejemplo normal:

User user = new User(666L, "公众号", "捡田螺的小男孩");
if (log.isDebugEnabled()) {
    log.debug("userId is: {}", user.getId());
}
复制代码

Porque actualmente existe el siguiente código de registro:

logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
复制代码

Si el nivel de registro configurado es advertir , el registro anterior no se imprimirá, pero se realizará la operación de concatenación de cadenas. Si symboles un objeto, toString()también se ejecutará el método, lo que desperdicia recursos del sistema. Después de realizar la operación anterior, el registro final no se imprime, por lo tanto, se recomienda Agregar juicio de cambio de registro.

6. La API en el sistema de registro (Log4j, Logback) no se puede usar directamente, pero la API en el marco de registro SLF4J.

SLF4J es un marco de registro en modo fachada, que conduce a la unificación de los métodos de procesamiento de registro y mantenimiento de varias clases, y puede reemplazar fácilmente el marco de registro subyacente sin modificar el código.

Ejemplo normal:

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory;

Logger final estático privado logger = LoggerFactory.getLogger(TianLuoBoy.class)
;

7. Se recomienda utilizar el marcador de posición de parámetro {} en lugar de + empalme.

Contador de ejemplo:

logger.info("Processing trade with id: " + id + " and symbol: " + symbol);
复制代码

En el ejemplo anterior, el uso +de operadores para concatenar cadenas tiene una cierta pérdida de rendimiento .

Por ejemplo:

logger.info("Processing trade with id: {} and symbol : {} ", id, symbol); 
复制代码

Usamos llaves {}como marcadores de posición en el registro, que es +más elegante y conciso que usar operadores. Y, en comparación con el ejemplo negativo , el uso de marcadores de posición es solo una acción de reemplazo que puede mejorar el rendimiento de manera efectiva.

8. Se recomienda generar registros de forma asíncrona.

  • Eventualmente, el registro se enviará a un archivo u otro flujo de salida, y se requerirá el rendimiento de IO. Si es asíncrono, puede mejorar significativamente el rendimiento de E/S.
  • A menos que existan requisitos especiales, se recomienda utilizar la forma asíncrona para generar el registro. Tome el inicio de sesión como ejemplo, es muy simple configurar asincrónico, solo use AsyncAppender
<appender name="FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="ASYNC"/>
</appender>
复制代码

9. No use e.printStackTrace()

Contador de ejemplo:

try{
  // 业务代码处理
}catch(Exception e){
  e.printStackTrace();
}
复制代码

Ejemplo normal:

try{
  // 业务代码处理
}catch(Exception e){
  log.error("你的程序有异常啦",e);
}
复制代码

razón:

  • El registro de pila impreso por e.printStackTrace() está intercalado con el registro de código comercial y, por lo general, no es conveniente verificar el registro anormal.
  • La cadena generada por la declaración e.printStackTrace() registra la información de la pila. Si la información es demasiado larga, el bloque de memoria donde se encuentra el conjunto de constantes de cadena no tiene espacio, es decir, la memoria está llena, entonces la solicitud del usuario estar atascado ~

10. No solo escriba la mitad del registro de excepciones, sino que emita todos los mensajes de error

Contador de ejemplo 1:

try {
    //业务代码处理
} catch (Exception e) {
    // 错误
    LOG.error('你的程序有异常啦');
} 

copiar codigo

  • Ninguna de las excepciones e se imprime, por lo que no hay idea de qué tipo de excepción se lanzó.

Contador de ejemplo 2:

try {
    //业务代码处理
} catch (Exception e) {
    // 错误
    LOG.error('你的程序有异常啦', e.getMessage());
} 
复制代码
  • e.getMessage()No se registrará la información detallada de la excepción de la pila, solo se registrará la información básica de la descripción del error, lo que no es propicio para la resolución de problemas.

Ejemplo normal:

try {
    //业务代码处理
} catch (Exception e) {
    // 错误
    LOG.error('你的程序有异常啦', e);
} 
复制代码

11. Deshabilitar la depuración en el entorno en línea

Es muy importante deshabilitar la depuración en el entorno en línea.

Debido a que el sistema general tiene muchos registros de depuración, y varios marcos también usan mucho los registros de depuración, la depuración en línea puede llenar el disco pronto, afectando el funcionamiento normal del sistema comercial.

12. No registre excepciones y vuelva a lanzarlas

Lo contrario es como sigue:

log.error("IO exception", e);
throw new MyException(e);
复制代码
  • Esta implementación generalmente imprime la información de la pila dos veces. Esto se debe a que cuando se detecta MyException, se imprimirá nuevamente.
  • Tal registro, o envoltura y luego lanzamiento, ¡no use ambos! De lo contrario, sus registros se verán confusos.

13. Evite la impresión repetida de registros

Evite imprimir el registro repetidamente, Jiangzi desperdiciará espacio en disco. Si ya tiene una línea de registro que expresa claramente el significado, evite la impresión redundante , y el contraejemplo es el siguiente:

if(user.isVip()){
  log.info("该用户是会员,Id:{}",user,getUserId());
  //冗余,可以跟前面的日志合并一起
  log.info("开始处理会员逻辑,id:{}",user,getUserId());
  //会员逻辑
}else{
  //非会员逻辑
}
复制代码

Si está utilizando el marco de registro log4j, asegúrese log4j.xmlde configurar additivity=false en él, ya que puede evitar la impresión repetida de registros.

Ejemplo normal:

<logger name="com.taobao.dubbo.config" additivity="false"> 
复制代码

14. Separación de archivos de registro

  • Podemos separar diferentes tipos de registros, como access.log o error level error.log, que se pueden imprimir en un archivo por separado.
  • Por supuesto, también se puede imprimir en diferentes archivos de registro de acuerdo con diferentes módulos comerciales, de modo que nos sea más conveniente solucionar problemas y hacer estadísticas de datos.

15. Para los módulos de funciones principales, se recomienda imprimir un registro más completo

  • En nuestro desarrollo diario, si el núcleo o la lógica es un código complejo, se recomienda agregar comentarios detallados y registros más detallados.
  • ¿Qué tan detallado debe ser el registro? Piénselo, si hay un error en su programa principal, puede localizarlo a través del registro, entonces puede hacerlo.

Reimpreso de: https://juejin.cn/post/7010889983149998117

Supongo que te gusta

Origin blog.csdn.net/huangjhai/article/details/121646135
Recomendado
Clasificación