数据加工服务简介
数据加工服务是阿里云日志服务推出的面向日志ETL处理的服务,主要解决数据加工过程中转换、过滤、分发、富化等场景。
数据加工服务集成在日志服务里。
数据加工支持的常见场景:
数据分发场景
- 数据规整(一对一)
- 数据分派(一对多)
接下来,我们以nginx日志解析为例,抛砖引玉,帮助大家快速入门阿里云日志服务的数据加工。
用于解析的Nginx日志
假设我们通过极简模式采集了Nginx默认日志。默认的nginx 日志format如下
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
机器上看到日志是这样的
使用阿里云日志服务采集极简日志如下
控制台启用数据加工
控制台打开“数据加工”按钮,然后在输入框里输入DSL语句,点击预览数据即可看到数据加工的效果。
字段正则抽取
通过正则,抽取nginx日志里的字段,这里可以用到正则的捕获组名称设置变量名称
e_regex("源字段名", "正则或有命名捕获正则", "目标字段名或数组(可选)", mode="fill-auto")
推荐一个正则编写辅助工具: https://regex101.com/
实际使用DSL语句
e_regex("content",'(?<remote_addr>[0-9:\.]*) - (?<remote_user>[a-zA-Z0-9\-_]*) \[(?<local_time>[a-zA-Z0-9\/ :\-]*)\] "(?<request>[^"]*)" (?<status>[0-9]*) (?<body_bytes_sent>[0-9\-]*) "(?<refer>[^"]*)" "(?<http_user_agent>[^"]*)"')
时间字段处理
默认格式的localtime不易读,我们把它解析成易读的格式
用到的dsl语句,通过dsl
e_set("字段名", "固定值或表达式函数", ..., mode="overwrite")
dt_strftime(日期时间表达式, "格式化字符串")
dt_strptime('值如v("字段名")', "格式化字符串")
实际使用的dsl语句
e_set("local_time", dt_strftime(dt_strptime(v("local_time"),"%d/%b/%Y:%H:%M:%S %z"),"%Y-%m-%d %H:%M:%S"))
Request URI解析
接下来,我们希望对 requst字段进行抽取,我们看到request 字段是由 HTTP_METHOD URI HTTP版本组成的。
我们可以用以下函数来做实现
e_regex("源字段名", "正则或有命名捕获正则", "目标字段名或数组(可选)", mode="fill-auto")
# 进行urldecode
url_decoding('值如v("字段名")’)
# 设置字段值
e_set("字段名", "固定值或表达式函数", ..., mode="overwrite")
e_kv 将request url中的key value键值对进行抽取
实现语句
e_regex("request", "(?<request_method>[^\s]*) (?<request_uri>[^\s]*) (?<http_version>[^\s]*)")
e_set("request_uri", url_decoding(v("request_uri")))
e_kv("request_uri")
实现效果
HTTP Code状态码映射
如果我们想把http code映射出具体的code描述信息,比如我想把404 映射为not found,可以用e_dict_map函数
e_dict_map(“字典如{‘k1’:‘v1’, ‘k2’:‘v2’}”, “源字段正则或列表”, “目标字段名”)
用到的DSL,如果有key match不到,就会使用*这个key对应的值
e_dict_map({'200':'OK',
'304' : '304 Not Modified',
'400':'Bad Request',
'401':'Unauthorized',
'403':'Forbidden',
'404':'Not Found',
'500':'Internal Server Error',
'*':'unknown'}, "status", "status_desc")
效果
通过User Agent判断客户端操作系统
如果我们想了解客户用的是什么os版本,可以通过user agent里的字段用正则匹配来判断,用到dsl语句
e_switch("条件1e_match(...)", "操作1如e_regex(...)", "条件2", "操作2", ..., default="可选无匹配时的操作")
regex_match('值如v("字段名")', r"正则表达式", full=False)
e_set("字段名", "固定值或表达式函数", ..., mode="overwrite")
用到的dsl语句
e_switch(regex_match(v("content"), "Mac"), e_set("os", "osx"),
regex_match(v("content"), "Linux"), e_set("os", "linux"),
regex_match(v("content"), "Windows"), e_set("os", "windows"),
default=e_set("os", "unknown")
)
效果
4xx的日志单独投递到指定logstore
可以使用e_output函数来做日志投递,用regex_match做字段匹配
regex_match('值如v("字段名")', r"正则表达式", full=False)
e_output(name=None, project=None, logstore=None, topic=None, source=None, tags=None)
e_if("条件1如e_match(...)", "操作1如e_regex(...)", "条件2", "操作2", ....)
实际的dsl语句
e_if(regex_match(v("status"),"^4.*"),
e_output(name="logstore_4xx",
project="dashboard-demo",
logstore="dsl-nginx-out-4xx"))
在预览里看到这个效果。(保存加工的时候,需要设置好对应project、logstore的ak信息)
完整的DSL代码以及上线流程
完整的DSL代码
# 通用字段抽取
e_regex("content",'(?<remote_addr>[0-9:\.]*) - (?<remote_user>[a-zA-Z0-9\-_]*) \[(?<local_time>[a-zA-Z0-9\/ :\-]*)\] "(?<request>[^"]*)" (?<status>[0-9]*) (?<body_bytes_sent>[0-9\-]*) "(?<refer>[^"]*)" "(?<http_user_agent>[^"]*)"')
# 设置localttime
e_set("local_time", dt_strftime(dt_strptime(v("local_time"),"%d/%b/%Y:%H:%M:%S %z"),"%Y-%m-%d %H:%M:%S"))
# uri字段抽取
e_regex("request", "(?<request_method>[^\s]*) (?<request_uri>[^\s]*) (?<http_version>[^\s]*)")
e_set("request_uri", url_decoding(v("request_uri")))
e_kv("request_uri")
# http code映射
e_dict_map({'200':'OK',
'304':'304 Not Modified',
'400':'Bad Request',
'401':'Unauthorized',
'403':'Forbidden',
'404':'Not Found',
'500':'Internal Server Error',
'*':'unknown'}, "status", "status_desc")
# user agent 字段判断
e_switch(regex_match(v("content"), "Mac"), e_set("os", "osx"),
regex_match(v("content"), "Linux"), e_set("os", "linux"),
regex_match(v("content"), "Windows"), e_set("os", "windows"),
default=e_set("os", "unknown")
)
# logstore单独投递
e_if(regex_match(v("status"),"^4.*"),
e_output(name="logstore_4xx", project="dashboard-demo", logstore="dsl-nginx-out-4xx"))
在页面提交代码以后,保存数据加工
配置目标logstore信息。如果有e_output的话,需要设置对应额外的存储目标名称、project、logstore需要和代码里一致
保存完即完成上线,可以在数据处理-加工下看到该任务,点击进去可以看到加工延迟等信息。
如果需要进行修改,也可以通过该入口进入修改。
参考
- https://help.aliyun.com/document_detail/125384.html 【阿里云日志服务- 数据加工简介】
- https://help.aliyun.com/document_detail/159702.html 【阿里云日志服务-数据加工函数总览】