Facility与Severity:设施代码和严重级别的定义与使用场景

说实话,学Syslog如果不搞懂Facility和Severity,那基本就是白学了。这两个字段是整个Syslog协议的灵魂,就像快递单上的“发件人地址”和“包裹破损程度”。它们决定了这条日志从哪里来,以及它有多紧急。

我刚开始接手公司日志系统时,碰到过一种情况——设备疯狂往外吐日志,但接收端全都丢掉了。排查了半天,最后发现是Facility代码没配对,导致过滤规则全盘错乱。嗯,从那以后我明白了:这两个数字,每一个都值得认真对待。

Facility:消息到底是谁发出的

Facility,中文叫“设施代码”。它告诉接收端:这条日志是由系统的哪个模块或哪类设备生成的。它不是IP地址,也不是主机名,而是一个0到23之间的数字(历史原因,后来又扩展了几个)。

为什么要有这个?你想想看,一个网络设备上跑着操作系统、路由协议、邮件服务、打印服务……所有日志混在一起,你根本分不清哪条是路由协议告警,哪条是邮件发送失败。Facility就是用来做这个区分的。

Facility代码 关键字 说明
0kern内核消息
1user用户级消息
2mail邮件系统
3daemon系统守护进程
4auth安全/认证消息
5syslogSyslog内部产生的消息
6lpr打印子系统
7news网络新闻组
8uucpUUCP子系统
9cron定时任务守护进程
10authpriv安全/认证消息(私密)
11ftpFTP守护进程
16-23local0 - local7保留给本地使用
重要:Facility 12到15在RFC 3164中是未定义的。但后来RFC 5424做了调整,增加了一些。不过在真实的网络设备上,最常用的还是0-11和16-23。

这里我特别想提一下local0到local7。我在项目中遇到过不少次,很多厂商的设备日志并不严格遵循标准Facility。比如思科的某些交换机,会把端口安全日志打到local4上。你如果不提前确认设备文档,直接按标准FAC_DAEMON去过滤,那大概率会漏掉关键事件。

我个人习惯的做法是:先抓一批原始Syslog报文,看看Facility字段实际填的是什么值,然后再去配置解析规则。记住,不要做任何假设。设备厂商有时候真的不按套路出牌。

Severity:这条消息有多严重

Severity,严重级别。它用一个0到7的数字表示消息的紧急程度。0最严重,7最不严重。在Syslog报文里,Severity和Facility其实是被编码在同一个字节里的——这叫Priority(优先级),后面我会详细讲计算方式。

Severity代码 关键字 说明
0emerg紧急,系统不可用
1alert必须立即采取措施
2crit临界状态
3err错误
4warning警告
5notice正常但重要的消息
6info信息性消息
7debug调试级别
策略建议:在我管理的日志系统里,Severity 0-3会直接触发实时告警推送到手机;Severity 4-6走工单系统当天处理;Severity 7一般不存或者只保留短期。但注意,debug日志量极大,存久了会把磁盘撑爆。

那么在实际生产中,这玩意到底怎么用?我举几个场景:

  • 你收到了Facility=kern, Severity=err的消息,基本上是内核报错了。这时候你应该立刻查看dmesg和硬件状态。
  • Facility=local4, Severity=warning。这可能是你自定义的应用告警,比如磁盘使用率超过80%。
  • Facility=mail, Severity=info。那就是邮件队列正常运行的日志,一般不需要关注。

我曾经见过一个运维新手,把所有Facility和Severity的日志全收进同一个队列不做分级,结果因为debug日志量太大,导致紧急告警被延迟了整整40分钟。嗯,这件事直接催生了我们团队的日志分级规范。

Priority值的计算与报文结构

Syslog报文里不直接存Facility和Severity这两个独立的字段,而是把它们合并成一个数字:Priority = Facility × 8 + Severity。这个Priority占据报文中的第一个字节。接收端收到后,通过取模运算就能还原出Facility和Severity。

