|
@@ -0,0 +1,138 @@
|
|
|
|
|
+apiVersion: v1
|
|
|
|
|
+kind: ConfigMap
|
|
|
|
|
+metadata:
|
|
|
|
|
+ name: vector-config
|
|
|
|
|
+ namespace: {{ .Release.Namespace }}
|
|
|
|
|
+ labels:
|
|
|
|
|
+ app: vector
|
|
|
|
|
+data:
|
|
|
|
|
+ vector.toml: |
|
|
|
|
|
+ # Vector config adapted from Log.md
|
|
|
|
|
+ [sources.kubernetes_logs]
|
|
|
|
|
+ type = "kubernetes_logs"
|
|
|
|
|
+ include_namespaces = ["{{ .Values.vector.namespace }}"]
|
|
|
|
|
+ # read pod/container logs under /var/log/pods
|
|
|
|
|
+ host_path = "/var/log"
|
|
|
|
|
+
|
|
|
|
|
+ [transforms.parse_json]
|
|
|
|
|
+ type = "remap"
|
|
|
|
|
+ inputs = ["kubernetes_logs"]
|
|
|
|
|
+ source = '''
|
|
|
|
|
+ parsed = parse_json!(.message)
|
|
|
|
|
+ .ts = parsed.ts
|
|
|
|
|
+ .level = parsed.level
|
|
|
|
|
+ .app = parsed.app
|
|
|
|
|
+ .env = parsed.env
|
|
|
|
|
+ .traceId = parsed.traceId
|
|
|
|
|
+ .uri = parsed.uri
|
|
|
|
|
+ .uri_group = parsed.uri_group
|
|
|
|
|
+ .duration_ms = to_int!(parsed.duration, 0)
|
|
|
|
|
+ .userId = parsed.userId
|
|
|
|
|
+ .event = parsed.event
|
|
|
|
|
+ .error = parsed.error
|
|
|
|
|
+ .status = parsed.status
|
|
|
|
|
+ .event_class = parsed.event_class
|
|
|
|
|
+
|
|
|
|
|
+ # fallback derive event_class from uri_group
|
|
|
|
|
+ if starts_with(.uri_group, "/order") {
|
|
|
|
|
+ .event_class = "order"
|
|
|
|
|
+ } else if starts_with(.uri_group, "/payment") {
|
|
|
|
|
+ .event_class = "payment"
|
|
|
|
|
+ } else if !exists(.event_class) {
|
|
|
|
|
+ .event_class = "api"
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # keep kubernetes metadata as labels fields
|
|
|
|
|
+ .k8s_ns = .kubernetes.namespace_name
|
|
|
|
|
+ .k8s_pod = .kubernetes.pod_name
|
|
|
|
|
+ .k8s_labels = .kubernetes.labels
|
|
|
|
|
+ '''
|
|
|
|
|
+
|
|
|
|
|
+ [transforms.filter_services]
|
|
|
|
|
+ type = "filter"
|
|
|
|
|
+ inputs = ["parse_json"]
|
|
|
|
|
+ # keep only selected apps (based on k8s labels.app or parsed .app)
|
|
|
|
|
+ condition = '(.kubernetes.labels.app in {{ toJson .Values.vector.logSelector }}) || (.app in {{ toJson .Values.vector.logSelector }})'
|
|
|
|
|
+
|
|
|
|
|
+ [transforms.filter_levels]
|
|
|
|
|
+ type = "filter"
|
|
|
|
|
+ inputs = ["filter_services"]
|
|
|
|
|
+ condition = '.level != "DEBUG" && .level != "TRACE"'
|
|
|
|
|
+
|
|
|
|
|
+ [sinks.loki]
|
|
|
|
|
+ type = "loki"
|
|
|
|
|
+ inputs = ["filter_levels"]
|
|
|
|
|
+ endpoint = "{{ .Values.vector.loki.endpoint }}"
|
|
|
|
|
+ encoding.codec = "json"
|
|
|
|
|
+ [sinks.loki.labels]
|
|
|
|
|
+ env = "{{ env }}"
|
|
|
|
|
+ app = "{{ app }}"
|
|
|
|
|
+ level = "{{ level }}"
|
|
|
|
|
+ event_class = "{{ event_class }}"
|
|
|
|
|
+ uri_group = "{{ uri_group }}"
|
|
|
|
|
+ status = "{{ status }}"
|
|
|
|
|
+
|
|
|
|
|
+ [transforms.to_metrics]
|
|
|
|
|
+ type = "log_to_metric"
|
|
|
|
|
+ inputs = ["filter_levels"]
|
|
|
|
|
+
|
|
|
|
|
+ # Counter: Total requests per app/uri_group/status
|
|
|
|
|
+ [[transforms.to_metrics.metrics]]
|
|
|
|
|
+ type = "counter"
|
|
|
|
|
+ field = "message"
|
|
|
|
|
+ name = "requests_total"
|
|
|
|
|
+ tags.app = "{{ app }}"
|
|
|
|
|
+ tags.env = "{{ env }}"
|
|
|
|
|
+ tags.uri_group = "{{ uri_group }}"
|
|
|
|
|
+
|
|
|
|
|
+ # Counter: HTTP request errors
|
|
|
|
|
+ [[transforms.to_metrics.metrics]]
|
|
|
|
|
+ type = "counter"
|
|
|
|
|
+ field = "message"
|
|
|
|
|
+ name = "requests_errors_total"
|
|
|
|
|
+ filter.condition = '.status == "server_error" || .status == "client_error"'
|
|
|
|
|
+ tags.app = "{{ app }}"
|
|
|
|
|
+ tags.env = "{{ env }}"
|
|
|
|
|
+ tags.status = "{{ status }}"
|
|
|
|
|
+
|
|
|
|
|
+ # Histogram: Request duration (latency)
|
|
|
|
|
+ [[transforms.to_metrics.metrics]]
|
|
|
|
|
+ type = "histogram"
|
|
|
|
|
+ field = "duration_ms"
|
|
|
|
|
+ name = "request_duration_ms"
|
|
|
|
|
+ tags.app = "{{ app }}"
|
|
|
|
|
+ tags.uri_group = "{{ uri_group }}"
|
|
|
|
|
+ tags.env = "{{ env }}"
|
|
|
|
|
+
|
|
|
|
|
+ # Counter: Total orders
|
|
|
|
|
+ [[transforms.to_metrics.metrics]]
|
|
|
|
|
+ type = "counter"
|
|
|
|
|
+ field = "message"
|
|
|
|
|
+ name = "orders_total"
|
|
|
|
|
+ filter.condition = '.event_class == "order"'
|
|
|
|
|
+ tags.app = "{{ app }}"
|
|
|
|
|
+ tags.env = "{{ env }}"
|
|
|
|
|
+
|
|
|
|
|
+ # Counter: Failed orders
|
|
|
|
|
+ [[transforms.to_metrics.metrics]]
|
|
|
|
|
+ type = "counter"
|
|
|
|
|
+ field = "message"
|
|
|
|
|
+ name = "orders_failed_total"
|
|
|
|
|
+ filter.condition = '.event_class == "order" && (.status == "server_error" || .status == "client_error")'
|
|
|
|
|
+ tags.app = "{{ app }}"
|
|
|
|
|
+ tags.env = "{{ env }}"
|
|
|
|
|
+
|
|
|
|
|
+ # Counter: Payment events
|
|
|
|
|
+ [[transforms.to_metrics.metrics]]
|
|
|
|
|
+ type = "counter"
|
|
|
|
|
+ field = "message"
|
|
|
|
|
+ name = "payment_events_total"
|
|
|
|
|
+ filter.condition = '.event_class == "payment"'
|
|
|
|
|
+ tags.app = "{{ app }}"
|
|
|
|
|
+ tags.env = "{{ env }}"
|
|
|
|
|
+
|
|
|
|
|
+ [sinks.prometheus]
|
|
|
|
|
+ type = "prometheus_exporter"
|
|
|
|
|
+ inputs = ["to_metrics"]
|
|
|
|
|
+ address = "{{ .Values.vector.prometheus.exporterAddress }}"
|
|
|
|
|
+ default_namespace = "shop_recycle"
|