Gunicorn: Das Standard-Datumsformat der Gunicorn-Fehlerprotokollierung entspricht nicht dem ISO8601-Standard

Erstellt am 3. Mai 2018  ·  34Kommentare  ·  Quelle: benoitc/gunicorn

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

Die Motivation für dieses Problem ist die folgende Grok-Anweisung in 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" }

Hätte das Datumsformat kein Leerzeichen zwischen der Zeit und der Zeitzone enthalten, hätte die folgende Anweisung es abgeschnitten:

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

Ich würde argumentieren, dass ein Standard-Datumsformat besser für eine Standardkonfiguration geeignet wäre. Ich denke, das Hinzufügen eines zusätzlichen Leerzeichens bringt keinen Mehrwert, sondern verursacht stattdessen Probleme. Entweder muss die gesamte Standard-Logconfig ersetzt werden, was übertrieben ist, oder es müssen benutzerdefinierte Ausdrücke in Protokollparsern geschrieben werden, um dies zu berücksichtigen.

Improvement Discussion FeaturLogging

Hilfreichster Kommentar

Ok, das bedeutet also, dass grok in Logstash mit einem strengen Muster vorinstalliert ist und nicht mit dem nachsichtigen. Ich habe zuvor bei der BBC/EBU mit Standards-Leuten gearbeitet und erinnere mich an diese schrecklichen Formulierungen. Für die Lesbarkeit "(sagen wir) ein Leerzeichen" Dies ist nicht implementierbar .... was ist das für ein Zeichen? Natürlich können Sie an dieser Stelle beliebige Zeichen zulassen und das ist nicht in Ordnung. Die Jungs von Logstash haben dies also folgendermaßen implementiert, um entweder T oder Space zu sein

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

Darüber hinaus ist dies nicht das, worum es bei dem Problem ging. Das Problem war, dass das Zeitzonen-Suffix ein Leerzeichen hat, das der Standard NICHT ERLAUBT.

Also nein, leider ist dieses Format nicht üblich. Dieses Format ist unorthodox und spezifisch für Gunicorn. Ich weiß, wie dumm das klingt, dass wir über ein Leerzeichen streiten, aber wenn es um Sprachen und Automotonen geht, ist Syntax alles.

Alle 34 Kommentare

Das Datumsformat folgt dem Common Log Format: https://en.wikipedia.org/wiki/Common_Log_Format

Oh, Entschuldigung. Meine Antwort bezieht sich auf das Zugriffsprotokollformat. In diesem Bericht geht es um das Fehlerprotokollformat.

Sieht so aus, als könnten Sie %{DATESTAMP} %{ISO8601_TIMEZONE} verwenden

für 19.x ist es zu spät, um Änderungen vorzunehmen. Es würde eine Menge Logging-Nutzung stören. Wollen wir das in der nächsten Hauptversion ändern?

@tilgovi also ist das etwas gewollt?

Viele bereitgestellte Systeme verlassen sich auf das aktuelle Format. Ich mache mir Sorgen, dass es sich um eine zu große Änderung handelt, die nicht viel Wert bringt, da in Log-Stash-ähnlichen Systemen immer eine Regel darüber geschrieben werden kann. Die Gedanken?

Ein möglicher Kompromiss könnte eine Umstellung und Abwertung sein. Sie können damit beginnen, das ungerade (wenn auch geringfügige) Datumsformat, das nicht den Standards entspricht, auslaufen zu lassen und dem Benutzer einen Wechsel zu einem festen Protokollzeilenformat bereitzustellen. Ich weiß, dass ich den Logger über Python überschreiben kann, aber da Gunicorn mit seinen konkurrierenden Einstellungen eingebaut ist, wäre es nicht meine bevorzugte Wahl: Ich bin keine OCD-Person, aber das Kochen einer Grok-Abfrage ist eine moderne Art von Folter, besonders wenn der Unterschied Sie berücksichtigen, ist ein Leerzeichen :D Und dann ist es Sache des Entwicklers, diese Übereinstimmung länger als nötig aufrechtzuerhalten, falls sich etwas ändern sollte. Es ist nicht das Ende der Welt, wenn es sein muss, aber wir beheben weiterhin Fehler, auch wenn sich die Leute auf die fehlerhafte Software verlassen ... Das denke ich ... nicht sicher, ob die Frage an mich gerichtet war ...

Wir könnten die Standardeinstellung für R20 ändern.

Dieses Format ist eigentlich ziemlich verbreitet. Der RFC 3339 enthält eine Anmerkung dazu:

