基于规则的错误日志过滤(log filter dragnet)

来自泡泡学习笔记
跳到导航 跳到搜索

log_filter_dragnet日志过滤器组件可以根据用户定义的规则进行日志过滤。


要启用log_filter_dragnet过滤器,首先加载过滤器组件,然后修改log_error_services的值。以下示例将log_filter_dragnet与内置的日志输出一起启用:

INSTALL COMPONENT 'file://component_log_filter_dragnet';
SET GLOBAL log_error_services = 'log_filter_dragnet; log_sink_internal';


启用log_filter_dragnet后,通过设置dragnet.log_error_filter_rules系统变量来定义其过滤规则。规则集由零个或多个规则组成,每个规则都是以句点(.)结尾的IF语句。如果变量值为空(零个规则),则不进行过滤。


  • 示例1:这个规则集删除信息事件,并且对于其他事件,删除source_line字段:
SET GLOBAL dragnet.log_error_filter_rules =
  'IF prio>=INFORMATION THEN drop. IF EXISTS source_line THEN unset source_line.';

效果类似于log_error_verbosity=2的log_sink_internal过滤器执行的过滤。


为了可读性,您可能更喜欢将规则列在单独的行上。例如:

SET GLOBAL dragnet.log_error_filter_rules = '
  IF prio>=INFORMATION THEN drop.
  IF EXISTS source_line THEN unset source_line.
';


  • 示例2:这个规则将信息事件限制为每60秒不超过一次:
SET GLOBAL dragnet.log_error_filter_rules =
  'IF prio>=INFORMATION THEN throttle 1/60.';

一旦您设置了所需的过滤配置,请考虑使用SET PERSIST而不是SET GLOBAL来分配dragnet.log_error_filter_rules,以使设置在服务器重启后仍然有效。或者,将该设置添加到服务器选项文件中。


要停止使用过滤语言,首先从错误日志组件集中删除它。通常,这意味着使用不同的过滤器组件而不是没有过滤器组件。例如:

SET GLOBAL log_error_services = 'log_filter_internal; log_sink_internal';


再次强烈建议使用SET PERSIST而不是SET GLOBAL,以使设置在服务器重启后仍然有效。


然后卸载过滤器log_filter_dragnet组件:

UNINSTALL COMPONENT 'file://component_log_filter_dragnet';


log_filter_dragnet规则语言的语法

以下语法定义了log_filter_dragnet过滤规则的语言。每个规则都是以句点(.)结尾的IF语句。该语言不区分大小写。


rule:
    IF condition THEN action
    [ELSEIF condition THEN action] ...
    [ELSE action]
    .

condition: {
    field comparator value
  | [NOT] EXISTS field
  | condition {AND | OR}  condition
}

action: {
    drop
  | throttle {count | count / window_size}
  | set field [:= | =] value
  | unset [field]
}

field: {
    core_field
  | optional_field
  | user_defined_field
}

core_field: {
    time
  | msg
  | prio
  | err_code
  | err_symbol
  | SQL_state
  | subsystem
}

optional_field: {
    OS_errno
  | OS_errmsg
  | label
  | user
  | host
  | thread
  | query_id
  | source_file
  | source_line
  | function
  | component
}

user_defined_field:
    sequence of characters in [a-zA-Z0-9_] class

comparator: {== | != | <> | >= | => | <= | =< | < | >}

value: {
    string_literal
  | integer_literal
  | float_literal
  | error_symbol
  | priority
}

count: integer_literal
window_size: integer_literal

string_literal:
    sequence of characters quoted as '...' or "..."

integer_literal:
    sequence of characters in [0-9] class

float_literal:
    integer_literal[.integer_literal]

error_symbol:
    valid MySQL error symbol such as ER_ACCESS_DENIED_ERROR or ER_STARTUP

priority: {
    ERROR
  | WARNING
  | INFORMATION
}


简单条件比较一个字段与一个值,或者测试字段的存在性。为了构建更复杂的条件,可以使用AND和OR运算符。这两个运算符具有相同的优先级,并且从左到右进行评估。


在字符串中转义字符时,请在其前面加上反斜杠(\)。反斜杠是必需的,用于包含反斜杠本身或字符串引用字符,其他字符可选。


为了方便起见,log_filter_dragnet支持对某些字段进行比较的符号名称。为了可读性和可移植性,在适用的情况下,符号值优于数值。


事件优先级值1、2和3可以分别指定为ERROR、WARNING和INFORMATION。优先级符号只在与prio字段的比较中识别。以下比较是等效的:

IF prio == INFORMATION THEN ...
IF prio == 3 THEN ...


错误代码可以以数字形式或相应的错误符号形式指定。例如,ER_STARTUP是错误代码1408的符号名称,所以以下比较是等效的:

IF err_code == ER_STARTUP THEN ...
IF err_code == 1408 THEN ...


错误符号只在与err_code字段和用户定义的字段的比较中识别。


要找到与给定错误代码对应的错误符号,请使用以下方法之一:

  • 查看服务器错误列表,参考服务器错误消息参考。
  • 使用perror命令。给定一个错误编号参数,perror会显示有关该错误的信息,包括其符号。


假设一个带有错误编号的规则集如下:

IF err_code == 10927 OR err_code == 10914 THEN drop.
IF err_code == 1131 THEN drop.


使用perror,确定错误符号:

