背景介绍
什么是日志服务?
日志服务是针对日志类数据的一站式服,像Log、Metric这类数据我们可以提供大规模、低成本、实时的平台化服务。它的应用场景非常多,像一些监控、分析、诊断都可以通过日志服务去实现,无需开发就能快捷完成日志数据采集、消费、投递以及查询分析等功能,提升运维、运营效率,建立DT时代海量日志处理能力。
什么是数据加工?
数据加工是日志服务推出的一项功能,是面向日志进行实时的处理,实时性高且功能丰富。数据加工目前提供了两百多种DSL算子用作数据处理,我们可以在数据加工中根据需求做数据过滤、转换、复制、富化、分裂等操作。
场景介绍
- 在我们使用数据加工时,若需要根据某种规则将日志分发到不同的logstore中,实现方式有以下两种:
- 通过将转发规则写入到DSL中去实现
- 维护一张维表,根据映射关系来实现(推荐)
- 在此文章中将主要介绍基于维表的映射关系来实现日志分发至不同的logstore,比如我们要通过日志中不同的code值,将日志分发至维表所对应的logstore中,如下图所示
场景示例
根据日志中code值和维表映射将日志分发至不同的logstore
- 准备一张维表,在这个示例中我们将拉取oss的csv文件
- csv格式:
code,logstore
2xx,logstore_2xx
3xx,logstore_3xx
4xx,logstore_4xx
5xx,logstore_5xx
- 原始日志:
host:www.xxx.mock.com
http_referer:www.xxx.mock.com
remote_user:2hdtk
request_method:GET
request_uri:/request/path-3/file-5
code:200
host:www.xxx.mock.com
http_referer:www.xxx.mock.com
remote_user:2hdtk
request_method:GET
request_uri:/request/path-3/file-5
code:301
host:www.xxx.mock.com
http_referer:www.xxx.mock.com
remote_user:2hdtk
request_method:GET
request_uri:/request/path-3/file-5
code:403
host:www.xxx.mock.com
http_referer:www.xxx.mock.com
remote_user:2hdtk
request_method:Get
request_uri:/request/path-3/file-5
code:500
- 加工目标:
- 将code值为2xx的日志分发到logstore_2xx中
- 将code值为3xx的日志分发到logstore_3xx中
- 将code值为4xx的日志分发到logstore_4xx中
- 将code值为5xx的日志分发到logstore_5xx中
- 实现DSL(基于维表映射):
#创建一个临时字段code_map 去和维表做映射 code:200->code_map:2xx
e_set("code_map", str_join("",op_slice(v("code"),1), "xx"))
#通过res_oss_file拉取csv文本,tav_parse_csv将文本转换为维表,再通过e_table_map映射富化出目标logstore
#res_oss_file设置change_detect_interval,更新时会自动拉取,拉取间隔单位为s
e_table_map(
tab_parse_csv(
res_oss_file(
"oss-cn-hangzhou.aliyuncs.com",
"ak_id",
"ak_key",
"log-etl-staging",
"code.csv",
format="text",change_detect_interval=1000)),[("code_map","code")],"logstore")
#删除临时字段
e_drop_fields("code_map")
#输出日志
e_output(project="etl-test-zhy", logstore=v("logstore"))
为什么推荐使用维表映射而不是DSL内编写转发规则?
- 基于DSL编写转发规则的实现:
#通过e_match正则匹配code值,分发至不同的logstore
e_switch(e_match("code", "2\d+"), e_output(project="etl-test-zhy", logstore="logstore_2xx"),
e_match("code", "3\d+"), e_output(project="etl-test-zhy", logstore="logstore_3xx"),
e_match("code", "4\d+"), e_output(project="etl-test-zhy", logstore="logstore_4xx"),
e_match("code", "5\d+"), e_output(project="etl-test-zhy", logstore="logstore_5xx"))
- 两种方案对比:
操作步骤
- 选择需要加工的logstore, 进入数据加工页面
- 编写DSL,在正确填写res_oss_file函数相关配置后可以通过高级预览查看加工结果
- 预览加工结果
- 保存加工任务,此处可以配置存储目标和加工范围等信息。
注:我们已经在e_output()函数中配置了输出的project和logstore,此处不需要再配置存储目标,但如果日志中存在无法匹配的日志,需要配置默认存储目标。如果配置的目标Project、Logstore不存在,您可以在此页面中将高级参数配置中的key设置为config.sls_output.failure_strategy,value设置为{"drop_when_not_exists":"true"} 来跳过该日志,被跳过的日志会被丢弃,并且上报为warning级别的日志。如果不设置高级参数配置,数据加工任务将一直等待目标Project、Logstore被创建后再执行加工任务
如何将同一条日志分发到多个logstore中?
- 我们可以这样维护一张维表,通过"#"来分割多个logstore
通过"#"来分割多个logstore
code,logstore
2xx,logstore_2xx#logstore_2#logstore_3
3xx,logstore_3xx#logstore_3
4xx,logstore_4xx#logstore_4#logstore5
5xx,logstore_5xx#logstore_5
- 实现DSL:
这里由于目标logstore数量不固定,所以我们用到e_split通过"#"来分裂日志,同一条日志被分裂的个数由logstore的数量决定。
#创建一个临时字段code_map 去和维表做映射 code:200->code_map:2xx
e_set("code_map", str_join("",op_slice(v("code"),1), "xx"))
#通过res_oss_file拉取csv文本,tav_parse_csv将文本转换为维表,再通过e_table_map映射富化出目标logstore
e_table_map(
tab_parse_csv(
res_oss_file(
"oss-cn-hangzhou.aliyuncs.com",
"ak_id",
"ak_key",
"log-etl-staging",
"code.csv",
format="text",change_detect_interval=1000)),[("code_map","code")],"logstore")
#删除临时字段
e_drop_fields("code_map")
#根据logstore分裂事件
e_split("logstore", sep='#')
#输出日志
e_output(project="etl-test-zhy", logstore=v("logstore"))