场景1:判断字段是否存在
原始日志
a: a_vlue
b: // 空串
LOG DSL编排
方案一:使用e_has, e_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)的形式合并为一个e_if
,此处为了易于读者阅读,拆成两个。
场景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)的形式合并为一个e_if
,此处为了易于读者阅读,拆成两个。
场景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. 但是只不存在是, 其返回None
,op_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)的形式合并为一个e_if
,此处为了易于读者阅读,拆成两个。
场景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
也可以, 只是==
更精准一些.
加工后的日志
"日志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_search
或e_match_all
。 -
e_search
用法相对更简洁一些。 - 一般情况下
e_search
的==
也可以换成:
如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_search
或e_match_any
。 -
e_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_length
和body_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
进一步参考
欢迎扫码加入官方钉钉群获得实时更新与阿里云工程师的及时直接的支持: