Gunicorn: El formato de fecha de registro de errores predeterminado de Gunicorn no es el estándar ISO8601

Creado en 3 may. 2018  ·  34Comentarios  ·  Fuente: benoitc/gunicorn

https://github.com/benoitc/gunicorn/blob/e73ca252f7e1d0286998a0ae4254164291020a0c/gunicorn/glogging.py#L88

La motivación de este problema es la siguiente declaración de grok en logstash:

grok { match => { "message" => "\[(?<gunicorn.time>%{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})? %{ISO8601_TIMEZONE})\] \[%{NUMBER:[gunicorn][worker_id]}\] \[%{LOGLEVEL:[gunicorn][level]}\] %{GREEDYDATA:[gunicorn][message]}" } remove_field => "message" }

Si el formato de fecha no hubiera incluido espacio entre la hora y la zona horaria, la siguiente declaración lo habría cortado:

grok { match => { "message" => "\[%{TIMESTAMP_ISO8601:[gunicorn][time]}\] \[%{NUMBER:[gunicorn][worker_id]}\] \[%{LOGLEVEL:[gunicorn][level]}\] %{GREEDYDATA:[gunicorn][message]}" } remove_field => "message" }

Yo diría que un formato de fecha estándar sería más adecuado para una configuración predeterminada. Creo que agregar un espacio adicional allí no agrega valor, sino que crea problemas. O tener que reemplazar toda la configuración de registro predeterminada, que es excesiva, o tener que escribir expresiones personalizadas en los analizadores de registro para atenderlo.

Improvement Discussion FeaturLogging

Comentario más útil

Ok, eso significa que grok en logstash está precargado con un patrón estricto en lugar de indulgente. He trabajado antes con gente de estándares en la BBC/EBU y recuerdo este tipo de redacción terrible. Para facilitar la lectura, "(digamos) un carácter de espacio" Esto no es implementable ... ¿cuál es ese carácter? Por supuesto, puede permitir cualquier carácter en este punto y eso no está bien. Entonces, los muchachos de Logstash implementaron esto de la siguiente manera para ser T o espacio

TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?

Además ESTO NO ES DE LO QUE SE TRATABA EL TEMA. De lo que se trataba el problema es que el sufijo de la zona horaria tiene un espacio que el estándar NO PERMITE.

Entonces no, desafortunadamente este formato no es común. Este formato es poco ortodoxo específico para gunicorn. Sé lo estúpido que suena esto de que estamos discutiendo sobre un espacio, pero cuando se trata de idiomas y autómatas, la sintaxis lo es todo.

Todos 34 comentarios

El formato de fecha sigue el formato de registro común: https://en.wikipedia.org/wiki/Common_Log_Format

Oh, mis disculpas. Mi respuesta es sobre el formato de registro de acceso. Este informe trata sobre el formato del registro de errores.

Parece que te vendría bien %{DATESTAMP} %{ISO8601_TIMEZONE}

para 19.x es demasiado tarde para hacer algún cambio. Rompería mucho el uso de registros. ¿Es esto algo que queremos cambiar en la próxima versión principal?

@tilgovi entonces, ¿es esto algo que se busca?

Muchos sistemas implementados se basan en el formato actual. Me preocupa que sea un cambio demasiado importante que no aporta mucho valor, ya que siempre se puede escribir una regla al respecto en sistemas similares a log stash. ¿Pensamientos?

Un posible compromiso podría ser un cambio y desaprobación. Puede comenzar a eliminar gradualmente el formato de fecha impar (aunque sea levemente) que no sigue los estándares y proporcionar al usuario un cambio a un formato de línea de registro fijo. Sé que puedo anular el registrador a través de python, pero dado que gunicorn viene con sus configuraciones de competencia incorporadas, no sería mi opción favorita: NO soy una persona con TOC, pero preparar una consulta grok es un tipo moderno de tortura, especialmente cuando la diferencia lo que está contabilizando es un espacio: D Y luego depende del desarrollador mantener esa coincidencia más larga de lo necesario en caso de que algo cambie. No es el fin del mundo si uno tiene que hacerlo, pero seguimos corrigiendo errores, incluso si la gente confía en el software con errores... Eso es lo que pienso... no estoy seguro de si la pregunta me estaba dirigida a mí...

Podríamos considerar cambiar el valor predeterminado para R20.

Este formato es bastante común en realidad. El RFC 3339 tiene una nota al respecto:

