如何用LogQL Pattern过滤器拆分路径与参数,实现按路径分组?
搞定LogQL统计Nginx Ingress纯路径请求的问题
直接说结论:正则比pattern好用
pattern过滤器是固定占位符匹配,没法同时适配「带参数」和「不带参数」的路径——比如/api/user和/api/user?id=123,要么抓不到带参数的纯路径,要么会把参数也塞进path里。这种情况用正则提取是最直接的办法。
具体怎么写?
1. 先正则提取纯路径
假设你的日志里请求行是"GET /api/user?id=123 HTTP/1.1"这种格式,用正则分组直接把?前面的路径抠出来:
{job="nginx-ingress"} |= "GET" | regexp(`"(GET|POST|PUT|DELETE) (?P<path>[^?]+)(?:\?.*)? HTTP/1\.1"`) | regexp(`status=(?P<status>\d{3})`) | regexp(`request_time=(?P<request_time>[0-9.]+)`)
拆解下关键部分:
(?P<path>[^?]+):专门抓从空格后到第一个?的所有内容,这就是你要的纯路径(?:\?.*)?:不管有没有?和后面的参数,都跳过不提取- 后面两个正则分别抓状态码和请求时间,你得根据自己的日志格式调整匹配规则
2. 按纯路径分组统计
提取完字段后,就可以按path分组聚合了,比如统计5分钟内每个路径的请求数:
sum(count_over_time({job="nginx-ingress"} |= "GET" | regexp(`"(GET|POST|PUT|DELETE) (?P<path>[^?]+)(?:\?.*)? HTTP/1\.1"`) | regexp(`status=(?P<status>\d{3})`) | regexp(`request_time=(?P<request_time>[0-9.]+)`)[5m])) by (path)
要是想算每个路径的平均请求时间,就改成:
avg_over_time({job="nginx-ingress"} |= "GET" | regexp(`"(GET|POST|PUT|DELETE) (?P<path>[^?]+)(?:\?.*)? HTTP/1\.1"`) | regexp(`request_time=(?P<request_time>[0-9.]+)`)[5m]) by (path)
为啥pattern不行?
pattern是死格式匹配,比如你写pattern "\"method=GET path={{path}} status={{status}}\"",如果路径带?,它会把?和参数全算进path里;要是你把pattern写成只匹配到?前,那不带参数的路径又匹配不上了,没法兼顾两种情况。
额外小技巧
如果你的Nginx Ingress日志是JSON格式输出的,那更省事:直接取json里的path字段,再用replace把?后面的内容删掉就行:
{job="nginx-ingress"} | json | replace(path, `\?.*`, "") as clean_path | sum(count_over_time([5m])) by (clean_path)
内容的提问来源于stack exchange,提问作者nikobelia
相关产品推荐
相关产品推荐

