首页 > 解决方案 > 如何将 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

标签: regexpostgresqlsplunk

解决方案


所以我选择通过 python 来实现这个解决方案,我这样做有几个原因。

  1. 一般来说,python 很快——你在每一行都执行大量的正则表达式搜索,python 具有诸如 pop、break 和全面的 if/else 语句等功能,可以进一步加快速度。(我相信我使用 pop 非常有效地在每次正则表达式迭代中不断缩小列表)

  2. 有限的生产数据——重建你的环境真的很难。无论我想出什么答案,我都无法对其进行测试,也不能保证它会更快,或者它甚至会起作用。

  3. 您已经有一个 CSV - 老实说,其中 90% 就在那里,将 CSV 放回 splunk 似乎是额外的步骤。

  4. 这可以根据您想要的任何内容进行缩放 - 我试图使其尽可能直观并且只使用基本库。更新 regex.txt、CSV 和 Go

现在吃肉和土豆——

我有三个文件 , , regex.txt(确保它们都在同一个文件夹中)。api_calls.csvapi_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 - 它们是最好/最简单的即插即用一切开始。

如果您有任何疑问或想要添加/更改某些内容,请随时在评论中发布,我会更新。


推荐阅读