长话短说,我正在构建一个规则引擎原型来过滤Web请求日志。
例如
Web 请求日志就像数百万行 json 数据,如下所示:
{"ip": "2.3.4.5", "user": {"register_time": 1494899081.527145, "gender": "F"}}
如果操作员可以在我们的系统中指定一些规则,例如
ip == '1.2.4.5' and (user.register_time - now < 3600 or user.gender == 'F')
如果日志中的某一行与规则匹配,则引擎会将该行执行下一系列操作。
请注意,now
变量由我们的规则引擎提供。规则引擎能够提供多个系统变量和函数。
我正在使用的原型是使用 python 中的eval()
方法将规则转换为实际的 python 代码并逐行检查日志。(是的,我知道eval()
很糟糕,但请记住这是一个原型)
我的问题是,在上面的示例中,如果某个行与规则匹配,我想告诉满足哪些确切条件。只是user.register_time - now < 3600
True
,还是只是user.gender == 'F'
True
?(或两者兼而有之?
目前我正在使用ast.iter_fields
来查找所有ast.Name
和ast.Attribute
并再次使用eval()
作为其值,但是对于一行数据,我不得不多次运行 eval() 感觉有点多余。
是否可以反省值是如何从最后一行代码计算的,就像上面的简单A and (B or C)
布尔表达式一样。我们能否很好地找出评估了哪个部分以及通过哪个值进行了评估?
PLus,对于or
表达式,我们能分辨出哪个部分被省略了,因为它被先验条件短路了?
由MacroPy解决。
from macropy.tracing import macros, trace
with trace:
sum = 0
for i in range(0, 5):
sum = sum + 5
# sum = 0
# for i in range(0, 5):
# sum = sum + 5
# range(0, 5) -> [0, 1, 2, 3, 4]
# sum = sum + 5
# sum + 5 -> 5
# sum = sum + 5
# sum + 5 -> 10
# sum = sum + 5
# sum + 5 -> 15
# sum = sum + 5
# sum + 5 -> 20
# sum = sum + 5
# sum + 5 -> 25