日志服务数据加工最佳实践: 函数调用

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 本篇介绍日志服务数据加工最佳实践: 函数调用汇总, 如何绕开相关的坑等

编写数据加工规则过程中,需根据场景选择不同的函数。LOG DSL函数的具体用法可参考数据加工语法参考

场景1: 理解e_keep/KEEP的应用场景

默认规则中, 不做处理的事件都是保留. 所以KEEP通常只用于特定场景. 如果需要丢弃日志, 可以使用e_drop/e_drop传入条件或者使用e_if/e_if_elseDROP搭配使用:

如下比较区别:

e_keep(e_search(...) )    # 满足保留, 不满足丢弃
e_drop(e_search(...) )    # 满足丢弃, 不满足保留
e_if(e_search("..."), KEEP)    # 没有意义的代码, 满足后KEEP
e_if_else(e_search("..."), KEEP, DROP)    # 有意义
e_if(e_search("not ..."), DROP)        # 有意义

场景2:尽可能使用函数自身提供的功能

子场景1:当原字段不存在或者为空时,为字段赋值

  • 最佳实践
e_set("result", ".....value...", mode="fill")
  • 非最佳实践
e_if(op_not(v("result")), e_set("result", ".....value..."))
  • 字段的提取与覆盖模式,参考字段提取与覆盖模式
    提取与覆盖模式包含:

    • fill – 当原字段不存在或者值为空时
    • add –当原字段不存在时设置
    • overwrite – 总是设置
    • fill/add/overwrite-auto – 当新值非空时才fill/add/overwrite

子场景2:使用GROK函数简化正则表达式

  • 加工逻辑
    提取content字段中的IP地址


  • 原日志格式
content:"ip address: 192.168.1.1"
  • 提取目标: 192.168.1.1

  • 最佳实践
e_regex("content", grok(r"\w+: (%{IP})"), "addr")
# 或者
e_regex("content", grok(r"\w+: (%{IP:addr})"))
  • 非最佳实践
    如下代码相对复杂一些:
e_regex("content", grok(r"\w+: (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})"), "addr")

进一步参考Grok函数说明

子场景3:给多个字段赋值

  • 最佳实践
e_set("k1", "v1", "k2", "v2", "k3", "v3", ....)
  • 相对冗余的规则
e_set("k1", "v1")
e_set("k2", "v2")
e_set("k3", "v3")
...

场景3:使用e_compose减少重复判断

  • 加工逻辑
    如果content是123,则首先执行删除age和name字段,然后重命名content为ctx


  • 原日志格式
content:123
age:23
name:twiss
  • 加工后的日志格式
  ctx: 123
  • 最佳实践
    一般情况下推荐使用e_compose组合相同逻辑下的操作.
e_if(e_search("content==123"), 
     e_compose(e_drop_fields("age|name"), e_rename("content", "ctx")))
  • 非最佳实践
    如下代码会多次判断, 一定程度上效率低一些.
e_if(e_search("content==123"), e_drop_fields("age|name"))
e_if(e_search("content==123"), e_rename("content", "ctx"))

进一步参考事件判断

场景4:注意表达式函数的参数类型

日志事件的字段和值在函数之间传递的过程中,始终都是字符串形式。非字符串类型的数据会被自动转化为字符串类型。因此在调用函数时,要注意各个函数能接收的参数类型。具体每个函数接收的参数类型可参考数据加工语法参考中对各个函数的解释。

样例1:
op_add既可以接收字符串类型,也可以接受数值类型,因此不需要做参数类型转换

e_set("a", 1)
e_set("b", 2)

op_add(v("a"), v("b"))    # 合法,返回值为"12"
op_add(ct_int(v("a")), ct_int(v("b")))    # 合法, 返回值为3

样例2:
op_sum, op_mul等函数只能接受数值类型,因此需要做数据类型转换,将字符串转化为数值型

e_set("a", 1)
e_set("b", 2)

op_sum(v("a"), v("b"))    # 非法
op_sum(ct_int(v("a")), ct_int(v("b")))    # 合法, 返回值为3

op_mul(v("a"), v("b"))    # 非法
op_mul(ct_int(v("a")), ct_int(v("b")))    # 合法, 返回值为2

日志事件在函数间传递,字段值都被自动转化为字符串类型,因此v("a"), v("b")都是字符串类型。而op_sum, op_mul等函数只能接受数值类型,可通过ct_int将字符串转化为整型,再传递给这类函数。

样例3:

"""
加工逻辑: 将time1表示的日期时间转化为Unix时间戳
"""
e_set("time1", "2019-06-03 2:41:26")

e_set("time2", dt_totimestap(v("time1"))) # 非法

e_set("time2", dt_totimestap(dt_parse(v("time1")))) # 合法
e_set("time2", dt_parsetimestamp(v("time1"))) # 合法
  • dt_totimestap接收的参数类型为日期时间对象, 不是字符串。因此需要调用dt_parse将time1的字符串值类型转化为日期时间对象类型。
  • 也可直接使用dt_parsetimestamp函数,它既可接收日期时间对象,也可接收字符串。