HINWEIS: ISO 8601 definiert Datum und Uhrzeit getrennt durch „T“. Anwendungen, die diese Syntax verwenden, können aus Gründen der Lesbarkeit ein vollständiges Datum und eine vollständige Uhrzeit angeben, die (z. B.) durch ein Leerzeichen getrennt sind.

Das Fehlerprotokoll wird auch auf der Kommandozeile ausgegeben und sollte von einem Menschen gelesen werden und das möchte ich auch so beibehalten. Gibt es ein Problem mit dem Zeitzonenformat?

Ok, das bedeutet also, dass grok in Logstash mit einem strengen Muster vorinstalliert ist und nicht mit dem nachsichtigen. Ich habe zuvor bei der BBC/EBU mit Standards-Leuten gearbeitet und erinnere mich an diese schrecklichen Formulierungen. Für die Lesbarkeit "(sagen wir) ein Leerzeichen" Dies ist nicht implementierbar .... was ist das für ein Zeichen? Natürlich können Sie an dieser Stelle beliebige Zeichen zulassen und das ist nicht in Ordnung. Die Jungs von Logstash haben dies also folgendermaßen implementiert, um entweder T oder Space zu sein

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

Darüber hinaus ist dies nicht das, worum es bei dem Problem ging. Das Problem war, dass das Zeitzonen-Suffix ein Leerzeichen hat, das der Standard NICHT ERLAUBT.

Also nein, leider ist dieses Format nicht üblich. Dieses Format ist unorthodox und spezifisch für Gunicorn. Ich weiß, wie dumm das klingt, dass wir über ein Leerzeichen streiten, aber wenn es um Sprachen und Automotonen geht, ist Syntax alles.

Das ist hilfreich, @kozmaz87. Danke, dass Sie sich mit der Spezifikation beschäftigt haben.

Aber da wir hier sind, würde ich gerne auch auf das Zugriffsprotokollformat hinweisen, das noch schlimmer ist. Ich habe es nicht einmal geschafft, im Code eine Stelle zu finden, von der es kommt ... Es ist aus einem ziemlich obskuren Konfigurationsmechanismus aufgebaut. von woanders zugeteilt. Ich habe den Code nicht ausgecheckt, um ihn zu untersuchen, aber er erzeugt diese Ausgabe:

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

Wenn wir uns die Gunicorn-Dokumente ansehen, erfahren wir, dass der 2. Teil dieses Protokolls aus irgendeinem Grund ein '-' ist ... der 3. Teil soll der Benutzer sein, der ebenfalls ein '-' auswertet, nicht sicher warum, und dann kommt dies schön Datumsformat, bei dem die Stunde mit dem Jahr durch ein ':' verheiratet ist und natürlich wieder das bevorzugte Leerzeichen-getrennte Zeitzonen-Suffix. Aber nachdem ich herumgegraben hatte, stellte ich fest, dass nginx es so protokolliert, also nehme ich an, dass dies der Ursprung dieser durch Leerzeichen getrennten Zeitzonensache ist, indem ich versuche, die nginx-Zugriffsprotokolle nachzuahmen. HAProxy verwendet dies auch, außer dass es kein Zeitzonen-Suffix anbringt ...

Holzfällerei ist verrückt ... Jemand bringt mir einen Eimer mit eiskaltem Wasser :)

Das Zugriffsprotokollformat ist definitiv "üblich": https://en.wikipedia.org/wiki/Common_Log_Format

Wir fügen jedoch Referrer und User Agent am Ende hinzu. Siehe das Flag --access-logformat : http://docs.gunicorn.org/en/latest/settings.html#access -log-format

Das ist mir klar. Ich finde es nur lustig, dass das 2. Element ein '-' ist: D Es fühlt sich an, als ob derjenige, der es implementiert hat, es damit hatte und einfach ein '-' eingefügt hat

Ich würde das aktuelle Protokollformat beibehalten. Das imo-Common-Format ist gut und mir ist keine Änderung der Upstream-Server bekannt. die Gedanken? cc @tilgovi

Bump @tilgovi auch @berkerpeksag

