优化日志警报查询

本文介绍如何编写和转换日志警报查询,以获得最佳性能。 经过优化的查询可降低延迟并加载频繁运行的警报。

如何开始编写警报日志查询

警报查询开始于查询 Log Analytics 中指示问题的日志数据。 可以使用警报查询示例主题来了解可发现的内容。 还可以开始编写你自己的查询

指示问题而非警报的查询

生成警报流是为了将指示问题的结果转换为警报。 例如,在如下查询中:

SecurityEvent
| where EventID == 4624

如果用户的意图是发出警报,那么当这个事件类型发生时,警报逻辑会将 count 追加到查询中。 要运行的查询将如下所示:

SecurityEvent
| where EventID == 4624
| count

无需向查询添加警报逻辑,这样做甚至可能导致问题。 在上面的示例中,如果你在查询中包括 count,它将始终得到值 1,因为警报服务将执行 countcount

避免使用 limittake 运算符

在查询中使用 limittake 可能会增加警报的延迟和负载,因为结果会随着时间的推移而产生不一致。 最好仅在必要时才使用它。

日志查询约束

Azure Monitor 中的日志查询以 table、searchunion 运算符开头。

对日志预警规则的查询应始终以表开始,以定义明确的范围,从而提高查询性能和结果的相关性。 预警规则中的查询经常运行,因此使用 searchunion 会造成额外开销,并增加警报的延迟,因为它需要扫描多个表。 这些运算符还会降低警报服务优化查询的性能。

除了跨资源查询,我们不支持创建或修改使用 searchunion 运算符的日志警报规则。

例如,以下警报查询的范围限定为 SecurityEvent 表,并搜索特定的事件 ID。 这是查询必须处理的唯一的表。

SecurityEvent
| where EventID == 4624

使用跨资源查询的日志预警规则不受此更改的影响,因为跨资源查询使用 union 类型,这会将查询范围限制为特定资源。 以下示例将是有效的日志警报查询:

union
app('Contoso-app1').requests,
app('Contoso-app2').requests,
workspace('Contoso-workspace1').Perf 

备注

新的 scheduledQueryRules API 支持跨资源查询

示例

以下示例包括使用 searchunion 的日志查询,并提供可用于修改这些查询以与预警规则配合使用的步骤。

示例 1

想要使用以下查询创建日志预警规则,该查询使用 search 检索性能信息:

search *
| where Type == 'Perf' and CounterName == '% Free Space'
| where CounterValue < 30

若要修改此查询,请首先使用以下查询来标识属性所属的表:

search *
| where CounterName == '% Free Space'
| summarize by $table

此查询结果将显示 CounterName 属性来自 Perf 表 。

可使用此结果创建以下查询,可将该查询用于预警规则:

Perf
| where CounterName == '% Free Space'
| where CounterValue < 30

示例 2

想要使用以下查询创建日志预警规则,该查询使用 search 检索性能信息:

search ObjectName =="Memory" and CounterName=="% Committed Bytes In Use"
| summarize Avg_Memory_Usage =avg(CounterValue) by Computer
| where Avg_Memory_Usage between(90 .. 95)  

若要修改此查询,请首先使用以下查询来标识属性所属的表:

search ObjectName=="Memory" and CounterName=="% Committed Bytes In Use"
| summarize by $table

此查询结果将显示 ObjectName 和 CounterName 属性来自 Perf 表 。

可使用此结果创建以下查询,可将该查询用于预警规则:

Perf
| where ObjectName =="Memory" and CounterName=="% Committed Bytes In Use"
| summarize Avg_Memory_Usage=avg(CounterValue) by Computer
| where Avg_Memory_Usage between(90 .. 95)

示例 3

想要使用以下查询创建日志预警规则,该查询使用 searchunion 检索性能信息:

search (ObjectName == "Processor" and CounterName == "% Idle Time" and InstanceName == "_Total")
| where Computer !in (
    union *
    | where CounterName == "% Processor Utility"
    | summarize by Computer)
| summarize Avg_Idle_Time = avg(CounterValue) by Computer

若要修改此查询,请首先使用以下查询来标识查询第一部分中属性所属的表:

search (ObjectName == "Processor" and CounterName == "% Idle Time" and InstanceName == "_Total")
| summarize by $table

此查询结果将显示所有这些属性来自 Perf 表。

现在,将 unionwithsource 命令配合使用,确定哪个源表提供了每行。

union withsource=table *
| where CounterName == "% Processor Utility"
| summarize by table

此查询结果将显示这些属性也来自 Perf 表。

可使用这些结果创建以下查询,可将该查询用于预警规则:

Perf
| where ObjectName == "Processor" and CounterName == "% Idle Time" and InstanceName == "_Total"
| where Computer !in (
    (Perf
    | where CounterName == "% Processor Utility"
    | summarize by Computer))
| summarize Avg_Idle_Time = avg(CounterValue) by Computer

示例 4

想要使用以下查询创建日志预警规则,该查询联接两条 search 查询的结果:

search Type == 'SecurityEvent' and EventID == '4625'
| summarize by Computer, Hour = bin(TimeGenerated, 1h)
| join kind = leftouter (
    search in (Heartbeat) OSType == 'Windows'
    | summarize arg_max(TimeGenerated, Computer) by Computer , Hour = bin(TimeGenerated, 1h)
    | project Hour , Computer
) on Hour

若要修改此查询,请首先使用以下查询来标识包含左侧联接中属性的表:

search Type == 'SecurityEvent' and EventID == '4625'
| summarize by $table

结果指示左侧联接中的属性属于 SecurityEvent 表。

现在使用以下查询来标识包含右侧联接中属性的表:

search in (Heartbeat) OSType == 'Windows'
| summarize by $table

结果指示右侧联接中的属性属于 Heartbeat 表。

可使用这些结果创建以下查询,可将该查询用于预警规则:

SecurityEvent
| where EventID == '4625'
| summarize by Computer, Hour = bin(TimeGenerated, 1h)
| join kind = leftouter (
    Heartbeat
    | where OSType == 'Windows'
    | summarize arg_max(TimeGenerated, Computer) by Computer , Hour = bin(TimeGenerated, 1h)
    | project Hour , Computer
) on Hour

后续步骤