Gunicorn: Le format de date d'enregistrement des erreurs par défaut de Gunicorn n'est pas la norme ISO8601

Créé le 3 mai 2018  ·  34Commentaires  ·  Source: benoitc/gunicorn

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

La motivation de ce problème est la déclaration grok suivante dans 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 le format de date n'avait inclus aucun espace entre l'heure et le fuseau horaire, l'instruction suivante l'aurait coupé :

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

Je dirais qu'un format de date standard serait mieux adapté à une configuration par défaut. Je pense que l'ajout d'un espace supplémentaire n'ajoute aucune valeur mais crée des problèmes à la place. Soit devoir remplacer l'intégralité de la configuration par défaut de logconfig, ce qui est excessif, soit devoir écrire des expressions personnalisées dans les analyseurs de journaux pour y répondre.

Improvement Discussion FeaturLogging

Commentaire le plus utile

Ok, cela signifie donc que grok dans logstash est préchargé avec un modèle strict plutôt qu'un modèle indulgent. J'ai déjà travaillé avec des spécialistes des normes à la BBC/EBU et je me souviens de ce genre de formulation terrible. Pour la lisibilité "(disons) un caractère d'espace" Ce n'est pas implémentable .... quel est ce caractère? Bien sûr, vous pouvez autoriser n'importe quel caractère à ce stade et ce n'est pas OK. Donc, les gars de Logstash l'ont implémenté de la manière suivante pour être soit T soit espace

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

De plus, CE N'EST PAS L'OBJET DU PROBLÈME. Le problème était que le suffixe de fuseau horaire avait un espace que la norme NE PERMET PAS.

Donc non, malheureusement ce format n'est pas courant. Ce format est peu orthodoxe spécifique au gunicorn. Je sais à quel point cela semble stupide que nous nous disputions à propos d'un espace, mais en ce qui concerne les langages et la syntaxe des automotons, c'est tout.

Tous les 34 commentaires

Le format de date suit le format de journal commun : https://en.wikipedia.org/wiki/Common_Log_Format

Oh, mes excuses. Ma réponse concerne le format du journal d'accès. Ce rapport concerne le format du journal des erreurs.

On dirait que vous pourriez utiliser %{DATESTAMP} %{ISO8601_TIMEZONE}

pour 19.x, il est trop tard pour faire le moindre changement. Cela briserait beaucoup d'utilisation de la journalisation. Est-ce quelque chose que nous voulons changer dans la prochaine version majeure ?

@tilgovi alors est-ce quelque chose de voulu ?

De nombreux systèmes déployés reposent sur le format actuel. Je crains que ce soit un changement trop important qui n'apporte pas beaucoup de valeur puisqu'une règle peut toujours être écrite à ce sujet dans des systèmes de stockage de journaux. Les pensées?

Un compromis possible pourrait être un changement et une dépréciation. Vous pouvez commencer à supprimer progressivement le format de date impaire (même si légèrement) qui ne respecte pas les normes et fournir à l'utilisateur un passage à un format de ligne de journal fixe. Je sais que je peux remplacer l'enregistreur via python, mais comme gunicorn est livré avec ses paramètres concurrents, ce ne serait pas mon choix préféré : Je ne suis pas une personne TOC, mais préparer une requête grok est un type de torture moderne, surtout quand la différence vous comptabilisez est un espace :D Et ensuite, c'est au développeur de maintenir cette correspondance plus longtemps que nécessaire si quelque chose devait changer. Ce n'est pas la fin du monde s'il le faut, mais nous continuons à corriger les bogues même si les gens comptent sur le logiciel bogué... C'est ce que je pense... je ne sais pas si la question m'était adressée...

Nous pourrions envisager de modifier la valeur par défaut pour R20.

Ce format est assez commun en fait. La RFC 3339 contient une note à ce sujet :

REMARQUE : ISO 8601 définit la date et l'heure séparées par "T". Les applications utilisant cette syntaxe peuvent choisir, pour des raisons de lisibilité, de spécifier une date complète et un temps complet séparés par (disons) un caractère espace.