Schließe das Problem, da es nicht behoben werden kann. Wie @tilgovi sagte, verwenden wir das [gängige Protokollformat](
https://en.wikipedia.org/wiki/Common_Log_Format.

Ich denke, wir könnten das offen lassen. Wir verwenden nicht das allgemeine Protokollformat für das Fehlerprotokoll. Das allgemeine Protokollformat ist ein Zugriffsprotokollformat und wir verwenden es dort.

Eigentlich egal. Ich habe es gerade noch einmal überprüft und wir verwenden für beide dieselbe Zeitformatzeichenfolge. Das scheint mir besser als jede Alternative. Ich möchte nicht, dass das Zugriffsprotokoll und das Fehlerprotokoll unterschiedliche Datumsformate haben.

Ich verstehe das Problem jetzt besser und denke, wir sollten wieder öffnen.

Hier ist eine Beispielausgabe von Gunicorn mit Standardeinstellungen:

[2019-01-25 11:44:34 -0800] [22794] [INFO] Starten von Gunicorn 19.9.0
[2019-01-25 11:44:34 -0800] [22794] [INFO] Zuhören unter: http://127.0.0.1 :8000 (22794)
[2019-01-25 11:44:34 -0800] [22794] [INFO] Nutzt Worker: sync
[2019-01-25 11:44:34 -0800] [22797] [INFO] Booting Worker mit 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 " -" "locken/7.54.0"

Es geht nicht darum, das allgemeine Protokollformat des Zugriffsprotokolls zu analysieren, sondern um die Analyse der _gesamten Protokollzeile_.

Gunicorn gibt am Anfang der Protokollzeile einen Zeitstempel, eine PID und eine Ebene aus. Die Zugriffsprotokollzeilen haben _auch_ eine Nachricht im gemeinsamen Protokollformat mit einem eigenen Zeitstempel.

Beachten Sie, dass die Zeitstempel nicht das gleiche Format haben. Die ursprüngliche Anforderung für dieses Problem war, dass der Zeitstempel am Anfang der Protokollzeile kein Leerzeichen hat, _genau wie das übliche Protokollformat_.

Das würde so aussehen:

[25/Jan/2019:11:44:34 -0800] [22794] [INFO] Gunicorn 19.9.0 gestartet
[25/Jan/2019:11:44:34 -0800] [22794] [INFO] Zuhören unter: http://127.0.0.1 :8000 (22794)
[25/Jan/2019:11:44:34 -0800] [22794] [INFO] Nutzt Worker: sync
[25/Jan/2019:11:44:34 -0800] [22797] [INFO] Booting Worker mit 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 "-" "locken/7.54.0"

Ich denke, die Antwort lautet wahrscheinlich nicht, weil das gängige Protokollformat nicht so international ist (es hat einen kurzen Monatsnamen).

Wir könnten jedoch den Zeitstempel am Anfang jeder Protokollzeile in einen ISO8601-Zeitstempel ändern.

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

Das Leerzeichen zwischen Datum und Uhrzeit ist anstelle eines T-Zeichens tatsächlich zulässig, ein Leerzeichen zwischen der Uhrzeit und dem Zonenoffset jedoch nicht.

Hier sind gültige ISO8601-Formate, die wir haben könnten:

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

Vergleichen Sie mit dem, was wir jetzt haben:

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

Ich würde mir jedoch große Sorgen machen, bereitgestellte Systeme zu beschädigen.

Nun, das Analysieren/Neuformatieren von Protokollen kann problemlos mit Tools wie Logstash gehandhabt werden, daher bin ich mir nicht sicher, ob dies ein Problem ist. Ich würde das jetzt so beibehalten.

Wenn die Leute ein anderes Format für Zugriffsprotokolle wünschen, können wir vielleicht eine bestimmte Kennung dafür hinzufügen? Auf diese Weise würden wir das Format nicht brechen. Fehlerprotokolle sind jedoch ein Problem, da wir keine Möglichkeit bieten, sie zu formatieren. In einem solchen Fall würde es vielleicht eine Umgebungsvariable tun?

Ich denke nicht, dass sich das Format des Zugriffsprotokolls ändern sollte. Es ist derzeit ein gängiges Protokollformat und wir haben die Einstellung --access-log-format .

Das Zugriffsprotokollformat formatiert nur die _Nachricht_ des Zugriffsprotokolls, das an den Handler übergeben wird. Der Handler hat dann seinen eigenen Formatierer.

Unser Standardformatierer für die Stream-Handler auf stdout und stderr setzt einen Zeitstempel an den Anfang. Das bedeutet, dass das Zugriffsprotokoll mit der Standardkonfiguration _zwei_ Zeitstempel hat: einen am Anfang und einen in der Nachricht.

Das Ändern des Formatierers für den Handler erfordert die Verwendung einer der --logconfig -Optionen (file oder dict).

Wir sollten erwägen, einen ISO8601-Zeitstempel im Standardformatierer zu haben.

Das Analysieren/Neuformatieren von Protokollen kann problemlos mit Tools wie Logstash gehandhabt werden

Ja, aber es ist sehr praktisch, wenn diese Tools den Zeitstempel mit integrierten Mustern parsen können, sodass der Benutzer keine regulären Ausdrücke schreiben muss. Das ursprüngliche Problem wurde geöffnet, weil grok ein eingebautes Muster für ISO8601-Zeitstempel hat.

@tilgovi Ich möchte die Kompatibilität nicht brechen. Auch NGINX bietet die Möglichkeit, die Zeit entweder im ISO8601-Format oder im Common Log Format einzustellen:

$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

Ich würde dasselbe tun, da es das Erbe nicht bricht. Übrigens sollten wir nicht einfach die Zugriffsprotokollzeile zur Ausgabe anzeigen? Es scheint, dass wir den ersten Header mit der PID nicht haben sollten. Die Gedanken?

darüber, dass es Teil des Standardformatierers wird, mache ich mir Sorgen, dass es irgendein Tool kaputt macht. Wie wäre es mit einer benutzerdefinierten Umgebungsvariable TIME_ISO8601=true , um dies zu erzwingen?

Ich möchte die Kompatibilität nicht brechen.

Ich auch nicht. Ich wollte das Ticket nur wieder öffnen, weil ich denke, dass wir es aus dem falschen Grund geschlossen haben. Wir haben beide reagiert, als ob das Problem darin bestünde, das gemeinsame Protokollformat zu ändern. Das Problem ist der Zeitstempel im Standardformatierer, nicht das Format der Zugriffsprotokollnachricht. Ich bin froh, dass wir weiter darüber diskutieren können, aber die Antwort ist vielleicht, immer noch nichts zu tun.

Übrigens sollten wir nicht einfach die Zugriffsprotokollzeile zur Ausgabe anzeigen? Es scheint, dass wir den ersten Header mit der PID nicht haben sollten. Die Gedanken?

Möglich. Ich bin mir nicht sicher.

Was ist mit einer benutzerdefinierten Umgebungsvariable?

Vielleicht in Ordnung. Der Benutzer kann das Protokoll immer vollständig steuern, indem er die erweiterte Protokollierungskonfiguration verwendet. Wir versuchen, einige Einstellungen für die CLI einfach zu machen, wie --log-level , damit Benutzer keine Konfigurationsdateien verwenden müssen. Vielleicht könnten wir --log-date-format hinzufügen? Es könnte sogar symbolische Zeichenfolgen wie iso8601 erkennen. Diese Einstellung ist für Benutzer gedacht, die --log-config oder log_config_dict nicht verwenden möchten.

@tilgovi in der Zwischenzeit ist die Version 20.0 ein guter Zeitpunkt für eine Änderung des Formats, da wir die Kompatibilität mit Python 2 brechen.

Ich denke, was mich bei Altlasten mehr beunruhigt, ist, dass ISO8601 für das menschliche Auge schwer zu analysieren ist und viele Leute, einschließlich mir, die Konsole als Gelegenheit nutzen, um zu beobachten, was passiert.

Ich möchte folgendes vorschlagen:

  • [ ] füge eine Option -iso8601 hinzu, die stdout- und stderr-Protokolle dazu zwingt, dieses Format zu verwenden (wie du vorschlägst)
  • [ ] im Zugriffsprotokoll fügen Sie eine Option im Format hinzu, um die Zeit in diesem Format anzuzeigen

Während wir hier sind, könnten wir vielleicht auch eine -utc Option haben, um UTC für die Zeit zu verwenden? Die Gedanken?

Nur um sicherzugehen, wäre dies der vorgeschlagene Unterschied, wenn wir nur die Standardeinstellung ändern würden:

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"

Ich denke, eine Option zur Verwendung einer ISO8601-Datumszeit in den Zugriffsprotokolltoken ist interessant, aber sie ist unabhängig von dem, was dieses Problem motiviert hat.

Davon halte ich übrigens nichts. 😄 Ich möchte nur das Thema genau darstellen.

da müssen wir wohl noch ein bisschen drüber nachdenken. Ich verschiebe es auf den 20.1, um uns einige Zeit zu lassen.

Liebe Entwickler,
Ich habe ein Problem mit dem Verlust von Anfragen (hat nichts mit Gunicorn zu tun). Ich müsste in der Lage sein, den genauen Zeitstempel einschließlich der Mikrosekunden zu haben, wie in diesem Beispiel von einem unserer Apache-Server: 2019-10-30 14:27:16.960421 . Es wäre eine coole Verbesserung, danke, dass Sie darüber nachgedacht haben.

Gibt es Hoffnung, ob die Flagge, log-date-format iso8601 , in der nächsten Version von Gunicorn verfügbar sein wird?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen