news 2026/9/29 22:13:24

Kong 插件,解决2.5.1不支持原生暴露url

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kong 插件,解决2.5.1不支持原生暴露url

lua脚本
建目录custom-latency,编辑文件,打zip包为

file schema.lua local typedefs = require "kong.db.schema.typedefs" return { name = "custom-latency", fields = { { consumer = typedefs.no_consumer }, { protocols = typedefs.protocols_http }, { config = { type = "record", fields = {} } }, }, } file handler.lua -- custom-latency 插件 -- 在 /metrics 上追加带 uri/method/status/service 标签的延迟与请求数指标 -- 复用 kong.plugins.prometheus.exporter 的 prometheus 实例(Kong 2.5.1 实测 API) local kong_prometheus = require "kong.plugins.prometheus.exporter" local CustomLatency = { PRIORITY = 899, VERSION = "1.0.0", } local pm local uri_histogram local uri_counter -- 将路径中的数字段归一化为 :id,避免同类型接口因参数不同产生过多标签 -- 注意:ngx.re.* 使用 PCRE 正则,数字需用 \d 而非 Lua pattern 的 %d local function normalize_uri(uri) return ngx.re.gsub(uri or "", "/\\d+", "/:id", "jo") end -- 取当前请求命中的 service 名({env}-{service} 命名,前缀即环境),匹配不到返回空串 local function get_service_name() local srvc = kong.router.get_service() if not srvc then return "" end return srvc.name or "" end function CustomLatency:init_worker() pm = kong_prometheus.get_prometheus() if not pm then ngx.log(ngx.ERR, "[custom-latency] prometheus exporter not initialized") return end -- 注意:exporter 会自动加 "kong_" 前缀,这里不能再带前缀 uri_histogram = pm:histogram( "uri_latency_ms", "Request latency in milliseconds, labeled by uri, method, status and service", { "uri", "method", "status", "service" }, { 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000 } ) uri_counter = pm:counter( "uri_requests_total", "Total number of requests, labeled by uri, method, status and service", { "uri", "method", "status", "service" } ) end function CustomLatency:log() if not pm or not uri_histogram or not uri_counter then return end local latency_ms = (ngx.var.request_time or 0) * 1000 local uri = normalize_uri(kong.request.get_path() or "") local method = kong.request.get_method() or "" local status = tostring(ngx.status or 0) local service = get_service_name() local labels = { uri, method, status, service } uri_histogram:observe(latency_ms, labels) uri_counter:inc(1, labels) end return CustomLatency

prometheus 配置

- job_name: 'kong' static_configs: - targets: ['127.0.0.1:2001'] labels: instance_service_name: kong

Grafana 配置

