Hablemos sobre el registro

Esta publicación está inspirada en el tema Go Forum lanzado por Nate Finch. Esta publicación se centra en Ir, pero si pasa esto, creo que las ideas presentadas aquí son ampliamente aplicables.

¿Por qué no hay amor?


El paquete de registro en Go no tiene niveles para registros; puede agregar manualmente los prefijos DEPURACIÓN, INFORMACIÓN, ADVERTENCIA y ERROR usted mismo. Además, el tipo de registrador en Go no tiene la capacidad de habilitar o deshabilitar estos niveles por separado para los paquetes seleccionados. A modo de comparación, veamos algunos reemplazos de desarrolladores externos.

imagen

Google Glog tiene niveles:

  • Informacion
  • Advertencia
  • Error
  • Fatal (finaliza el programa)

Veamos otra biblioteca, loggo , desarrollada para Juju, los niveles están disponibles en ella:

  • Traza
  • Depurar
  • Informacion
  • Advertencia
  • Error
  • Crítico

Loggo también tiene la capacidad de establecer el nivel de detalle del registro para los paquetes deseados individualmente.

Aquí hay dos ejemplos, claramente creados bajo la influencia de otras bibliotecas para iniciar sesión en otros idiomas.

De hecho, su origen se remonta a syslog (3), posiblemente incluso antes. Y creo que están equivocados.

Quiero tomar una posición controvertida. Creo que todas las bibliotecas de registros son malas porque ofrecen demasiadas funciones; Un conjunto impresionante de características que aturde al programador justo en el momento en que necesita pensar con claridad sobre cómo comunicarse con el lector del futuro, con quién verá estas revistas.

Sostengo que los paquetes de registro exitosos requieren muchas menos funciones y, por supuesto, menos niveles.

Hablemos de advertencias (ADVERTENCIA)


Comencemos con lo más simple. Nadie necesita el nivel de registro de ADVERTENCIA (advertencia).

Nadie lee las advertencias, porque por definición no ha pasado nada malo. Tal vez algo salga mal en el futuro, pero suena como alguien más, no es mi problema.

Además, si utiliza algún tipo de registro de varios niveles, ¿por qué necesita establecer el nivel de ADVERTENCIA? Establecería el nivel en INFO o ERROR. Establecer el nivel de ADVERTENCIA significa que probablemente esté informando errores en el nivel de ADVERTENCIA.

Excluya el nivel de advertencia: este es un mensaje informativo o un error.

Hablemos sobre el nivel de error fatal


El nivel FATAL en realidad registra el mensaje y luego llama a os.Exit (1). En principio, esto significa:

  • las expresiones diferidas en otras rutinas (goroutines) no se ejecutan;
  • los tampones no están enjuagados;
  • Los archivos y directorios temporales no se eliminan.

En esencia, log.Fatal es menos detallado, pero semánticamente equivalente al pánico.

En general, se acepta que las bibliotecas no deben usar panic1, pero si se llama log.Fatal2 tiene el mismo efecto, también se debe deshabilitar.

La suposición de que este problema de limpieza se puede resolver registrando controladores de apagado en el registrador proporciona una estrecha relación entre el registrador utilizado y cada lugar donde se realizan las operaciones de limpieza. También viola la separación de intereses.

No grabe mensajes con un nivel FATAL, prefiera devolver un error a la persona que llama. Si el error llega a main.main, este es el lugar correcto para realizar cualquier limpieza antes de cerrar el programa.

Hablemos del error (nivel de ERROR)


El manejo y el registro de errores están estrechamente relacionados, por lo tanto, a primera vista, el registro de nivel de error (ERROR) debe justificarse fácilmente. No estoy de acuerdo

En Go, si llamar a una función o método devuelve un valor de error, entonces realmente tiene dos opciones:

  • manejar el error
  • devolver un error a la persona que llama. Puede envolver maravillosamente un error en la envoltura de regalos (envoltura), pero esto no es importante para esta discusión.

Si decide procesar el error escribiéndolo en el registro, entonces, por definición, ya no es un error: lo ha procesado. El acto de registrar el error en sí mismo es el procesamiento del error; por lo tanto, ya no es aconsejable escribirlo en el registro como un error.

