vector.yaml aktualisiert
This commit is contained in:
+101
-10
@@ -1,47 +1,138 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# VECTOR CONFIGURATION
|
||||||
|
# Zweck: Docker-Container-Logs einsammeln, aufbereiten und an Loki (-> Grafana)
|
||||||
|
# senden. Zusätzlich Debug-Ausgabe in der Konsole.
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# GLOBAL / API (optional, aber praktisch für Monitoring von Vector selbst)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
api:
|
||||||
|
enabled: true
|
||||||
|
address: "127.0.0.1:8686" # Vector-eigenes Dashboard/API, nur lokal erreichbar
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# SOURCES: Woher kommen die Daten?
|
# SOURCES: Woher kommen die Daten?
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
sources:
|
sources:
|
||||||
docker_logs:
|
docker_logs:
|
||||||
type: docker_logs
|
type: docker_logs
|
||||||
|
# Nur laufende + gestoppte Container-Logs seit Vector-Start (Default: true)
|
||||||
|
include_containers: [] # leer = alle Container
|
||||||
|
exclude_containers:
|
||||||
|
- "vector" # verhindert, dass Vector seine eigenen Logs einsammelt (Log-Loop!)
|
||||||
|
auto_partial_merge: true # zusammengehörige, von Docker aufgeteilte Zeilen mergen
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# TRANSFORMS: Verarbeitung der Daten
|
# TRANSFORMS: Verarbeitung der Daten
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
transforms:
|
transforms:
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1. Grundbereinigung + feste Metadaten
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
parse_logs:
|
parse_logs:
|
||||||
type: remap
|
type: remap
|
||||||
inputs: [docker_logs]
|
inputs: [docker_logs]
|
||||||
source: |
|
source: |
|
||||||
# FIX: Prüfung, ob .message existiert und ein String ist (verhindert Error E103)
|
# --- Message bereinigen (Newlines raus, damit Loki/Grafana sauber anzeigen) ---
|
||||||
if is_string(.message) {
|
if is_string(.message) {
|
||||||
.message = replace(.message, "\n", " ")
|
.message = replace!(.message, "\n", " ")
|
||||||
|
.message = strip_whitespace(.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Das Feld 'service' setzen.
|
# --- Statisches Service-/Cluster-Label ---
|
||||||
.service = "my-cluster"
|
.service = "my-cluster"
|
||||||
|
|
||||||
# Optional: Zusätzliche Metadaten bereinigen
|
# --- Docker-Metadaten absichern (falls mal Felder fehlen) ---
|
||||||
# .container_name = .container_name || "unknown"
|
.container_name = .container_name || "unknown"
|
||||||
|
.host = .host || "unknown"
|
||||||
|
|
||||||
|
# --- Container-Image ohne Tag/Hash extrahieren (weniger Kardinalität) ---
|
||||||
|
if exists(.image) {
|
||||||
|
image_parts, err = split(string!(.image), ":")
|
||||||
|
if err == null {
|
||||||
|
.image_name = image_parts[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Log-Level heuristisch erkennen (falls die App das nicht strukturiert liefert) ---
|
||||||
|
.level = "info"
|
||||||
|
msg_lower = downcase(to_string(.message) ?? "")
|
||||||
|
if contains(msg_lower, "error") || contains(msg_lower, "err ") || contains(msg_lower, "exception") {
|
||||||
|
.level = "error"
|
||||||
|
} else if contains(msg_lower, "warn") {
|
||||||
|
.level = "warn"
|
||||||
|
} else if contains(msg_lower, "debug") {
|
||||||
|
.level = "debug"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2. Versuch, JSON-Logs (strukturierte Logs von Apps) zu parsen
|
||||||
|
# Falls die Message JSON ist, wird sie geflattet -> mehr Kontext in Grafana.
|
||||||
|
# Falls nicht, bleibt .message unverändert (kein Fehler, kein Absturz).
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
parse_json_if_possible:
|
||||||
|
type: remap
|
||||||
|
inputs: [parse_logs]
|
||||||
|
source: |
|
||||||
|
parsed, err = parse_json(.message)
|
||||||
|
if err == null {
|
||||||
|
# nur mergen, wenn wirklich ein Objekt rauskam (kein Array/String/Zahl)
|
||||||
|
if is_object(parsed) {
|
||||||
|
. = merge(., object!(parsed), deep: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# SINKS: Wohin sollen die Daten?
|
# SINKS: Wohin sollen die Daten?
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
sinks:
|
sinks:
|
||||||
# Debug-Ausgabe in der Konsole
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Debug-Ausgabe in der Konsole (praktisch zum Testen, kann später raus)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
stdout_debug:
|
stdout_debug:
|
||||||
type: console
|
type: console
|
||||||
inputs: [parse_logs]
|
inputs: [parse_json_if_possible]
|
||||||
encoding:
|
encoding:
|
||||||
codec: json
|
codec: json
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Loki-Sink -> Grafana
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
loki_sink:
|
loki_sink:
|
||||||
type: loki
|
type: loki
|
||||||
inputs: [parse_logs]
|
inputs: [parse_json_if_possible]
|
||||||
endpoint: "http://docker1.lan:3100"
|
endpoint: "http://docker1.lan:3100"
|
||||||
|
|
||||||
|
# Falls dein Loki Multi-Tenancy nutzt (Standard bei vielen Setups, auch Single-User).
|
||||||
|
# Falls "no org id"-Fehler auftauchen: diese Zeile aktivieren.
|
||||||
|
tenant_id: "fake"
|
||||||
|
|
||||||
encoding:
|
encoding:
|
||||||
codec: json
|
codec: json
|
||||||
|
# Diese Felder werden bereits als Loki-Labels genutzt -> nicht doppelt im JSON-Body
|
||||||
|
except_fields: ["host", "service", "container_name"]
|
||||||
|
|
||||||
|
# WICHTIG: Nur Felder mit niedriger Kardinalität als Labels verwenden!
|
||||||
|
# container_id, message, timestamp etc. NIEMALS als Label -> "too many streams" in Loki.
|
||||||
labels:
|
labels:
|
||||||
host: "{{ host }}"
|
host: "{{ host }}"
|
||||||
service: "{{ service }}"
|
service: "{{ service }}"
|
||||||
container_name: "{{ container_name }}"
|
container_name: "{{ container_name }}"
|
||||||
|
level: "{{ level }}"
|
||||||
|
|
||||||
|
# Reihenfolge der Log-Zeilen pro Stream sicherstellen
|
||||||
|
out_of_order_action: rewrite_timestamp
|
||||||
|
|
||||||
|
batch:
|
||||||
|
max_bytes: 1048576 # 1 MB pro Batch
|
||||||
|
timeout_secs: 5
|
||||||
|
|
||||||
|
request:
|
||||||
|
retry_attempts: 10
|
||||||
|
retry_max_duration_secs: 30
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
enabled: true
|
||||||
Reference in New Issue
Block a user