本文档主要介绍使用函数进行事件判断的一些常见场景和最佳方案示例。

场景1:判断字段是否存在

  • 原始日志
    a: a_vlue
    b:    // 空串
  • LOG DSL编排
    • 方案一:使用e_hase_not_has
      e_if(e_has("a"), e_set("has_a", true))
      e_if(e_has("b"), e_set("has_b", true))
      e_if(e_has("c"), e_set("has_c", true))
      e_if(e_not_has("a"), e_set("not_has_a", true))
      e_if(e_not_has("b"), e_set("not_has_b", true))
      e_if(e_not_has("c"), e_set("not_has_c", true))
    • 方案二:使用e_search
      e_if(e_search('a: *'), e_set("has_a", true))
      e_if(e_search('b: *'), e_set("has_b", true))
      e_if(e_search('c: *'), e_set("has_c", true))
      e_if(e_search('not a: *'), e_set("not_has_a", true))
      e_if(e_search('not b: *'), e_set("not_has_b", true))
      e_if(e_search('not c: *'), e_set("not_has_c", true))
  • 加工结果
    a: a_vlue
    b:    // 空串
    has_a: true
    has_b: true
    has_c: false
    not_has_a: false
    not_has_b: false
    not_has_c: true
说明
  • 以上两种方案都可用于判断字段是否存在,但是方案一更直观、易理解。
  • 以上加工规则中的e_if可通过e_if(条件1,操作1,条件2,操作2)的形式合并为一个,此处拆分是为了易于读者阅读。

场景2:判断字段值是否存在且不为空

  • 原始日志
    a: a_vlue
    b:     // 空串
  • LOG DSL编排
    • 方案一:使用字段取值函数v
      e_if(v("a"), e_set("not_empty_a", true))
      e_if(v("b"), e_set("not_empty_b", true))
      e_if(v("c"), e_set("not_empty_c", true))
      字段取值函数v,当对应字段存在且值不为空时,其自动转换的Bool值为True,否则为False
    • 方案二:使用e_search
      # 至少一个字符
      e_if(e_search('a: "?"'), e_set("not_empty_a", true))
      e_if(e_search('b: "?"'), e_set("not_empty_b", true))
      e_if(e_search('c: "?"'), e_set("not_empty_c", true))
      
      # 正则
      e_if(e_search('a~=".+"'), e_set("not_empty_a", true))
      e_if(e_search('b~=".+"'), e_set("not_empty_b", true))
      e_if(e_search('c~=".+"'), e_set("not_empty_c", true))
      
      # 存在且不为空
      e_if(e_search('a: * and not a==""'), e_set("not_empty_a", true))
      e_if(e_search('b: * and not b==""'), e_set("not_empty_b", true))
      e_if(e_search('c: * and not c==""'), e_set("not_empty_b", true))
  • 加工结果
    a: a_vlue
    b:     // 空串
    not_empty_a: true
    not_empty_b: false
    not_empty_c: false
说明
  • 以上两种方案都可用于判断字段是否存在,但是方案一更直观、易理解。
  • 以上加工规则中的e_if可通过e_if(条件1,操作1,条件2,操作2)的形式合并为一个,此处拆分是为了易于读者阅读。

场景3:判断字段值是否存在且为空

  • 原始日志
    a: a_vlue
    b:   // 空串
  • LOG DSL编排
    • 方案一:使用字段取值函数v
      e_if(op_and(e_has("a"), op_not(v("a"))), e_set("empty_a", true))
      e_if(op_and(e_has("b"), op_not(v("b"))), e_set("empty_b", true))
      e_if(op_and(e_has("c"), op_not(v("c"))), e_set("empty_c", true))
      
      # 错误的方案
      e_if(op_not(v("a")), e_set("empty_a", true))
      e_if(op_not(v("b")), e_set("empty_b", true))
      e_if(op_not(v("c")), e_set("empty_c", true))
      字段取值函数v,当对应字段存在且值不为空时,其自动转换的Bool值为True,否则为False。但是值不存在时,其返回Noneop_not(None)时也是返回True
    • 方案二:使用e_search
      e_if(e_search('a==""'), e_set("empty_a", true))
      e_if(e_search('b==""'), e_set("empty_b", true))
      e_if(e_search('c==""'), e_set("empty_c", true))
      
      # 以下是错误调用
      e_if(e_search('a:""'), e_set("empty_a", true))
      e_if(e_search('b:""'), e_set("empty_b", true))
      说明 以上错误调用中,因为:e_search是部分查询,字段存在时,无论是否空串的情况下,空串a: ""一直为真。
  • 加工结果
    a: a_vlue
    b:    // 空串
    empty_a: false
    empty_b: true
    empty_b: false
说明
  • 以上两种方案都可用于判断字段是否存在,但是方案二更简洁。
  • 以上加工规则中的e_if可通过e_if(条件1,操作1,条件2,操作2)的形式合并为一个,此处拆分是为了易于读者阅读。

场景4:基于字段值的逻辑查询判断

原始日志
"日志1"
http_host:  m1.abcd.com
status:  200
request_method:  GET
scheme:  https
header_length: 700
body_length: 1200