Déjame convencerte con este código:

err := somethingHard() if err != nil { log.Error("oops, something was too hard", err) return err // what is this, Java ? } 

Nunca debe registrar nada en el nivel de error porque debe manejar el error o pasarlo a la persona que llama.

Debe comprender claramente, no estoy diciendo que no deba escribir en el registro que se ha producido un cambio de estado:

 if err := planA(); err != nil { log.Infof("could't open the foo file, continuing with plan b: %v", err) planB() } 

Pero en realidad, log.Info y log.Error tienen el mismo objetivo.

¡No digo "no registrar errores"! En cambio, hago la pregunta, ¿cuál es la API más pequeña posible para iniciar sesión? Y cuando se trata de errores, creo que la gran mayoría de las cosas registradas en el nivel de ERROR se realizan simplemente porque están relacionadas con el error. De hecho, son solo informativos, por lo que podemos eliminar el registro de nivel de error (ERROR) de nuestra API.

Lo que queda


Excluimos WARNING, argumentamos que no debe registrarse nada en el nivel de error (ERROR) y mostramos que solo la aplicación de nivel superior debe tener algún tipo de registro. Comportamiento fatal. Lo que queda

Creo que solo hay dos cosas en las que debe iniciar sesión:

  • cosas que a los desarrolladores les interesan cuando desarrollan o depuran un programa;
  • cosas que les interesan a los usuarios cuando usan su programa.

Obviamente, estos son niveles de depuración (DEBUG) e informativos (INFO), respectivamente.

log.Info solo debe escribir esta línea en la salida del registro. No debería ser posible deshabilitarlo, ya que el usuario solo debe decir lo que es útil para él. Si se produce un error que no puede procesarse, debería aparecer en main.main donde sale el programa. El pequeño inconveniente de tener que insertar el prefijo FATAL antes del mensaje de registro final o escribir directamente en os.Stderr usando fmt.Fprintf no es razón suficiente para expandir el paquete con el método log.Fatal.

log.Debug, este es un asunto completamente diferente. Un desarrollador o ingeniero de soporte lo necesita para controlar el programa. Durante el desarrollo, las expresiones de depuración deben ser numerosas sin recurrir al nivel de rastreo o debug2 (ya sabes quién eres). El paquete de registro debe ser compatible con el control granular para habilitar o deshabilitar las expresiones de depuración para los paquetes deseados en el paquete, o posiblemente incluso en un ámbito más limitado.

Conclusión


Si se tratara de una encuesta de Twitter, le pediría que elija entre

  • el registro es importante
  • iniciar sesión es difícil

Pero el hecho es que el registro es ambos. La solución a este problema DEBE ser destruir y reducir sin piedad distracciones innecesarias.

Que piensas ¿Es lo suficientemente extravagante para trabajar, o es simplemente extravagante?

Notas


Algunas bibliotecas pueden usar pánico / recuperación como mecanismo de flujo de control interno, pero el mantra principal es que no deberían permitir que estas operaciones de flujo de control se filtren fuera del límite del paquete.

Irónicamente, aunque no tiene un nivel de salida DEBUG, el paquete de registro Go estándar tiene características Fatal y Panic. En este paquete, el número de funciones que conducen a la finalización repentina del programa excede el número de las que no lo hacen.

Sobre el autor


El autor de este artículo, Dave Cheney , es autor de muchos paquetes populares para Go, como github.com/pkg/errors y github.com/davecheney/httpstat . Puede evaluar la autoridad y la experiencia del autor usted mismo.

Del traductor


Muchos desarrolladores están preocupados por el registro, algunos discutieron agregar una interfaz Logger a la biblioteca Go estándar para agilizar el registro en las bibliotecas y estimular a sus desarrolladores de esta manera. Los chicos incluso redactaron su propuesta y pusieron el documento para discusión.

Más reflexión de presentación ¿Necesitamos un nuevo registrador y qué debería ser? de Chris Hines.

Hay varias implementaciones de las ideas de inicio de sesión de Dave y un poco fuera de tema sobre el problema de nivel de ERROR y un paquete de registro más elaborado.

Source: https://habr.com/ru/post/440200/


All Articles