
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 CustomLatencyprometheus 配置- job_name: kong static_configs: - targets: [127.0.0.1:2001] labels: instance_service_name: kongGrafana 配置{ 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 }