Le journal des erreurs est également imprimé sur la ligne de commande et doit être lu par un humain et j'aimerais que cela reste ainsi. Y a-t-il un problème avec le format du fuseau horaire ?

Ok, cela signifie donc que grok dans logstash est préchargé avec un modèle strict plutôt qu'un modèle indulgent. J'ai déjà travaillé avec des spécialistes des normes à la BBC/EBU et je me souviens de ce genre de formulation terrible. Pour la lisibilité "(disons) un caractère d'espace" Ce n'est pas implémentable .... quel est ce caractère? Bien sûr, vous pouvez autoriser n'importe quel caractère à ce stade et ce n'est pas OK. Donc, les gars de Logstash l'ont implémenté de la manière suivante pour être soit T soit espace

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

De plus, CE N'EST PAS L'OBJET DU PROBLÈME. Le problème était que le suffixe de fuseau horaire avait un espace que la norme NE PERMET PAS.

Donc non, malheureusement ce format n'est pas courant. Ce format est peu orthodoxe spécifique au gunicorn. Je sais à quel point cela semble stupide que nous nous disputions à propos d'un espace, mais en ce qui concerne les langages et la syntaxe des automotons, c'est tout.

C'est utile, @ kozmaz87. Merci d'avoir creusé les spécifications.

Mais puisque nous sommes ici, j'aimerais également souligner le format du journal d'accès, qui est encore pire. Je n'ai même pas réussi à trouver dans le code d'où il venait... Il est construit à partir d'un mécanisme de configuration assez obscur. attribué d'ailleurs. Je n'ai pas vérifié le code pour enquêter, mais il produit cette sortie:

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

En regardant les documents gunicorn, nous apprenons que la 2ème partie de ce journal est un '-' pour une raison quelconque... la 3ème est censée être l'utilisateur, qui évalue également '-' sans savoir pourquoi, puis vient ce charmant format de date où l'heure est mariée à l'année par un ':' et bien sûr le suffixe de fuseau horaire préféré séparé par un espace à nouveau. Mais après avoir fouillé, j'ai découvert que c'est ainsi que nginx l'enregistre, donc je suppose que c'est de là que provient ce fuseau horaire séparé par l'espace en essayant d'imiter les journaux d'accès nginx. HAProxy l'utilise également, sauf qu'il ne met pas de suffixe de fuseau horaire sur ...

L'exploitation forestière est folle... Que quelqu'un m'apporte un seau d'eau glacée :)

Le format du journal d'accès est définitivement "commun": https://en.wikipedia.org/wiki/Common_Log_Format

Cependant, nous ajoutons le référent et l'agent utilisateur à la fin. Reportez-vous au drapeau --access-logformat : http://docs.gunicorn.org/en/latest/settings.html#access -log-format

Je m'en rends compte. Je trouve juste drôle que le 2ème élément soit un '-' :D C'est comme si celui qui l'avait implémenté l'avait eu avec ça et avait juste mis un '-'

Je garderais le format de journal actuel. le format commun imo est bon et je ne suis au courant d'aucun changement de serveurs en amont. les pensées? cc @tilgovi

bosse @tilgovi aussi @berkerpeksag

fermer le problème car ne résoudra pas. Comme l'a dit @tilgovi , nous utilisons le [format de journal commun](
https://en.wikipedia.org/wiki/Common_Log_Format.

Je pense qu'on pourrait garder ça ouvert. Nous n'utilisons pas le format de journal commun pour le journal des erreurs. Le format de journal commun est un format de journal d'accès et nous l'utilisons ici.

En fait, tant pis. J'ai revérifié tout à l'heure et nous utilisons la même chaîne de format d'heure pour les deux. Cela me semble mieux que n'importe quelle alternative. Je ne voudrais pas que le journal d'accès et le journal des erreurs aient des formats de date différents.

Je comprends mieux le problème maintenant et je pense que nous devrions rouvrir.

