// Receives syslog from routers, switches, and Yealink phones on this host's // LAN interface, tags each message with useful labels, and ships it to the // local Loki instance. // // Point network devices at this host's IP, port 514/udp (or 1514/tcp for // devices that only speak TCP framing). loki.relabel "syslog" { forward_to = [] rule { source_labels = ["__syslog_message_hostname"] target_label = "hostname" } rule { source_labels = ["__syslog_message_severity"] target_label = "severity" } rule { source_labels = ["__syslog_message_facility"] target_label = "facility" } rule { source_labels = ["__syslog_connection_ip_address"] target_label = "source_ip" } } // syslog_format is "rfc3164" (legacy BSD syslog, no version field) rather // than the component's rfc5424 default — confirmed by packet capture that // both the Yealink phones and RouterOS routers send rfc3164 in practice. // A listener can only parse one format; if a device ever sends genuine // rfc5424, it needs its own listener on a different port. // Lifts the Yealink device MAC out of the message body into a real `mac` label. // // Why this is needed: UDP syslog gives us only three possible identities — the // sender IP, the RFC3164 HOSTNAME field, and the message body. // * source_ip is DHCP (observed lease time: 1200s), so it is NOT stable. A // phone that re-IPs becomes a "new device", and one that inherits a // recycled IP silently inherits another phone's history. // * HOSTNAME is useless here: Yealink puts its internal *subsystem* there // (sua, GUI, cfg, sys...). After enabling prepend-MAC the bracketed MAC // occupies that slot and is rejected as a hostname, so the label is simply // absent on new lines. // So the body is the only place the device identity exists. Yealink's // `static.syslog.prepend_mac_address.enable` puts it at the head of every line: // [80:5e:0c:b2:44:d3] sua [824.1146]: FSM <6+info > [255] free nist ressource // // Non-Yealink senders (e.g. the D-Link switches) don't match the regex and are // passed through untouched with no `mac` label — that is intentional. // // Cardinality is safe: mac is 1:1 with a device, so it does not multiply // against source_ip (~100 phones -> ~100 values, and the pair is stable). loki.process "extract_mac" { forward_to = [loki.write.default.receiver] stage.regex { expression = "^\\[(?P(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})\\]" } stage.labels { values = { mac = "mac", } } } loki.source.syslog "network_devices_udp" { listener { address = "0.0.0.0:514" protocol = "udp" syslog_format = "rfc3164" labels = { job = "syslog", transport = "udp", } } relabel_rules = loki.relabel.syslog.rules forward_to = [loki.process.extract_mac.receiver] } loki.source.syslog "network_devices_tcp" { listener { address = "0.0.0.0:1514" protocol = "tcp" syslog_format = "rfc3164" labels = { job = "syslog", transport = "tcp", } } relabel_rules = loki.relabel.syslog.rules forward_to = [loki.process.extract_mac.receiver] } loki.write "default" { endpoint { url = "http://loki:3100/loki/api/v1/push" } }