Grafana Alloy

Grafana Alloy is an open source OpenTelemetry Collector distribution with built-in Prometheus pipelines and support for metrics, logs, traces, and profiles.

It supports pushing logs to loki and metrics to Prometheus. It is the successor to promtail.

Configuration

Configuration is done via the config.alloy config file.

Example:

// System Logs
local.file_match "system" {
	path_targets = [{
		__address__ = "localhost",
		__path__    = "/var/log/*.log",
		host        = "${HOSTNAME}",
		job         = "system",
	}]
}

loki.source.file "system" {
	targets               = local.file_match.system.targets
	forward_to            = [loki.write.default.receiver]
}

// Systemd Journal
discovery.relabel "journal" {
	targets = []

	rule {
		source_labels = ["__journal__systemd_unit"]
		regex         = "^ceph-.*"
		target_label  = "job"
		replacement   = "ceph"
	}

	rule {
		source_labels = ["__journal__systemd_unit"]
		target_label  = "unit"
	}

	rule {
		source_labels = ["__journal__hostname"]
		target_label  = "hostname"
	}

	rule {
		source_labels = ["__journal_syslog_identifier"]
		target_label  = "syslog_identifier"
	}

	rule {
		source_labels = ["__journal_transport"]
		target_label  = "transport"
	}

	rule {
		source_labels = ["__journal_priority_keyword"]
		target_label  = "keyword"
	}
}

loki.source.journal "journal" {
	max_age       = "12h0m0s"
	path          = "/var/log/journal"
	relabel_rules = discovery.relabel.journal.rules
	forward_to    = [loki.write.default.receiver]
	labels        = {
		job = "systemd-journal",
	}
}

// K3s pods
discovery.kubernetes "pods" {
	role = "pod"
}

discovery.relabel "pods" {
	targets = discovery.kubernetes.pods.targets

	rule {
		source_labels = ["__meta_kubernetes_pod_node_name"]
		target_label  = "__host__"
	}

	rule {
		regex  = "__meta_kubernetes_pod_label_(.+)"
		action = "labelmap"
	}

	rule {
		source_labels = ["__meta_kubernetes_namespace"]
		target_label  = "job"
	}

	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"
	}

	rule {
		source_labels = ["__meta_kubernetes_pod_uid", "__meta_kubernetes_pod_container_name"]
		separator     = "/"
		target_label  = "__path__"
		replacement   = "/var/log/pods/*$1/*.log"
	}
}

local.file_match "pods" {
	path_targets = discovery.relabel.pods.output
}

loki.process "pods" {
	forward_to = [loki.write.default.receiver]

	stage.cri { }
}

loki.source.file "pods" {
	targets               = local.file_match.pods.targets
	forward_to            = [loki.process.pods.receiver]
}

// Loki Push
loki.write "default" {
	endpoint {
		url = "http://<LOKI_HOST>/loki/api/v1/push"
	}
	external_labels = {}
}

Compose

services:
    alloy:
        volumes:
            - <CONFIG_FILE_PATH>:/etc/alloy/config.alloy
        ports:
            - 12345:12345
        image: grafana/alloy:latest
        command: run --server.http.listen-addr=0.0.0.0:12345
            --storage.path=/var/lib/alloy/data /etc/alloy/config.alloy