Voici un exemple de sortie de Gunicorn avec les paramètres par défaut :

[2019-01-25 11:44:34 -0800] [22794] [INFO] Démarrage du gunicorn 19.9.0
[2019-01-25 11:44:34 -0800] [22794] [INFO] Écoute sur : http://127.0.0.1 :8000 (22794)
[2019-01-25 11:44:34 -0800] [22794] [INFO] Utilisation de Worker : synchronisation
[2019-01-25 11:44:34 -0800] [22797] [INFO] Booter worker avec pid : 22797
[2019-01-25 11:44:36 -0800] [22797] [INFO] 127.0.0.1 - - [25/Jan/2019:11:44:36 -0800] "GET / HTTP/1.1" 200 14 " -" "boucle/7.54.0"

Le problème n'est pas d'analyser le format de journal commun du journal d'accès, il s'agit d'analyser la _ligne de journal entière_.

Gunicorn génère un horodatage, un pid et un niveau au début de la ligne de journal. Les lignes du journal d'accès _également_ ont un message au format de journal commun avec son propre horodatage.

Remarquez comment les horodatages ne sont pas dans le même format. La demande initiale pour ce problème était que l'horodatage au début de la ligne de journal n'ait pas d'espace _tout comme le format de journal commun_.

Cela ressemblerait à ceci :

[25/Jan/2019:11:44:34 -0800] [22794] [INFO] Démarrage de gunicorn 19.9.0
[25/Jan/2019:11:44:34 -0800] [22794] [INFO] Écoute sur : http://127.0.0.1 :8000 (22794)
[25/Jan/2019:11:44:34 -0800] [22794] [INFO] Utilisation de Worker : synchronisation
[25/Jan/2019:11:44:34 -0800] [22797] [INFO] Booter worker avec pid : 22797
[25/Jan/2019:11:44:36 -0800] [22797] [INFO] 127.0.0.1 - - [25/Jan/2019:11:44:36 -0800] "GET / HTTP/1.1" 200 14 "-" "boucle/7.54.0"

Je pense que la réponse est probablement non, car le format de journal commun n'est pas aussi international (il a un nom de mois court).

Cependant, nous pourrions changer l'horodatage au début de chaque ligne de journal pour qu'il soit un horodatage ISO8601.

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

L'espace entre la date et l'heure est en fait autorisé à la place du caractère T, mais un espace entre l'heure et le décalage de zone ne l'est pas.

Voici les formats ISO8601 valides que nous pourrions avoir :

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

Comparez avec ce que nous avons maintenant :

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

Je m'inquiéterais beaucoup de casser les systèmes déployés, cependant.

bien l'analyse/le reformatage des journaux peuvent facilement être gérés par des outils comme logstash, donc je ne suis pas sûr que ce soit un problème. Je garderais ça pour l'instant.

Si les gens veulent un format différent pour les journaux d'accès, peut-être pouvons-nous ajouter un identifiant spécifique ? De cette façon, nous ne casserions pas le format. Les journaux d'erreurs sont cependant un problème car nous ne fournissons pas de moyen de les formater. Dans ce cas, une variable d'environnement le ferait peut-être ?

Je ne pense pas que le format du journal d'accès doive changer. Il s'agit d'un format de journal courant en ce moment et nous avons le paramètre --access-log-format .

Le format du journal d'accès formate uniquement le _message_ du journal d'accès qui est transmis au gestionnaire. Le gestionnaire a alors son propre formateur.

Notre formateur par défaut pour les gestionnaires de flux sur stdout et stderr met un horodatage au début. Cela signifie qu'avec la configuration par défaut, le journal d'accès a _deux_ horodatages : un au début et un dans le message.

La modification du formateur du gestionnaire nécessite l'utilisation de l'une des options --logconfig (fichier ou dict).

Nous devrions envisager d'avoir un horodatage ISO8601 dans le formateur par défaut.

l'analyse / reformatage des journaux peut facilement être géré par des outils tels que logstash