NOTA: ISO 8601 define la fecha y la hora separadas por "T". Las aplicaciones que utilizan esta sintaxis pueden elegir, en aras de la legibilidad, especificar una fecha completa y un tiempo completo separados por (digamos) un carácter de espacio.

El registro de errores también se imprime en la línea de comando y debe ser leído por un humano y me gustaría mantenerlo así. ¿Hay algún problema con el formato de la zona horaria?

Ok, eso significa que grok en logstash está precargado con un patrón estricto en lugar de indulgente. He trabajado antes con gente de estándares en la BBC/EBU y recuerdo este tipo de redacción terrible. Para facilitar la lectura, "(digamos) un carácter de espacio" Esto no es implementable ... ¿cuál es ese carácter? Por supuesto, puede permitir cualquier carácter en este punto y eso no está bien. Entonces, los muchachos de Logstash implementaron esto de la siguiente manera para ser T o espacio

TIMESTAMP_ISO8601 %{YEAR}-%{MONTHNUM}-%{MONTHDAY}[T ]%{HOUR}:?%{MINUTE}(?::?%{SECOND})?%{ISO8601_TIMEZONE}?

Además ESTO NO ES DE LO QUE SE TRATABA EL TEMA. De lo que se trataba el problema es que el sufijo de la zona horaria tiene un espacio que el estándar NO PERMITE.

Entonces no, desafortunadamente este formato no es común. Este formato es poco ortodoxo específico para gunicorn. Sé lo estúpido que suena esto de que estamos discutiendo sobre un espacio, pero cuando se trata de idiomas y autómatas, la sintaxis lo es todo.

Eso es útil, @ kozmaz87. Gracias por profundizar en las especificaciones.

Pero ya que estamos aquí, me encantaría señalar también el formato del registro de acceso, que es aún peor. Ni siquiera logré encontrar en el código ningún lugar de donde provenga... Está construido a partir de un mecanismo de configuración bastante oscuro. asignado desde otro lugar. No revisé el código para investigar, pero produce este resultado:

127.0.0.1 - - [13/Aug/2018:15:03:26 +0000] "GET /debug/sms HTTP/1.1" 400 74 "-" "python-requests/2.18.4"

Mirando los documentos de gunicorn, nos enteramos de que la segunda parte de este registro es un '-' por cualquier razón... se supone que la tercera es el usuario, que también está evaluando como '-', no estoy seguro de por qué y luego viene este hermoso formato de fecha donde la hora está casada con el año por un ':' y, por supuesto, el sufijo de zona horaria separado por espacio favorito nuevamente. Pero después de investigar, descubrí que así es como nginx lo registra, así que asumo que aquí es donde se origina esta zona horaria separada por espacios al intentar imitar los registros de acceso de nginx. HAProxy también usa esto, excepto que no pone un sufijo de zona horaria en...

Logging es una locura... Que alguien me traiga un balde de agua helada :)

El formato de registro de acceso es definitivamente "común": https://en.wikipedia.org/wiki/Common_Log_Format

Sin embargo, agregamos el referente y el agente de usuario al final. Consulte el indicador --access-logformat : http://docs.gunicorn.org/en/latest/settings.html#access -log-format

me doy cuenta de eso Simplemente me parece divertido que el segundo elemento sea un '-': D Parece que quien lo implementó se cansó de esto y simplemente puso un '-'

mantendría el formato de registro actual. El formato común de imo es bueno y no estoy al tanto de ningún cambio en los servidores aguas arriba. ¿pensamientos? cc @tilgovi

golpe @tilgovi también @berkerpeksag

