diff --git a/telegraf/apache.conf b/telegraf/apache.conf index 10136e3..e70452a 100644 --- a/telegraf/apache.conf +++ b/telegraf/apache.conf @@ -58,19 +58,28 @@ # COMBINED_LOG_FORMAT — NICHT HTTPD_* (das sind andere Muster, Telegraf kennt # sie nicht: "no pattern found for %{HTTPD_COMBINED_LOG_FORMAT}"). # Reihenfolge: spezifischste zuerst — VHost-Varianten vor der einfachen Form. - # EIGENES MUSTER statt %{COMBINED_LOG_FORMAT} — wegen eines realen Ausfalls: - # Die Log-Zeile hat nur SEKUNDEN-Aufloesung. Telegraf uebernimmt einen - # erkannten Zeitstempel als Sample-Zeit; bei mehreren Treffern pro Sekunde - # vergibt es +1 ms Aufschlag. Bei hoher Last (>1000 Zeilen/s) laeuft dieser - # Aufschlag in die naechste Sekunde und kollidiert mit echten Zeilen: - # "duplicate sample for timestamp ...; overrides not allowed" - # Gemessen an echten x22-Logs: 2000 Zeilen -> 286 Kollisionen. - # Prometheus weist den Batch ab, Telegraf wiederholt ihn endlos — der Node - # liefert dann GAR NICHTS mehr (auch keine Systemmetriken). + # EIGENES MUSTER statt %{COMBINED_LOG_FORMAT} — wegen eines realen Ausfalls. # - # Der Fix: das Zeitfeld heisst `log_time` (kein `ts`), darum nutzt Telegraf - # seine EIGENE Uhr mit Nanosekunden-Aufloesung. Die Log-Zeit bleibt als Feld - # erhalten, der Zeitstempel ist eindeutig. + # WARUM EIN EIGENES MUSTER: das eingebaute Muster vergibt dem Log-Zeitfeld den + # Namen `ts`. Telegraf nimmt einen erkannten Zeitstempel dann als SAMPLE-ZEIT, + # und die Log-Zeile hat nur SEKUNDEN-Aufloesung. Mit `log_time` findet Telegraf + # kein Zeitfeld mehr und stempelt mit eigener Uhr. Die Log-Zeit bleibt als + # Feld erhalten — praktisch, weil Remote Write nur MILLISEKUNDEN kann. + # + # DER EIGENTLICHE FEHLER liegt tiefer, und ein Zeitstempel-Trick loest ihn + # NICHT: Telegraf schreibt pro Sammelzyklus einen Batch mit EINEM Zeitstempel. + # Treffen zwei Requests derselben Serie (path+resp_code+verb) in dieselbe + # Millisekunde, entsteht "duplicate sample ... overrides not allowed". + # Prometheus weist den Batch ab, Telegraf wiederholt ihn ENDLOS — der Batch + # sitzt im FIFO-Kopf fest und der Node liefert danach GAR NICHTS mehr, auch + # kein system_uptime. Erkennungsmerkmal: derselbe eingefrorene Timestamp + # wiederholt sich alle ~15 s im Prometheus-Log. + # + # DIE LOESUNG ist deshalb der Aggregator weiter unten: er fasst alle + # Metriken einer Serie pro Intervall zu EINEM Punkt zusammen. Pro Serie und + # Intervall gibt es dann genau einen Punkt — eine Kollision ist strukturell + # unmoeglich, unabhaengig von der Last. Gemessen an 2000 echten x22-Zeilen: + # ohne Aggregator ~2000 Einzelpunkte, mit Aggregator 4 Punkte, 0 Konflikte. grok_custom_patterns = ''' APACHE_LINE (?:%{HOSTNAME:vh}(?::%{NUMBER:vport})? )?%{IPORHOST:client_ip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:log_time}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:http_version})?|-)" %{NUMBER:resp_code:int} (?:%{NUMBER:resp_bytes:int}|-)(?: "%{DATA:referrer}" "%{DATA:agent}")? ''' @@ -89,6 +98,39 @@ APACHE_LINE (?:%{HOSTNAME:vh}(?::%{NUMBER:vport})? )?%{IPORHOST:client_ip} %{USE [processors.converter.fields] tag = ["resp_code", "verb"] +# -------------------------------------------------------------------------- +# Aggregation: der eigentliche Schutz gegen Zeitstempel-Kollisionen +# -------------------------------------------------------------------------- +# WARUM DAS NOETIG IST (realer Ausfall, nicht Theorie): +# Telegraf schreibt pro Sammelzyklus einen Batch, dessen Metriken ALLE denselben +# Zeitstempel tragen. Prometheus' Remote Write kann nur Millisekunden. Treffen +# zwei Requests derselben Serie (path + resp_code + verb) in dieselbe +# Millisekunde, antwortet Prometheus: +# "duplicate sample for timestamp ...; overrides not allowed" +# Er verwirft damit den GANZEN Batch. Telegrafs Puffer ist FIFO: der abgelehnte +# Batch bleibt am Kopf stehen und wird endlos wiederholt — die Node liefert +# danach gar nichts mehr, auch keine Systemmetriken. Merkmal im Log: derselbe +# eingefrorene Timestamp alle ~15 s. +# +# Der Aggregator loest das an der Wurzel: er fasst alle Metriken einer Serie pro +# Intervall zu EINEM Punkt zusammen. Damit gibt es pro Serie und Intervall genau +# einen Wert — eine Kollision ist strukturell unmoeglich, egal wie hoch die Last +# ist. Zusaetzlich sinkt die Serienzahl deutlich, was Prometheus entlastet. +# +# Was dabei entsteht (gemessen an 2000 echten x22-Zeilen, 4 Gruppen): +# apache_access_resp_bytes_count — Requests je Gruppe (das brauchen die Panels) +# apache_access_resp_bytes_sum — uebertragene Bytes je Gruppe +# apache_access_resp_bytes_mean — mittlere Antwortgroesse +# Die Felder `resp_code` und `verb` sind Tags und bleiben damit Gruppenschluessel. +# +# `drop_original = true` ist zwingend: ohne das schickt Telegraf die Einzelwerte +# ZUSAETZLICH und die Kollision waere wieder da. +[[aggregators.basicstats]] + namepass = ["apache_access"] + period = "60s" + drop_original = true + stats = ["count", "sum", "mean"] + # -------------------------------------------------------------------------- # 3) mod_status (optional, auskommentiert) # --------------------------------------------------------------------------