Oui, mais c'est très pratique lorsque ces outils peuvent analyser l'horodatage avec des modèles intégrés afin que l'utilisateur n'ait pas à écrire d'expression régulière. Le problème d'origine a été ouvert car grok a un modèle intégré pour les horodatages ISO8601.

@tilgovi Je ne veux pas casser la compatibilité. NGINX offre également la possibilité de régler l'heure en utilisant le format ISO8601 ou Common Log Format :

$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

Je ferais la même chose car cela ne brise pas l'héritage. Au fait, ne devrions-nous pas simplement afficher la ligne du journal d'accès à la sortie ? Il semble que nous ne devrions pas avoir le premier en-tête avec le PID. Les pensées?

à propos de l'intégrer au formateur par défaut, je crains qu'il ne casse certains outils. Qu'en est-il d'avoir une variable d'environnement personnalisée TIME_ISO8601=true pour la forcer ?

Je ne veux pas casser la compatibilité.

Moi non plus. Je voulais seulement rouvrir le ticket car je pense que nous l'avons fermé pour la mauvaise raison. Nous avons tous les deux répondu comme si le problème était de changer de format de journal commun. Le problème est l'horodatage dans le formateur par défaut, pas le format du message du journal d'accès. Je suis content que nous puissions en discuter davantage, mais la réponse est peut-être de ne rien faire.

Au fait, ne devrions-nous pas simplement afficher la ligne du journal d'accès à la sortie ? Il semble que nous ne devrions pas avoir le premier en-tête avec le PID. Les pensées?

Possible. Je ne suis pas sûr.

Qu'en est-il d'avoir une variable d'environnement personnalisée

Peut-être d'accord. L'utilisateur peut toujours contrôler complètement le journal en utilisant la configuration de journalisation avancée. Nous essayons de simplifier certains paramètres pour la CLI, comme --log-level , afin que les utilisateurs n'aient pas à utiliser de fichiers de configuration. Peut-être pourrions-nous ajouter --log-date-format ? Il pourrait même reconnaître des chaînes symboliques comme iso8601 . Ce paramètre serait destiné aux utilisateurs qui ne souhaitent pas utiliser --log-config ou log_config_dict .

@tilgovi en attendant, la version 20.0 est un bon moment pour un changement de format puisque nous brisons la compatibilité avec python 2.

Je pense que ce qui m'inquiète le plus à propos de tout héritage, c'est que l'ISO8601 est difficile à analyser pour les yeux humains et que beaucoup de gens, dont moi, utilisent la console comme une opportunité d'observer ce qui se passe.

Je voudrais suggérer ce qui suit :

  • [ ] ajoutez une option -iso8601 qui force les journaux stdout et stderr à utiliser ce format (comme vous le suggérez)
  • [ ] dans le journal d'accès ajouter une option dans le format pour afficher l'heure sous ce format

Pendant que nous sommes ici, nous pourrions peut-être aussi avoir une option -utc pour utiliser UTC pour le moment ? Les pensées?

Juste pour être sûr, ce serait le diff proposé si nous changions simplement la valeur par défaut :

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"

Je pense qu'une option pour utiliser une date/heure ISO8601 dans les jetons de journal d'accès est intéressante, mais elle est distincte de ce qui a motivé ce problème.

Je ne suis pas très attaché à ça, d'ailleurs. 😄 Je veux juste représenter le problème avec précision.

nous devons probablement y réfléchir un peu plus. Je le reporte au 20.1 pour nous laisser quelques temps.

Chers développeurs,
Je suis confronté à un problème de perte de requête (n'a rien à voir avec Gunicorn). J'aurais besoin d'être en mesure d'avoir l'horodatage précis, y compris les microsecondes, comme dans cet exemple de l'un de nos serveurs Apache : 2019-10-30 14:27:16.960421 . Ce serait une amélioration intéressante, merci de l'avoir envisagée.

Un espoir si le drapeau, log-date-format iso8601 , sera disponible dans la prochaine version de gunicorn ?

Cette page vous a été utile?
0 / 5 - 0 notes