举个例子:如果Priority的值是134。

Facility = 134 ÷ 8 = 16(local0)
Severity = 134 % 8 = 6(info)

那你这条日志就是来自本地应用的一条普通信息,不需要紧张。

RFC 5424中的Priority取值范围是0到191。其中Facility最大是23,Severity最大是7,算一下:23×8+7=191,刚好覆盖。

还有一点,Level(级别)这个词有时候会和Severity混用。在一些非Syslog协议但兼容其格式的场景里,比如某些审计软件,它们会用Level这个说法。技术上说是一样的,但学术上更准确的叫法是Severity。我这边的习惯是统一叫Severity,避免与日志内容的“级别”混淆。

面面俱到的Facility与Severity矩阵

当你开始设计日志接收端策略时,最重要的一个思维模型就是“Facility × Severity矩阵”。说白了,就是先看谁发的,再看严不严重,然后决定怎么处理。

Facility × Severity 筛选决策模型 Facility 来源分组 系统内核 (0) 守护进程 (3, 6, 7) 安全认证 (4, 10) 应用自定义 (16-23) ↓ 决定日志来源 Severity 严重级别 EMERG (0) — 立即告警 ALERT/CRIT (1-2) — 紧急 ERR/WARN (3-4) — 处理 INFO/DEBUG (6-7) — 归档 ↓ 决定处理动作 接收端执行动作 实时告警推送 工单自动创建 分层存储策略 安全审计标识 ↑ 根据权重执行 理解重点 • Facility 决定日志来源,Severity 决定处理优先级,两者交叉形成过滤策略。 • 比如:local0.err 应该告警,而 kern.info 可以忽略或归档。 • 同一类Facility的不同Severity可以走不同处理管道。 • 注意:不要把debug级别和emerg级别混在一起处理,后果很可怕。

实践中的Facility分配案例

说个我真实的项目配置。当时我们在为一个大型数据中心搭建统一的日志接收平台。网络设备的Facility分配是这样的:

网络设备Facility分配表(实际部署案例):
----------------------------------------
核心路由器     →  local0   (Facility 16)
汇聚交换机     →  local1   (Facility 17)
防火墙         →  local2   (Facility 18)
负载均衡器     →  local3   (Facility 19)
数据库服务器   →  local4   (Facility 20)
应用服务器     →  local5   (Facility 21)
所有设备       →  Severity 0-3 直接进入实时告警通道

为什么要这么分配?因为不同团队看不同的设备。网络团队只看local0和local1,安全团队只看local2和local3。Facility划清了管理边界,谁的问题找谁,清晰明了。

警告:不要把不同来源的设备配置成同一个Facility+Severity组合!比如核心路由器和打印机都用local0.err,那你根本分不清到底是网络断了还是打印机卡纸了。我见过有人这么干过,后来排查问题时差点疯了——所有日志都混在一起,只能一条一条去看主机名。记住了,Facility是物理来源的第一级标签,不要浪费这个字段。

避坑指南

最后总结几个我踩过的坑,你遇到了可以直接绕开:

  • 不要直接依赖设备默认配置。很多设备的出厂配置里Facility是瞎填的。我遇到过一个型号的防火墙,所有日志不管什么模块都发到kern上去。拿到了先抓包确认。
  • Facility的local0到local7不是标准定义。不同厂商使用方式不同。跨厂商环境必须做映射表。
  • Severity不要只看数值。有些系统会把Debug写成“级别7”,但实际用途却是Info。还是要看真实报文。
  • 优先级计算别写错。我见过有同事把公式写成了Facility + Severity×8,结果Priority全乱套了。记住:Facility×8 + Severity,加号两端不要搞反。

Facility和Severity这两个字段,看起来简单,但用好了就是整个日志体系的骨架。我个人的经验是:花30分钟把这套规则定清楚,后续的运维会省下你几百个小时的排查时间。框架对了,细节才不会崩。