场景5:注意表达式函数的异常处理情况

许多表达式函数对于输入的参数有一定的要求, 如果不满足会报错. 也有一些会返回默认值容错, 需要特别注意, 这些默认值传递给后续的函数时可能进一步会报错. 例如:

e_set("data_len": op_len(v("data")))                     # 错误调用
e_set("data_len": op_len(v("data", default="")))  # 正确调用

如果字段data不存在时v("data")会返回None, 那么第一个调用会报错. 第二个通过默认值default给与一个合法的默认值, 让表达式可以不会报错.

场景6:理解e_if与e_switch的区别

  • e_if语法
e_if(条件1, 操作1, 条件2, 操作2, 条件3, 操作3, ....)

条件与操作的配对组合, 依次根据条件判断, 满足条件的进行相应操作, 不满足条件的不进行对应操作, 进行下一个条件判断.

  • e_switch语法
e_switch(条件1, 操作1, 条件2, 操作2, 条件3, 操作3, ...., default=None)

条件与操作的配对组合, 依次根据条件判断, 满足条件的进行相应操作, 然后直接返回操作的结果, 不满足条件的不进行对应操作, 进行下一个条件判断. 如果没有任何条件满足, 并且配置了default参数的话, 执行default配置的操作并返回

  • 样例

原始日志

status1: 200
status2: 404

e_if加工规则

e_if(e_match("status1", "200"), e_set("status1_info", "normal"), 
          e_match("status2", "404"), e_set("status2_info", "error"))

加工后日志

status1: 200
status2: 404
status1_info: normal
status2_info: error

e_if会进行所有条件的判断,满足的则进行对应操作,不满足不进行对应操作。


e_switch加工规则

e_switch(e_match("status1", "200"), e_set("status1_info", "normal"), 
                   e_match("status2", "404"), e_set("status2_info", "error"))

加工后日志

status1: 200
status2: 404
status1_info: normal

e_switch只要有一个条件满足,就会返回结果,不会再进行后续条件判断。

进一步参考

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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
4月前
|
SQL 关系型数据库 MySQL
我使用flinkcdc的sql形式进行全量同步,4张表,有两张表数据没进去,看日志,id怎么是null呢?
我使用flinkcdc的sql形式进行全量同步,4张表,有两张表数据没进去,看日志,id怎么是null呢?
117 40
|
6月前
|
XML Java API
SpringBoot3.x日志生产最佳实践原来是这样!
SpringBoot3.x日志生产最佳实践原来是这样!
162 0
|
1天前
|
人工智能 数据可视化 开发工具
Git log 进阶用法(含格式化、以及数据过滤)
Git log 进阶用法(含格式化、以及数据过滤)
|
3天前
|
机器学习/深度学习 前端开发 数据挖掘
工具变量法(两阶段最小二乘法2SLS)线性模型分析人均食品消费时间序列数据和回归诊断(下)
工具变量法(两阶段最小二乘法2SLS)线性模型分析人均食品消费时间序列数据和回归诊断
74 11
|
8天前
工具变量法(两阶段最小二乘法2SLS)线性模型分析人均食品消费时间序列数据和回归诊断2
工具变量法(两阶段最小二乘法2SLS)线性模型分析人均食品消费时间序列数据和回归诊断
15 0
|
9天前
|
机器学习/深度学习 前端开发 数据挖掘
R语言计量经济学:工具变量法(两阶段最小二乘法2SLS)线性模型分析人均食品消费时间序列数据和回归诊断
R语言计量经济学:工具变量法(两阶段最小二乘法2SLS)线性模型分析人均食品消费时间序列数据和回归诊断
39 0
|
2月前
|
JSON 监控 Java
Java Web开发中的异常处理与日志记录最佳实践
Java Web开发中的异常处理与日志记录最佳实践
|
4月前
|
SQL 存储 监控
使用CloudLens for SLS监控Project资源配额最佳实践
本文主要介绍如何使用CloudLens for SLS中全局错误日志、监控指标做Project 资源配额的水位监控 、超限监控 以及 如何提交资源配额提升申请。
79337 19
使用CloudLens for SLS监控Project资源配额最佳实践
|
4月前
|
SQL 关系型数据库 MySQL
⑩⑥ 【MySQL】详解 触发器TRIGGER,协助 确保数据的完整性,日志记录,数据校验等操作。
⑩⑥ 【MySQL】详解 触发器TRIGGER,协助 确保数据的完整性,日志记录,数据校验等操作。
39 0
|
8天前
|
存储 数据库 流计算
Flink CDC为什么我几张表十来条数据就产生了那么大日志?
Flink CDC为什么我几张表十来条数据就产生了那么大日志?
111 0

相关产品

  • 日志服务