优化日志搜索警报查询

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

开始编写日志搜索警报查询

警报查询开始于查询 Log Analytics 中指示问题的日志数据。 若要了解可以发现的内容,请参阅在 Azure Monitor Log Analytics 中使用查询。 还可以开始编写你自己的查询。

确保查询可标识问题,而不是警报本身

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

SecurityEvent
| where EventID == 4624

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

SecurityEvent
| where EventID == 4624
| count

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

避免限制并采用运算符

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

日志查询约束

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

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

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

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

SecurityEvent
| where EventID == 4624

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

union
app('00000000-0000-0000-0000-000000000001').requests,
app('00000000-0000-0000-0000-000000000002').requests,
workspace('00000000-0000-0000-0000-000000000003').Perf 

注意

新的 scheduledQueryRules API 支持跨资源查询。

示例

以下示例包括使用 search 和 union 的日志查询。 它们提供了步骤,可用于修改这些查询以在警报规则中使用。

示例 1

你希望通过使用以下查询来创建一个日志搜索预警规则,该查询使用 search 检索性能信息:

search *
| where Type == 'Perf' and CounterName == '% Free Space'
| where CounterValue < 30
  1. 若要修改此查询,请首先使用以下查询来标识属性所属的表:

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

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

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

    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)  
  1. 若要修改此查询,请首先使用以下查询来标识属性所属的表:

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

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

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

    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

你希望通过使用以下查询来创建一个日志搜索预警规则,该查询同时使用 search 和 union 来检索性能信息:

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
  1. 若要修改此查询,请首先使用以下查询来标识查询第一部分中属性所属的表:

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

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

  2. 将 union 与 withsource 命令配合使用,确定哪个源表提供了每行:

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

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

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

    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
  1. 若要修改此查询,请首先使用以下查询来标识包含左侧联接中属性的表:

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

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

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

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

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

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

    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
    

后续步骤