"日志2"
http_host:  m2.abcd.com
status:  200
request_method:  POST
scheme:  https
header_length: 100
body_length: 800

"日志3"
http_host:  m3.abcd.com
status:  200
request_method:  GET
scheme:  http
header_length: 700
body_length: 800

"日志4"
http_host:  m4.abcd.com
status:  404
request_method:  GET
scheme:  https
header_length: 100
body_length: 300
  • 加工需求1
    为所有status字段值为200的日志事件,添加一个字段type,其值为normal
    • LOG DSL编排
      e_if(e_match("status", "200"), e_set("type", "normal))
      或者
      e_if(e_search('status==200'), e_set("type", "normal"))
      说明
      • 简单场景下,以上两种方式均可以,并无太大差别。
      • 一般情况下status: 200也可以,但status==200更精准一些。
    • 加工结果
      "日志1"
      type: normal
      http_host:  m1.abcd.com
      status:  200
      request_method:  GET
      scheme:  https
      header_length: 700
      body_length: 1200
      
      "日志2"
      type: normal
      http_host:  m2.abcd.com
      status:  200
      request_method:  POST
      scheme:  https
      header_length: 100
      body_length: 800
      
      "日志3"
      type: normal
      http_host:  m3.abcd.com
      status:  200
      request_method:  GET
      scheme:  http
      header_length: 700
      body_length: 800
      
      "日志4"
      http_host:  m4.abcd.com
      status:  404
      request_method:  GET
      scheme:  https
      header_length: 100
      body_length: 300
  • 加工需求2
    为所有status字段值为200并且request_method字段值为GET并且scheme字段值为https的日志事件,添加一个字段type,其值为normal
    • LOG DSL编排
      e_if(e_search('status==200 and request_method==GET and scheme==https'), e_set("type", "normal"))
      或者
      e_if(e_match_all("status", "200", "request_method","GET", "scheme", "https"), e_set("type", "normal"))
      说明
      • 此场景下,需要同时满足多个字段的匹配条件,可以使用e_searche_match_alle_search用法相对更简洁一些。
      • 一般情况下status: 200也可以,但status==200更精准一些。
    • 加工结果
      "日志1"
      type: normal
      http_host:  m1.abcd.com
      status:  200
      request_method:  GET
      scheme:  https
      header_length: 700
      body_length: 1200
      
      "日志2"
      http_host:  m2.abcd.com
      status:  200
      request_method:  POST
      scheme:  https
      header_length: 100
      body_length: 800
      
      "日志3"
      http_host:  m3.abcd.com
      status:  200
      request_method:  GET
      scheme:  http
      header_length: 700
      body_length: 800
      
      "日志4"
      http_host:  m4.abcd.com
      status:  404
      request_method:  GET
      scheme:  https
      header_length: 100
      body_length: 300
  • 加工需求3
    为所有status字段值为200或者request_method字段值为GET或者scheme字段值为https的日志事件,添加一个字段type,其值为normal
    • LOG DSL编排
      e_if(e_search('status==200 or request_method==GET or scheme==https'), e_set("type", "normal"))
      或者
      e_if(e_match_any("status", "200", "request_method","GET", "scheme", "https"), e_set("type", "normal"))
      说明 此场景下,需要同时满足多个字段的匹配条件,可以使用e_searche_match_alle_search用法相对更简洁一些。
    • 加工结果
      "日志1"
      type: normal
      http_host:  m1.abcd.com
      status:  200
      request_method:  GET
      scheme:  https
      header_length: 700
      body_length: 100
      
      "日志2"
      type: normal
      http_host:  m2.abcd.com
      status:  200
      request_method:  POST
      scheme:  https
      header_length: 100
      body_length: 800
      
      "日志3"
      type: normal
      http_host:  m3.abcd.com
      status:  200
      request_method:  GET
      scheme:  http
      header_length: 700
      body_length: 800
      
      "日志4"
      type: normal
      http_host:  m4.abcd.com
      status:  404
      request_method:  GET
      scheme:  https
      header_length: 100
      body_length: 1300
  • 加工需求4
    为所有status字段值为200并且request_method字段值为GET并且header_lengthbody_length的字段值之和小于等于1000的日志事件,添加一个字段type,其值为normal
    • LOG DSL编排
      e_if(op_and(e_search('status: 200 and request_method: GET'), op_le(op_sum(v("header_length"), v("body_length")), 1000)), e_set("type", "normal"))
      说明 在复杂的逻辑场景下,可通过e_search和其他表达式函数的组合来完成。
    • 加工结果
      "日志1"
      type: normal
      http_host:  m1.abcd.com
      status:  200
      request_method:  GET
      scheme:  https
      header_length: 700
      body_length: 100
      
      "日志2"
      http_host:  m2.abcd.com
      status:  200
      request_method:  POST
      scheme:  https
      header_length: 100
      body_length: 800
      
      "日志3"
      http_host:  m3.abcd.com
      status:  200
      request_method:  GET
      scheme:  http
      header_length: 700
      body_length: 800
      
      "日志4"
      http_host:  m4.abcd.com
      status:  404
      request_method:  GET
      scheme:  https
      header_length: 100
      body_length: 1300