regex - 如何将 API 调用列表与其 API 模式(或组)进行模式匹配?
问题描述
我需要使用日志对 API 调用进行分析,例如avg, min, max response time。
背景
我正在使用splunk,因此这些 API 调用会记录在我的 ILB 日志中,然后我可以使用 Splunk捕获并导出到CSV 。因此,对于 API /data/user/{id}
,我可能有多个调用以及它们的响应时间,例如:
/data/users/1443 | 0.5 sec
/data/users/2232 | 0.2 sec
挑战 :
如果假设具有这些 API 调用命中数据的工作表有 1000 万条记录,并且我有一个 API 模式列表,比如说 3000 个 API 模式(例如:/data/user/{id}/address
、/data/user/{id}/xyz/{another_id}
注意:在某些 API 中, {id} 可能是字母数字。
当前方法
我将此 CSV 表加载到PostgresSQL dbraw data table
中的表中(称为 ,其中包含 ILB 上每个 API 命中的详细信息及其响应时间),然后有一个固定的 API 列表和我替换的列带有正则表达式模式的路径变量,然后我使用基于正则表达式的连接将主表与原始数据表连接起来,并计算 avg、min、max response_time 等。master table
但是,由于使用正则表达式连接,查询需要 5-6 小时才能运行。
我能做点更好的吗?
注意:带有几行原始数据的CSV 示例: https ://pastebin.com/Nx0Hnc9u
proxy method request_time
/data/users/{id} POST 0.046
/server/healthcheck/check/up GET 0.001
/data/commons/people/multi_upsert POST 0.141
/store/org/manufacturing/multi_read POST 0.363
/data/users/{id}/homepage/{name} POST 0.084
/data/view/{name}/pagecount PUT 0.043
Category 1 (path variable only at the end) :
/data/users/{id} POST 0.046
Category 2 (1 or more path variables only in the middle) :
/data/view/{name}/pagecount PUT 0.043
/data/view/{name}/details/{type}/pagecount PUT 0.043
Category 3 (1 or more path variables only in the middle and also at the end) :
/data/users/{id}/homepage/{name} POST 0.084
/data/users/{id}/homepage/{type}/details/{name} POST 0.084
解决方案
所以我选择通过 python 来实现这个解决方案,我这样做有几个原因。
一般来说,python 很快——你在每一行都执行大量的正则表达式搜索,python 具有诸如 pop、break 和全面的 if/else 语句等功能,可以进一步加快速度。(我相信我使用 pop 非常有效地在每次正则表达式迭代中不断缩小列表)
有限的生产数据——重建你的环境真的很难。无论我想出什么答案,我都无法对其进行测试,也不能保证它会更快,或者它甚至会起作用。
您已经有一个 CSV - 老实说,其中 90% 就在那里,将 CSV 放回 splunk 似乎是额外的步骤。
这可以根据您想要的任何内容进行缩放 - 我试图使其尽可能直观并且只使用基本库。更新 regex.txt、CSV 和 Go
现在吃肉和土豆——
我有三个文件 , , regex.txt
(确保它们都在同一个文件夹中)。api_calls.csv
api_reg.py
api_calls.csv
- (这是您调用的 CSV 输出,请注意标题仍然存在)
proxy,method,request_time
/request_time/data/users/3456,POST,0.056
/server/healthcheck/check/up,GET,0.012
/data/commons/people/multi_upsert,POST,0.131
/store/org/manufacturing/multi_read,POST,0.463
/data/users/45645/homepage/fghrt,POST,0.074
/request_time/data/users/5643,POST,0.026
/data/view/fgnfrt/pagecount,PUT,0.034
/server/healthcheck/check/up,GET,0.016
/data/commons/people/multi_upsert,POST,0.135
/store/org/manufacturing/multi_read,POST,0.163
/data/users/45678/homepage/fgbfgn,POST,0.062
/data/view/dfg/pagecount,PUT,0.073
/request_time/data/users/7567,POST,0.026
/server/healthcheck/check/up,GET,0.011
/data/commons/people/multi_upsert,POST,0.121
/store/org/manufacturing/multi_read,POST,0.323
/data/users/64564/homepage/fghfgh,POST,0.054
/data/view/hrthe/pagecount,PUT,0.093
/server/healthcheck/check/up,GET,0.021
/data/commons/people/multi_upsert,POST,0.041
/request_time/data/users/3456,POST,0.048
/store/org/manufacturing/multi_read,POST,0.323
/data/users/56756/homepage/hrthr,POST,0.054
/data/view/bdfbdr/pagecount,PUT,0.103
regex.txt
- (这是您放置所需正则表达式的地方)
\/data\/users\/.*\/homepage\/.*
\/server\/healthcheck\/check\/up
\/data\/commons\/people\/multi_upsert
\/store\/org\/manufacturing\/multi_read
\/data\/view\/.*\/pagecount
\/request_time\/data\/users\/.*
api_reg.py
- (这是python脚本)
import re
import csv
import json
csvDoc = list(csv.DictReader(open("api_calls.csv").readlines()))
regexes = open("regex.txt").readlines()
apis = {}
for regex in regexes:
regex = regex.strip()
prettyReg = regex.replace("\\", "")
for line in reversed(csvDoc):
if re.findall(regex, line['proxy']):
csvDoc.pop(csvDoc.index(line))
time = float(line['request_time'])
if prettyReg not in apis:
apis[prettyReg] = {"min": float("inf"), "max": float("-inf"), "avg": 0.0, "total": 0.0, "count": 0}
apis[prettyReg]['total'] += time
apis[prettyReg]['count'] += 1
apis[prettyReg]['avg'] = apis[prettyReg]['total'] / apis[prettyReg]['count']
if time < apis[prettyReg]['min']: apis[prettyReg]['min'] = time
if time > apis[prettyReg]['max']: apis[prettyReg]['max'] = time
with open("output.txt", "w+") as f:
f.write(json.dumps(apis, indent=4))
output.txt - (这是上面脚本在给定 api_calls.csv 和 regex.txt 的情况下生成的内容)
{
"/data/users/.*/homepage/.*": {
"min": 0.054,
"max": 0.074,
"avg": 0.061,
"total": 0.244,
"count": 4
},
"/server/healthcheck/check/up": {
"min": 0.011,
"max": 0.021,
"avg": 0.015,
"total": 0.06,
"count": 4
},
"/data/commons/people/multi_upsert": {
"min": 0.041,
"max": 0.135,
"avg": 0.10700000000000001,
"total": 0.42800000000000005,
"count": 4
},
"/store/org/manufacturing/multi_read": {
"min": 0.163,
"max": 0.463,
"avg": 0.318,
"total": 1.272,
"count": 4
},
"/data/view/.*/pagecount": {
"min": 0.034,
"max": 0.103,
"avg": 0.07575000000000001,
"total": 0.30300000000000005,
"count": 4
},
"/request_time/data/users/.*": {
"min": 0.026,
"max": 0.056,
"avg": 0.039,
"total": 0.156,
"count": 4
}
}
抱歉,我无法使用 splunk 想出一些东西,但我保证此方法不会需要 5-6 小时才能运行。
如果您的计算机上没有 python,请下载 Python(当前为 3.9.6),我建议使用来自 IDEA 的 IDE Pycharm - 它们是最好/最简单的即插即用一切开始。
如果您有任何疑问或想要添加/更改某些内容,请随时在评论中发布,我会更新。
推荐阅读
- node.js - 有没有办法通过编辑 package.json 来摆脱 npm 可选依赖警告?
- python - Python - “NoneType”对象没有属性“find_next_sibling”
- c# - C# DataTable 和 SqlDataAdapter 打开、关闭连接和性能问题
- c - C如何读取新插入文件的内容?
- android - 使用 Checkstyle 进行 Android 代码分析
- postgresql - PostgreSQL 11 - 程序
- c++ - 索引字符串时通过空终止符
- symfony - Symfony 3.4.11 索引的默认语言环境不起作用
- android - 如何在 git-ignore 文件 android 中添加 gradle.properties?
- python-3.x - 在 scraper.py 中使用 scrapy 自定义设置