成喆 2019-06-10 05:55:22 浏览 16 评论 0
python
日志
LOG
配置
Image
负载均衡
slb
regex
数据加工
数据规整
日志分发
摘要: 日志服务数据加工上线, 本文以 SLB 日志加工实战为例, 覆盖规则编写, 控制台交互, 权限配置, 监控排错等
背景
这里我们对一个 Logstore 中的网关数据 (阿里云 SLB 日志) 举例, 对其数据进行加工并分发到不通的 Logstore 中.
数据
源 logstore(slb-log)的数据内容是一个阿里云 SLB 的网络日志, 格式样例如下:
- __source__: log_service
- __tag__:__receive_time__: 1559799897
- __topic__:
- body_bytes_sent: 740
- client_ip: 1.2.3.4
- host: m.abcd.com
- http_host: m.abcd.com
- http_referer: -
- http_x_forwarded_for: -
- http_x_real_ip: -
- read_request_time: 0
- request_length: 0
- request_method: GET
- request_time: 0.000
- request_uri: /category/abc/product_id?id=75&type=2&sam=123
- scheme: https
- server_protocol: HTTP/2.0
- slb_vport: 443
- slbid: lb-1234
- ssl_cipher: ECDHE-RSA-AES128-GCM-SHA256
- ssl_protocol: TLSv1.2
- status: 200
- tcpinfo_rtt: 58775
- time: 2019-06-06T13:44:50+08:00
- upstream_addr: 1.2.3.4:80
- upstream_response_time: 4.1234
- upstream_status: 200
- vip_addr: 1.2.3.4
- write_response_time: 4.1234
目标
这里我们希望对数据进行如下加工获取三份数据:
分发
将所有 status 非 2XX 或者 3XX 的请求, 复制一份到目标 logstore: slb-log-error 中, 日志时间 180 天, 以便进一步做研发与安全类分析,__topic__设置为 slb_error
将所有不那么重要的图片或静态资源的请求日志, 分发到目标 logstore: slb-log-media, 日志保存 30 天, topic 设置为 slb_media_request
其他的请求日志, 用于进一步分析统计业务对接的, 分发到目标 logstore: slb-log-normal, 日志保存 90 天, topic 设置为 slb_normal
转换
对 slb_media_request 的请求
提取如下字段
- object_file=App.icon
- object_type = icon # CSS, jpeg, JS 等
保留如下字段:
- http_referer: -
- body_bytes_sent: 740
- client_ip: 1.2.3.4
- host: m.abcd.com
- request_time: 4.33
slb_normal 请求
保留如下字段
- body_bytes_sent: 740
- client_ip: 1.2.3.4
- host: m.abcd.com
- http_referer: -
- http_x_real_ip: -
- request_length: 0
- request_method: GET
- request_time: 4.33
- request_uri: /category/abc/product_id?id=75&type=2&sam=123
- scheme: https
- slb_vport: 443
- slbid: lb-1234
- status: 200
- time: 2019-06-06T13:44:50+08:00
提取 request_uri 的参数加上前缀 reqparam_
- reqparam_id: 75
- reqparam_type: 2
- reqparam_sam: 123
http_x_real_ip 如果为空或者 - 时, 填上 client_ip 的值
提取 host 中的 domain 值:
domain: abcd
准备工作
目标 logstore 准备
创建好如下 3 个 logstore
- slb-log-normal # 日志保存 90 天, 逻辑命名定为 target0
- slb-log-error # 日志保存 180 天, 逻辑命名定为 target1
- slb-log-media # 日志保存 30 天, 逻辑命名定位 target2
并各自配置好索引
点击每个 logstore 的[查询] 页面的[索引] 设置, 并根据每个 logstore 存储的日志的字段, 配置相应的索引. 也可以使用 CloudShell 中的 CLI 的子命令来从源 logstore 复制一份索引到目标, 再进行调整来简化操作.
权限秘钥准备
当前操作需要授权以便读取源 logstore 或写入目标 logstore
通过 AK 秘钥授权
通过角色授权(二期会支持)
需要准备好一个或多个(每个 logstore 对应一个)AK 秘钥访问:
源 logstore 的最小 RAM 授权
- {
- "Version": "1",
- "Statement": [
- {
- "Action": [
- "log:ListShards",
- "log:GetCursorOrData",
- "log:GetConsumerGroupCheckPoint",
- "log:UpdateConsumerGroup",
- "log:ConsumerGroupHeartBeat",
- "log:ConsumerGroupUpdateCheckPoint",
- "log:ListConsumerGroup",
- "log:CreateConsumerGroup"
- ],
- "Resource": [
- "acs:log:*:*:project / 源 project/logstore/slb-log",
- "acs:log:*:*:project / 源 project/logstore/slb-log/*"
- ],
- "Effect": "Allow"
- }
- ]
- }
目标 logstore 的最下 RAM 授权
- {
- "Statement": [
- {
- "Action": [
- "log:Post*"
- ],
- "Effect": "Allow",
- "Resource": [ "acs:log:*:*:project / 目标 Project/logstore/slb-log-error", "acs:log:*:*:project / 目标 Project/logstore/slb-log-media", "acs:log:*:*:project / 目标 Project/logstore/slb-log-normal"]
- }
- ],
- "Version": "1"
- }
也可以考虑将这两个授权合并成一个以便简化操作.
配置加工任务
进入加工规则界面
在日志服务列表中, 选择源 logstore(slb-log)[加工]
进入交互的加工界面
在 #1 中选择日期的时间, 例如[今天] , 确保能够看到数据:
复制失败的请求日志到 sbl-log-error
在编辑框中输入如下的规则(关于语法说明, 可参考后续的章节):
- TRANSFORM_ANY_1 = {
- "status": r"4\d+|5\d+"
- }, COUTPUT(name='target1', topic="slb_error")
- DROP_EVENT_1 = ANY
再点击[预览数据] , 会弹窗提示输入访问源 logstore 的 AK 秘钥, 输入前面准备的,
等一会, 可以在[数据加工] 标签页中看到结果中, 将所有非 2XX/3XX 的请求会输出到 target1 的目标中, 且 topic 设置为了 slb_error:
提取静态类请求日志并输出到 sbl-log-media
在规则编辑框中更新如下规则(关于语法说明, 可参考后续的章节:
- #TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
- SET_EVENT_object_file = regex(v("request_uri"), r"/([\.\w]+\.\w+)(?:\?.+|$)?", gi=0)
- SET_EVENT_object_type = regex(v("object_file"), r"^[\w\.]+\.(\w+)$", gi=0)
- TRANSFORM_EVENT_2 = NO_EMPTY("object_file"),
- [ KEEP_F([F_META, r"object_\w+|request_uri|client_ip|host|request_time" ]),
- OUTPUT(name="target2", topic="slb_media_request"),
- ]
- DROP_EVENT_1 = ANY
再点击[预览数据] , 等一会, 可以在[数据加工] 标签页中看到结果中, 将静态类请求会输出到 target2 的目标中, 如前面需求描述, 特定的字段被提取, 并且还新增了 2 个字段 object_file 和 object_type 且 topic 设置为了 slb_media_request:
调整字段并输出正常请求日志到 sbl-log-normal
在编辑框中更新如下规则(关于语法说明, 可参考后续的章节:
- #TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
- #SET_EVENT_object_file = regex(v("request_uri"), r"/([\.\w]+\.\w+)(?:\?.+|$)?", gi=0)
- #SET_EVENT_object_type = regex(v("object_file"), r"^[\w\.]+\.(\w+)$", gi=0)
- #TRANSFORM_EVENT_2 = NO_EMPTY("object_file"),
- # [ KEEP_F([F_META, r"object_\w+|request_uri|client_ip|host|request_time" ]),
- # OUTPUT(name="target2", topic="slb_media_request"),
- # ]
- SET_EVENT___topic__ = 'slb_normal'
- EXTRACT_EVENT_request_uri = KV(prefix="reqparam_")
- SET_EVENT_http_x_real_ip = op_if(op_eq(v("http_x_real_ip"), '-'), v("client_ip"), v("http_x_real_ip")
- KEEP_FIELDS_1 = [F_META, r"body_bytes_sent|client_ip|host|http_referer|http_x_real_ip|request_length",
- "request_method|request_time|request_uri|scheme|slb_vport|slbid|status"]
- #DROP_EVENT_1 = ANY
再点击[预览数据] , 等一会, 可以在[数据加工] 标签页中看到结果中, 将非媒体类请求输出到 target0 的目标中, 如前面需求描述, 特定的字段被提取, 并且字段 http_x_real_ip 被设置成了非 - 的值, 且 topic 设置为了 slb_normal:
保存配置
最终加工规则
在确认规则正确后, 去掉注释的部分, 就是完整版本:
- TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
- SET_EVENT_object_file = regex(v("request_uri"), r"/([\.\w]+\.\w+)(?:\?.+|$)?", gi=0)
- SET_EVENT_object_type = regex(v("object_file"), r"^[\w\.]+\.(\w+)$", gi=0)
- TRANSFORM_EVENT_2 = NO_EMPTY("object_file"),
- [ KEEP_F([F_META, r"object_\w+|request_uri|client_ip|host|request_time" ]),
- OUTPUT(name="target2", topic="slb_media_request"),
- ]
- SET_EVENT___topic__ = 'slb_normal'
- EXTRACT_EVENT_request_uri = KV(prefix="reqparam_")
- SET_EVENT_http_x_real_ip = op_if(op_eq(v("http_x_real_ip"), '-'), v("client_ip"), v("http_x_real_ip")
- KEEP_FIELDS_1 = [F_META, r"body_bytes_sent|client_ip|host|http_referer|http_x_real_ip|request_length",
- "request_method|request_time|request_uri|scheme|slb_vport|slbid|status"]
配置目标
点击[保存加工配置] , 在配置中, 依据前面的需求, 配置源 logstore 的秘钥(预览的时候已经配置了), 以及 3 个目标 logstore 的 Project 名, logstore 名和写入的 AK 秘钥. 注意 3 个目标的逻辑名称需要与规则中应用的规则保持一致.
配置加工范围
在加工范围中, 可以根据情况选择[所有] ,[某个时间开始] 或者特定范围, 这里选择[某个时间开始] , 并选择此刻. 那么保存后, 新写入源 logstore 的数据将会自动应用规则写入到配置的 3 个目标去.
加工任务管理与监控
任务管理
点击日志服务项目页面的左侧导航栏中的[数据加工] , 可以看到保存的加工任务, 可以根据情况选择修改, 停止, 重启等操作.
状态洞察
对于数据加工的状态, 可以点击以上的[规则洞察] , 可以看到当前任务的执行状态, 以及错误信息, 以便调整:
语法详细说明
第一次预览操作
规则
- TRANSFORM_ANY_1 = {
- "status": r"4\d+|5\d+"
- }, COUTPUT(name='target1', topic="slb_error")
- DROP_EVENT_1 = ANY
说明
这里的规则
TRANSFORM_ANY_1 = 条件, 操作
Python 语法中, 字符串前面用 r 修饰, 可以避免写两个 \ 的麻烦.
操作: COUTPUT(name='target1', topic="slb_error") 表示复制一份数据并输出到目标 target1 中, 并且将 topic 设置为 slb_error
规则 DROP_EVENT_1 = ANY 表示丢弃所有剩余的日志; 这里是为了预览的效果特意加上, 实际保存的配置中不会有这句话.
第二次预览操作
规则
- #TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
- SET_EVENT_object_file = regex(v("request_uri"), r"/([\.\w]+\.\w+)(?:\?.+|$)?", gi=0)
- SET_EVENT_object_type = regex(v("object_file"), r"^[\w\.]+\.(\w+)$", gi=0)
- TRANSFORM_EVENT_2 = NO_EMPTY("object_file"),
- [ KEEP_F([F_META, r"object_\w+|request_uri|client_ip|host|request_time" ]),
- OUTPUT(name="target2", topic="slb_media_request"),
- ]
- DROP_EVENT_1 = ANY
详细说明
SET_EVENT_字段名表示设置一个新字段, 使用后面的表达式函数的返回值: 从字段 request_uri 中提取了字段 object_file, 然后进一步提取了 object_type, 如果 object_file 不存在, 字段 object_type 也不会存在.
TRANSFORM_EVENT_2 = 条件, [操作 1, 操作 2]
表示对于字段 object_file 不为空的事件, 保留特定字段, 并且输出到 target2 后不再后续处理.
规则中的第一行步骤使用 Python 的语法方式 #注释掉了, 保留最后一行 DROP_EVENT_1 = ANY 的目的是方便预览.
第三次预览操作
规则
- #TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
- #SET_EVENT_object_file = regex(v("request_uri"), r"/([\.\w]+\.\w+)(?:\?.+|$)?", gi=0)
- #SET_EVENT_object_type = regex(v("object_file"), r"^[\w\.]+\.(\w+)$", gi=0)
- #TRANSFORM_EVENT_2 = NO_EMPTY("object_file"),
- # [ KEEP_F([F_META, r"object_\w+|request_uri|client_ip|host|request_time" ]),
- # OUTPUT(name="target2", topic="slb_media_request"),
- # ]
- SET_EVENT___topic__ = 'slb_normal'
- EXTRACT_EVENT_request_uri = KV(prefix="reqparam_")
- SET_EVENT_http_x_real_ip = op_if(op_eq(v("http_x_real_ip"), '-'), v("client_ip"), v("http_x_real_ip")
- KEEP_FIELDS_1 = [F_META, r"body_bytes_sent|client_ip|host|http_referer|http_x_real_ip|request_length",
- "request_method|request_time|request_uri|scheme|slb_vport|slbid|status"]
详细说明
这里设置默认的事件__topic__
使用
EXTRACT_EVENT_字段名 = 字段类操作
, 对字段 request_uri 的值进行 KV 操作, 自动提取其中的键值对并放到事件中.
进一步的基于表达式函数设置了字段 http_x_real_ip 的值. 最后保留特定字段.
默认没有使用 OUTPUT 等, 因为默认会将事件输出到第一个配置的目标 target0 中.
规则中的前 2 个步骤使用 Python 的语法方式 #注释掉了, 目的是为了避免预览效果的查看, 后续会恢复.
进一步参考
欢迎扫码加入官方钉钉群 (11775223)获得实时更新与阿里云工程师的及时直接的支持:
来源: https://yq.aliyun.com/articles/704936