{ "annotations": { "list": [] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": null, "links": [], "panels": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "drawStyle": "line", "fillOpacity": 8, "lineInterpolation": "smooth", "lineWidth": 1, "showPoints": "never", "spanNulls": true }, "min": 0, "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 1 }, "id": 1, "options": { "legend": { "calcs": ["lastNotNull", "max"], "displayMode": "table", "placement": "bottom" }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum by (uri, method) (rate(kong_uri_requests_total{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval]))", "legendFormat": "{{method}} {{uri}}", "refId": "A" } ], "title": "接口请求 QPS", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "drawStyle": "line", "fillOpacity": 8, "lineInterpolation": "smooth", "lineWidth": 2, "showPoints": "never", "spanNulls": true }, "min": 0, "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 1 }, "id": 2, "options": { "legend": { "calcs": ["lastNotNull", "max"], "displayMode": "table", "placement": "bottom" }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "histogram_quantile(0.95, sum by (uri, le) (rate(kong_uri_latency_ms_bucket{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval])))", "legendFormat": "{{uri}}", "refId": "A" } ], "title": "接口 P95 响应时间", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "drawStyle": "line", "fillOpacity": 8, "lineInterpolation": "smooth", "lineWidth": 1, "showPoints": "never", "spanNulls": true }, "min": 0, "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 9 }, "id": 4, "options": { "legend": { "calcs": ["lastNotNull", "max"], "displayMode": "table", "placement": "bottom" }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "sum by (uri) (rate(kong_uri_latency_ms_sum{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval])) / sum by (uri) (rate(kong_uri_latency_ms_count{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval]))", "legendFormat": "avg {{uri}}", "refId": "A" } ], "title": "接口平均响应时间", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "continuous-reds" }, "custom": { "drawStyle": "line", "fillOpacity": 8, "lineInterpolation": "smooth", "lineWidth": 1, "showPoints": "never", "spanNulls": true }, "min": 0, "unit": "percent" }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 9 }, "id": 5, "options": { "legend": { "calcs": ["lastNotNull", "max"], "displayMode": "table", "placement": "bottom" }, "tooltip": { "mode": "multi", "sort": "desc" } }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "100 * sum by (uri) (rate(kong_uri_requests_total{status=~\"5..\", method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval])) / clamp_min(sum by (uri) (rate(kong_uri_requests_total{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval])), 0.0001)", "legendFormat": "{{uri}}", "refId": "A" } ], "title": "接口 5xx 错误率", "type": "timeseries" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "unit": "reqps" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 17 }, "id": 6, "options": { "displayMode": "gradient", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "topk(10, sum by (uri) (rate(kong_uri_requests_total{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval])))", "legendFormat": "{{uri}}", "refId": "A" } ], "title": "请求量 Top10", "type": "bargauge" }, { "datasource": { "type": "prometheus", "uid": "prometheus" }, "fieldConfig": { "defaults": { "color": { "mode": "continuous-BlYlRd" }, "unit": "ms" }, "overrides": [] }, "gridPos": { "h": 8, "w": 24, "x": 0, "y": 25 }, "id": 7, "options": { "displayMode": "gradient", "orientation": "horizontal", "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }, "showUnfilled": true }, "targets": [ { "datasource": { "type": "prometheus", "uid": "prometheus" }, "expr": "topk(10, histogram_quantile(0.95, sum by (uri, le) (rate(kong_uri_latency_ms_bucket{method=~\"$method\", uri=~\"$uri\", service=~\"$env-.*\"}[$__rate_interval]))))", "legendFormat": "{{uri}}", "refId": "A" } ], "title": "P95 耗时 Top10(最慢接口)", "type": "bargauge" } ], "refresh": "10s", "schemaVersion": 39, "tags": ["kong"], "templating": { "list": [ { "current": { "text": "dev-current", "value": "dev-current", "selected": true }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(kong_uri_requests_total, service)", "includeAll": true, "allValue": ".*", "multi": false, "name": "env", "label": "环境", "options": [], "query": "label_values(kong_uri_requests_total, service)", "regex": "/(.*)-[a-z0-9]+$/", "refresh": 1, "type": "query" }, { "current": { "text": "All", "value": "$__all", "selected": true }, "includeAll": true, "allValue": ".*", "multi": false, "name": "method", "label": "方法", "options": [ { "text": "All", "value": "$__all", "selected": true }, { "text": "GET", "value": "GET", "selected": false }, { "text": "POST", "value": "POST", "selected": false } ], "query": "GET,POST", "refresh": 1, "type": "custom" }, { "current": { "text": "All", "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "definition": "label_values(kong_uri_requests_total, uri)", "includeAll": true, "allValue": ".*", "multi": true, "name": "uri", "label": "接口路径", "options": [], "query": "label_values(kong_uri_requests_total, uri)", "refresh": 1, "type": "query" } ] }, "time": { "from": "now-1h", "to": "now" }, "timepicker": { "refresh_intervals": ["5s", "10s", "30s", "1m", "5m"] }, "timezone": "browser", "title": "Kong 接口响应时间监控(按环境)", "uid": "kong-uri-metrics-cloud", "version": 1 }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 22:12:59

AI论文降重工具实战:从查重原理到高效降重的完整流程指南

又到一年毕业季,群里哀嚎一片的不是论文写不出来,而是查重报告上那个刺眼的红字。我见过太多人卡在最后一步:学校的查重系统结果一出来,重复率35%,距离合格线还差一大截,留给自己的时间却只剩两三天。说实话…

作者头像 李华
网站建设 2026/9/29 22:12:06

告别无效读论文!从零搞定文献阅读与实验复现完整流程

做机器学习相关课程作业或课题预研,相信很多人都有同样的困扰:认真读完一篇论文,看懂了理论思路,却完全没法落地实操。要么找不到配套数据集和源码,要么实验设计晦涩难懂,手动搭环境、调参耗时费力&#xf…

作者头像 李华
网站建设 2026/9/29 22:10:39

OpenClaw 3.1.0 上手教程,支持键鼠模拟、网页采集、文档批量处理

📖 前言 本文面向 Windows 系统用户,系统梳理 OpenClaw 的标准化部署流程。全程无需输入任何命令行,所有操作均依托可视化向导完成,即便是零基础用户也能独立走完整套部署。文中同时汇总了高频报错的对应解决方案,力求…

作者头像 李华
网站建设 2026/9/29 22:09:20

2026年GEO服务商怎么选?主流方案全维度拆解与优选推荐

AI大模型正在重塑信息分发规则。当越来越多用户开始习惯向豆包、DeepSeek、千问、元宝等平台提问,品牌能否出现在AI的回答里、排在第几位、以什么形象被描述,已经成为决定流量走向的关键变量。GEO(生成引擎优化)由此成为企业营销的…

作者头像 李华
网站建设 2026/9/29 22:09:15

从0打造Agent智能体:2026年开发者必修的架构与实战

简介:这份PDF资料面向具备一定AI与机器学习基础的研发人员、产品经理及技术爱好者,系统讲解AI Agent智能体从概念认知到项目落地的完整路径。内容从人工智能、机器学习、深度学习与大语言模型等基础知识切入,辨析AI Agent与传统程序在自主性、…

作者头像 李华
网站建设 2026/9/29 22:08:55

高层综合体半夜起火:三维一张图如何把内部火点、烟路和消防力量同屏

高层商业综合体深夜起火,指挥中心最先遇到的往往不是“有没有系统”,而是系统之间能不能在同一空间里说话。建筑内部结构、消防设施、人员位置、烟气走向、消防车辆与水源信息分散在图纸、台账、监控和电话汇报里,指挥员拿到的是一串碎片&…

作者头像 李华