cerrando el problema ya que no se solucionará. Como dijo @tilgovi , estamos usando el [formato de registro común] (
https://en.wikipedia.org/wiki/Common_Log_Format.

Creo que podríamos mantener esto abierto. No estamos utilizando el formato de registro común para el registro de errores. El formato de registro común es un formato de registro de acceso y lo usamos allí.

En realidad, no importa. Revisé dos veces ahora y usamos la misma cadena de formato de hora para ambos. Eso me parece mejor que cualquier alternativa. No me gustaría que el registro de acceso y el registro de errores tuvieran diferentes formatos de fecha.

Entiendo mejor el problema ahora y creo que deberíamos reabrir.

Aquí hay una salida de ejemplo de Gunicorn con la configuración predeterminada:

[2019-01-25 11:44:34 -0800] [22794] [INFO] Iniciando gunicorn 19.9.0
[2019-01-25 11:44:34 -0800] [22794] [INFO] Escuchando en: http://127.0.0.1 :8000 (22794)
[2019-01-25 11:44:34 -0800] [22794] [INFO] Usando trabajador: sincronizar
[2019-01-25 11:44:34 -0800] [22797] [INFO] Trabajador de arranque con pid: 22797
[2019-01-25 11:44:36 -0800] [22797] [INFO] 127.0.0.1 - - [25/ene/2019:11:44:36 -0800] "GET/HTTP/1.1" 200 14 " -" "rizo/7.54.0"

El problema no se trata de analizar el formato de registro común del registro de acceso, se trata de analizar la _línea de registro completa_.

Gunicorn genera una marca de tiempo, un pid y un nivel al comienzo de la línea de registro. Las líneas de registro de acceso _también_ tienen un mensaje en formato de registro común con su propia marca de tiempo.

Observe cómo las marcas de tiempo no están en el mismo formato. La solicitud original para este problema era que la marca de tiempo al comienzo de la línea de registro no tuviera espacio _al igual que el formato de registro común_.

Eso se vería así:

[25/ene/2019:11:44:34 -0800] [22794] [INFO] Iniciando gunicorn 19.9.0
[25/ene/2019:11:44:34 -0800] [22794] [INFO] Escuchando en: http://127.0.0.1 :8000 (22794)
[25/ene/2019:11:44:34 -0800] [22794] [INFO] Usando trabajador: sincronizar
[25/ene/2019:11:44:34 -0800] [22797] [INFO] Trabajador de arranque con pid: 22797
[25/ene/2019:11:44:36 -0800] [22797] [INFO] 127.0.0.1 - - [25/ene/2019:11:44:36 -0800] "GET / HTTP/1.1" 200 14 "-" "rizo/7.54.0"

Creo que la respuesta probablemente sea no, porque el formato de registro común no es tan internacional (tiene un nombre de mes corto).

Sin embargo, podríamos cambiar la marca de tiempo al comienzo de cada línea de registro para que sea una marca de tiempo ISO8601.

https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representaciones

El espacio entre la fecha y la hora se permite en lugar de un carácter T, pero no se permite un espacio entre la hora y el desplazamiento de zona.

Estos son los formatos ISO8601 válidos que podríamos tener:

  • [2019-01-25T11:44:34-0800]
  • [2019-01-25 11:44:34-0800]

Comparar con lo que tenemos ahora:

[2019-01-25 11:44:34 -0800]
                    ^ there is a space here

Sin embargo, me preocuparía mucho romper los sistemas implementados.

bien, los registros de análisis/reformateo se pueden manejar fácilmente con herramientas como logstash, por lo que no estoy seguro de que sea un problema. Yo lo mantendría así por ahora.

Si la gente quiere un formato diferente para los registros de acceso, ¿quizás podamos agregar un identificador específico? Así no romperíamos el formato. Sin embargo, los registros de errores son un problema, ya que no proporcionamos una forma de formatearlos. En tal caso, ¿tal vez una variable de entorno lo haría?

No creo que el formato del registro de acceso deba cambiar. Es un formato de registro común en este momento y tenemos la configuración --access-log-format .

El formato de registro de acceso solo formatea el _mensaje_ del registro de acceso que se pasa al controlador. El controlador entonces tiene su propio formateador.

Nuestro formateador predeterminado para los controladores de flujo en stdout y stderr coloca una marca de tiempo al principio. Eso significa que con la configuración predeterminada, el registro de acceso tiene _dos_ sellos de tiempo: uno al principio y otro en el mensaje.

Cambiar el formateador para el controlador requiere el uso de una de las opciones --logconfig (archivo o dictado).

Deberíamos considerar tener una marca de tiempo ISO8601 en el formateador predeterminado.

Los registros de análisis/reformateo se pueden manejar fácilmente con herramientas como logstash

Sí, pero es muy conveniente cuando esas herramientas pueden analizar la marca de tiempo con patrones incorporados para que el usuario no tenga que escribir una expresión regular. El problema original se abrió porque Grok tiene un patrón incorporado para las marcas de tiempo ISO8601.

@tilgovi No quiero romper la compatibilidad. Además, NGINX ofrece la posibilidad de establecer la hora utilizando el formato ISO8601 o el formato de registro común:

$time_iso8601
local time in the ISO 8601 standard format
$time_local
local time in the Common Log Format

https://nginx.org/en/docs/http/ngx_http_log_module.html

Yo haría lo mismo ya que no rompe el legado. Por cierto, ¿no deberíamos simplemente mostrar la línea de registro de acceso a la salida? Parece que no deberíamos tener el primer encabezado con el PID. ¿Pensamientos?

acerca de hacerlo parte del formateador predeterminado, me preocupa que rompa alguna herramienta. ¿Qué hay de tener una variable de entorno personalizada TIME_ISO8601=true para forzarlo?

No quiero romper la compatibilidad.

yo tampoco Solo quería volver a abrir el ticket porque creo que lo cerramos por el motivo equivocado. Ambos respondimos como si el problema fuera cambiar el formato de registro común. El problema es la marca de tiempo en el formateador predeterminado, no el formato del mensaje de registro de acceso. Me alegro de que podamos discutirlo más, pero tal vez la respuesta sea no hacer nada.

Por cierto, ¿no deberíamos simplemente mostrar la línea de registro de acceso a la salida? Parece que no deberíamos tener el primer encabezado con el PID. ¿Pensamientos?

Posible. No estoy seguro.

¿Qué hay de tener una variable de entorno personalizada?

Tal vez está bien. El usuario siempre puede controlar el registro por completo utilizando la configuración de registro avanzada. Intentamos simplificar algunas configuraciones para la CLI, como --log-level , para que los usuarios no tengan que usar archivos de configuración. ¿Tal vez podríamos agregar --log-date-format ? Incluso podría reconocer cadenas simbólicas como iso8601 . Esta configuración sería para usuarios que no quieren usar --log-config o log_config_dict .

@tilgovi mientras tanto, la versión 20.0 es un buen momento para un cambio en el formato, ya que estamos rompiendo la compatibilidad con python 2.

Creo que lo que más me preocupa de cualquier legado es que ISO8601 es difícil de analizar para los ojos humanos y muchas personas, incluyéndome a mí, están usando la consola como una oportunidad para observar lo que está sucediendo.

Me gustaría sugerir lo siguiente:

  • [] agregue una opción -iso8601 que obligue a los registros stdout y stderr a usar este formato (como sugiere)
  • [ ] en el registro de acceso agregue una opción en el formato para mostrar la hora en este formato

Mientras estamos aquí, ¿tal vez también podríamos tener una opción de -utc para usar UTC por el momento? ¿Pensamientos?

Solo para estar seguros, esta sería la diferencia propuesta si solo cambiáramos el valor predeterminado:

diff --git a/gunicorn/glogging.py b/gunicorn/glogging.py
index 56cc5bd..0735e58 100644
--- a/gunicorn/glogging.py
+++ b/gunicorn/glogging.py
@@ -80,7 +80,7 @@ CONFIG_DEFAULTS = dict(
         formatters={
             "generic": {
                 "format": "%(asctime)s [%(process)d] [%(levelname)s] %(message)s",
-                "datefmt": "[%Y-%m-%d %H:%M:%S %z]",
+                "datefmt": "[%Y-%m-%d %H:%M:%S%z]",
                 "class": "logging.Formatter"
             }
         }
@@ -175,7 +175,7 @@ class Logger(object):
     loglevel = logging.INFO

     error_fmt = r"%(asctime)s [%(process)d] [%(levelname)s] %(message)s"
-    datefmt = r"[%Y-%m-%d %H:%M:%S %z]"
+    datefmt = r"[%Y-%m-%d %H:%M:%S%z]"

     access_fmt = "%(message)s"
     syslog_fmt = "[%(process)d] %(message)s"

Creo que una opción para usar una fecha y hora ISO8601 en los tokens de registro de acceso es interesante, pero es independiente de lo que motivó este problema.

Por cierto, no estoy muy convencido de esto. 😄 Solo quiero representar el problema con precisión.

probablemente tengamos que pensar un poco más al respecto. Lo estoy posponiendo a 20.1 para permitirnos algunas veces.

Estimados desarrolladores,
Me enfrento a un problema de pérdida de solicitud (no tiene nada que ver con Gunicorn). Necesitaría poder tener la marca de tiempo precisa, incluidos los microsegundos, como en este ejemplo de uno de nuestros servidores Apache: 2019-10-30 14:27:16.960421 . Sería una mejora genial, gracias por considerarlo.

¿Alguna esperanza de que la bandera, log-date-format iso8601 , esté disponible en la próxima versión de gunicorn?

¿Fue útil esta página
0 / 5 - 0 calificaciones