apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: alloy namespace: argocd annotations: argocd.argoproj.io/sync-wave: "0" finalizers: - resources-finalizer.argocd.argoproj.io spec: project: default source: repoURL: https://grafana.github.io/helm-charts chart: alloy targetRevision: "1.10.0" helm: values: | alloy: configMap: content: |- // Discover Kubernetes pods discovery.kubernetes "pods" { role = "pod" } // Relabel pods to intelligently map existing Kubernetes labels to service/component discovery.relabel "pods" { targets = discovery.kubernetes.pods.targets // Create service label - try multiple sources in priority order rule { source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_name"] regex = "(.+)" replacement = "${1}" target_label = "service" } // 2. Second priority: app label rule { source_labels = ["__meta_kubernetes_pod_label_app", "service"] regex = "^(.+);$" replacement = "${1}" target_label = "service" } // 3. Third priority: extract from pod name (remove hash suffix) rule { source_labels = ["__meta_kubernetes_pod_name", "service"] regex = "^([a-z0-9-]+?)(?:-[a-f0-9]{5,10})?;$" replacement = "${1}" target_label = "service" } // Create component label from app.kubernetes.io/component or component label rule { source_labels = ["__meta_kubernetes_pod_label_app_kubernetes_io_component"] regex = ".+" target_label = "component" } rule { source_labels = ["__meta_kubernetes_pod_label_component"] regex = ".+" target_label = "component" } // Drop pods that we still can't identify rule { source_labels = ["service"] regex = "^$" action = "drop" } // Map standard Kubernetes metadata to Loki labels rule { source_labels = ["__meta_kubernetes_namespace"] target_label = "namespace" } rule { source_labels = ["__meta_kubernetes_pod_name"] target_label = "pod" } rule { source_labels = ["__meta_kubernetes_pod_container_name"] target_label = "container" } } // Parse Traefik access logs to derive log level from HTTP status code loki.process "traefik_level" { forward_to = [loki.process.filter.receiver] stage.match { selector = "{service=\"traefik\"}" stage.regex { expression = `\"\w+ .+ HTTP/[\d.]+\" (?P[0-9])[0-9]{2} ` } stage.template { source = "level" template = `{{ if eq .status_class "5" }}error{{ else if eq .status_class "4" }}warn{{ else }}info{{ end }}` } stage.labels { values = { level = "", } } } } // Filter out noisy fsnotify/inotify errors from Loki and ArgoCD loki.process "filter" { forward_to = [loki.write.loki.receiver] stage.drop { expression = ".*fsnotify.*|.*too many open files.*|.*inotify.*" drop_counter_reason = "inotify_noise" } } // Collect logs from Kubernetes pods using the Kubernetes API loki.source.kubernetes "pods" { targets = discovery.relabel.pods.output forward_to = [loki.process.traefik_level.receiver] } // Write logs to Loki loki.write "loki" { endpoint { url = "http://loki.metrics.svc.cluster.local:3100/loki/api/v1/push" } } destination: server: https://kubernetes.default.svc namespace: metrics syncPolicy: syncOptions: - CreateNamespace=true