优化日志搜索警报查询

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

开始编写警报日志查询

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

指示问题而非警报的查询

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

SecurityEvent
| where EventID == 4624

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

SecurityEvent
| where EventID == 4624
| count

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

避免限制并采用运算符

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

日志查询约束

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

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

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

例如,以下警报查询的范围限定为 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 支持跨资源查询

示例

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

示例 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

你希望通过使用以下查询来创建一个日志搜索预警规则,该查询同时使用 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
  1. 若要修改此查询,请首先使用以下查询来标识查询第一部分中属性所属的表:

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

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

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

    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
    

后续步骤