日志服务数据加工:快速开始(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

目标

这里我们希望对数据进行如下加工获取三份数据:

分发

  1. 将所有status非2XX或者3XX的请求,复制一份到目标logstore: slb-log-error中,日志时间180天,以便进一步做研发与安全类分析,__topic__设置为slb_error
  2. 将所有不那么重要的图片或静态资源的请求日志,分发到目标logstore: slb-log-media,日志保存30天, topic设置为slb_media_request
  3. 其他的请求日志,用于进一步分析统计业务对接的,分发到目标logstore: slb-log-normal,日志保存90天,topic设置为slb_normal

转换

  1. 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
  1. 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准备

  1. 创建好如下3个logstore
slb-log-normal  # 日志保存90天,逻辑命名定为target0
slb-log-error    # 日志保存180天,逻辑命名定为target1
slb-log-media  # 日志保存30天, 逻辑命名定位target2
  1. 并各自配置好索引
    点击每个logstore的【查询】页面的【索引】设置,并根据每个logstore存储的日志的字段,配置相应的索引。也可以使用CloudShell中的CLIcopy_logstore子命令来从源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"
}

也可以考虑将这两个授权合并成一个以便简化操作。

配置加工任务

进入加工规则界面

  1. 在日志服务列表中,选择源logstore(slb-log)【加工】

image

  1. 进入交互的加工界面
    在 #1 中选择日期的时间,例如【今天】,确保能够看到数据:

image

复制失败的请求日志到sbl-log-error

在编辑框中输入如下的规则(关于语法说明,可参考后续的章节):

TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
DROP_EVENT_1 = ANY 

再点击【预览数据】,会弹窗提示输入访问源logstore的AK秘钥,输入前面准备的,
image

等一会,可以在【数据加工】标签页中看到结果中,将所有非2XX/3XX的请求会输出到target1的目标中,且topic设置为了slb_error
image

提取静态类请求日志并输出到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_fileobject_typetopic设置为了slb_media_request
image

调整字段并输出正常请求日志到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
image

保存配置

最终加工规则
在确认规则正确后,去掉注释的部分,就是完整版本:

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个目标的逻辑名称需要与规则中应用的规则保持一致。

image

配置加工范围
在加工范围中,可以根据情况选择【所有】、【某个时间开始】或者特定范围,这里选择【某个时间开始】,并选择此刻。那么保存后,新写入源logstore的数据将会自动应用规则写入到配置的3个目标去。
image

加工任务管理与监控

任务管理

点击日志服务项目页面的左侧导航栏中的【数据加工】,可以看到保存的加工任务,可以根据情况选择修改、停止、重启等操作。
image

状态洞察

对于数据加工的状态,可以点击以上的【规则洞察】,可以看到当前任务的执行状态,以及错误信息,以便调整:
image
image

语法详细说明

第一次预览操作

规则

TRANSFORM_ANY_1 = {"status": r"4\d+|5\d+" }, COUTPUT(name='target1', topic="slb_error")
DROP_EVENT_1 = ANY 

说明

  1. 这里的规则TRANSFORM_ANY_1 = 条件, 操作
  • Python语法中,字符串前面用r修饰,可以避免写两个\的麻烦。
  • 操作:COUTPUT(name='target1', topic="slb_error") 表示复制一份数据并输出到目标target1中,并且将topic设置为slb_error
  1. 规则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 

详细说明

  1. SET_EVENT_字段名表示设置一个新字段,使用后面的表达式函数的返回值:从字段request_uri中提取了字段object_file,然后进一步提取了object_type,如果object_file不存在,字段object_type也不会存在。
  2. TRANSFORM_EVENT_2 = 条件, [操作1, 操作2]表示对于字段object_file不为空的事件,保留特定字段,并且输出到target2后不再后续处理。
  3. 规则中的第一行步骤使用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"]

详细说明

  1. 这里设置默认的事件__topic__
  2. 使用EXTRACT_EVENT_字段名 = 字段类操作,对字段request_uri的值进行KV操作,自动提取其中的键值对并放到事件中。
  3. 进一步的基于表达式函数设置了字段http_x_real_ip的值。最后保留特定字段。
  4. 默认没有使用OUTPUT等,因为默认会将事件输出到第一个配置的目标target0中。
  5. 规则中的前2个步骤使用Python的语法方式#注释掉了,目的是为了避免预览效果的查看,后续会恢复。

进一步参考

欢迎扫码加入官方钉钉群 (11775223)获得实时更新与阿里云工程师的及时直接的支持:
image

猜你喜欢

转载自yq.aliyun.com/articles/704936
今日推荐