$> perror 10927 10914 1131
MySQL error code MY-010927 (ER_ACCESS_DENIED_FOR_USER_ACCOUNT_LOCKED):
Access denied for user '%-.48s'@'%-.64s'. Account is locked.
MySQL error code MY-010914 (ER_ABORTING_USER_CONNECTION):
Aborted connection %u to db: '%-.192s' user: '%-.48s' host:
'%-.64s' (%-.64s).
MySQL error code MY-001131 (ER_PASSWORD_ANONYMOUS_USER):
You are using MySQL as an anonymous user and anonymous users
are not allowed to change passwords


将错误符号替换为数字后,规则集变为:

IF err_code == ER_ACCESS_DENIED_FOR_USER_ACCOUNT_LOCKED
  OR err_code == ER_ABORTING_USER_CONNECTION THEN drop.
IF err_code == ER_PASSWORD_ANONYMOUS_USER THEN drop.


可以将符号名称指定为带引号的字符串,用于与字符串字段进行比较,但在这种情况下,这些名称是没有特殊含义的字符串,log_filter_dragnet不会将它们解析为相应的数值。此外,拼写错误可能不会被发现,而尝试使用服务器未知的未引用符号时,立即发生错误。


log_filter_dragnet规则中支持以下操作:

  • drop:丢弃当前的日志事件(不记录)。


  • throttle:对匹配特定条件的事件应用速率限制,以减少日志的冗长程度。参数指定一个速率,形式为count或count/window_size。count值表示每个时间窗口内允许记录的事件发生次数。window_size值是时间窗口的秒数;如果省略,则默认窗口为60秒。两个值都必须是整数字面量。

以下规则将plugin-shutdown消息限制为每60秒出现5次:

IF err_code == ER_PLUGIN_SHUTTING_DOWN_PLUGIN THEN throttle 5.

以下规则将错误和警告限制为每小时1000次,将信息消息限制为每小时100次:

IF prio <= INFORMATION THEN throttle 1000/3600 ELSE throttle 100/3600.


  • set:给字段赋值(如果字段不存在,则创建该字段)。在后续的规则中,对字段名称的EXISTS测试为真,并且可以通过比较条件来测试新值。


  • unset:丢弃一个字段。在后续的规则中,对字段名称的EXISTS测试为假,并且对字段与任何值的比较都为假。


在条件引用恰好引用一个字段名的特殊情况下,unset后面的字段名是可选的,unset会丢弃指定的字段。以下规则是等效的:

IF myfield == 2 THEN unset myfield.
IF myfield == 2 THEN unset.


log_filter_dragnet规则中的字段引用

log_filter_dragnet规则支持对错误事件中的核心字段、可选字段和用户定义字段进行引用。


核心字段引用

在log_filter_dragnet规则语言的语法中,列出了过滤规则所识别的核心字段。以下备注仅提供特定于在log_filter_dragnet规则中使用的核心字段引用的附加信息。

  • prio

事件的优先级,用于指示错误、警告或注释/信息事件。在比较中,每个优先级可以指定为符号优先级名称或整数字面值。优先级符号只在与prio字段的比较中识别。以下比较是等效的:

IF prio == INFORMATION THEN ...
IF prio == 3 THEN ...


以下表格显示了允许的优先级级别。

事件类型 优先级符号 数值优先级
错误事件 ERROR 1
警告事件 WARNING 2
注释/信息事件 INFORMATION 3


还有一个系统消息的优先级为SYSTEM,但系统消息无法进行过滤,而是始终写入错误日志。


优先级值遵循较高优先级具有较低值的原则,反之亦然。优先级值从最严重的事件(错误)开始,对于优先级递减的事件而言,值逐渐增加。例如,要丢弃优先级低于警告的事件,请测试高于WARNING的优先级值:

IF prio > WARNING THEN drop.

以下示例显示了实现与log_filter_internal过滤器允许的每个log_error_verbosity值类似效果的log_filter_dragnet规则:

  • 仅错误(log_error_verbosity=1):
IF prio > ERROR THEN drop.


  • 错误和警告(log_error_verbosity=2):
IF prio > WARNING THEN drop.


  • 错误、警告和注释(log_error_verbosity=3):
IF prio > INFORMATION THEN drop.

实际上可以省略此规则,因为没有大于INFORMATION的prio值,所以它实际上不丢弃任何事件。


  • err_code

事件的数字错误代码。在比较中,要测试的值可以指定为符号错误名称或整数字面值。错误符号只在与err_code字段和用户定义字段的比较中识别。以下比较是等效的:

IF err_code == ER_ACCESS_DENIED_ERROR THEN ...
IF err_code == 1045 THEN ...


  • err_symbol

事件的错误符号,作为字符串(例如,'ER_DUP_KEY')。err_symbol值更适用于识别日志输出中的特定行,而不适用于过滤规则的比较,因为log_filter_dragnet不会将指定为字符串的比较值解析为等效的数字错误代码。(要发生这种情况,必须使用未引用的符号来指定错误。)


可选字段引用

在log_filter_dragnet规则语言的语法中,列出了过滤规则所识别的可选字段。以下备注仅提供特定于在log_filter_dragnet规则中使用的可选字段引用的附加信息。


  • label

与优先级值对应的标签,作为字符串。过滤规则可以更改支持自定义标签的日志输出的标签。标签值更适用于识别日志输出中的特定行,而不适用于过滤规则的比较,因为log_filter_dragnet不会将指定为字符串的比较值解析为等效的数值优先级。


  • source_file

事件发生的源文件,不包含任何前导路径。例如,要测试sql/gis/distance.cc文件,可以编写如下比较:

IF source_file == "distance.cc" THEN ...


用户定义字段引用

在log_filter_dragnet过滤规则中,任何未被识别为核心字段或可选字段名的字段名都被认为是对用户定义字段的引用。