Skip to content
This repository has been archived by the owner on Aug 7, 2021. It is now read-only.

feat(exporter) add url location and GET param counters, with regex extract #116

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,18 @@ kong_bandwidth{type="ingress",service="google"} 254
# HELP kong_datastore_reachable Datastore reachable from Kong, 0 is unreachable
# TYPE kong_datastore_reachable gauge
kong_datastore_reachable 1
# HELP kong_http_consumer_status HTTP status codes for customer per service/route in Kong
# TYPE kong_http_consumer_status counter
kong_http_consumer_status{service="upstream",route="default",code="200",consumer="consumer1"} 5185
# HELP kong_http_status HTTP status codes per service in Kong
# TYPE kong_http_status counter
kong_http_status{code="301",service="google"} 2
# HELP kong_http_url_location_consumer_total HTTP status codes for specific URL location in Kong
# TYPE kong_http_url_location_consumer_total counter
kong_http_url_location_consumer_total{service="upstream",route="default",location="hello",consumer="consumer1"} 5
# HELP kong_http_url_param_consumer_total HTTP status codes for specific GET param in Kong
# TYPE kong_http_url_param_consumer_total counter
kong_http_url_param_consumer_total{service="upstream",route="default",param="123456",consumer="consumer1"} 5
# HELP kong_latency Latency added by Kong, total request time and upstream latency for each service in Kong
# TYPE kong_latency histogram
kong_latency_bucket{type="kong",service="google",le="00001.0"} 1
Expand Down
98 changes: 97 additions & 1 deletion kong/plugins/prometheus/exporter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,27 @@ local function init()
"Total bandwidth in bytes " ..
"consumed per service/route in Kong",
{"service", "route", "type"})
metrics.consumer_status = prometheus:counter("http_consumer_status",
"HTTP status codes for customer per service/route in Kong",
{"service", "route", "code", "consumer"})

-- per location / url param
metrics.param_total = prometheus:counter("http_url_param_total",
"HTTP status codes for specific GET param in Kong",
{"service", "route", "param"})

metrics.param_consumer_total = prometheus:counter("http_url_param_consumer_total",
"HTTP status codes for specific GET param in Kong",
{"service", "route", "param", "consumer"})

metrics.location_total = prometheus:counter("http_url_location_total",
"HTTP status codes for specific URL location in Kong",
{"service", "route", "location"})

metrics.location_consumer_total = prometheus:counter("http_url_location_consumer_total",
"HTTP status codes for specific URL location in Kong",
{"service", "route", "location", "consumer"})

if enterprise then
enterprise.init(prometheus)
end
Expand All @@ -92,6 +113,7 @@ end
-- Since in the prometheus library we create a new table for each diverged label
-- so putting the "more dynamic" label at the end will save us some memory
local labels_table = {0, 0, 0}
local labels_table4 = {0, 0, 0, 0}
local upstream_target_addr_health_table = {
{ value = 0, labels = { 0, 0, 0, "healthchecks_off" } },
{ value = 0, labels = { 0, 0, 0, "healthy" } },
Expand All @@ -113,7 +135,7 @@ end
local log

if ngx.config.subsystem == "http" then
function log(message)
function log(message, serialized)
if not metrics then
kong.log.err("prometheus: can not log metrics because of an initialization "
.. "error, please make sure that you've declared "
Expand Down Expand Up @@ -168,6 +190,80 @@ if ngx.config.subsystem == "http" then
labels_table[3] = "kong"
metrics.latency:observe(kong_proxy_latency, labels_table)
end

if serialized.consumer ~= nil then
labels_table4[1] = labels_table[1]
labels_table4[2] = labels_table[2]
labels_table4[3] = message.response.status
labels_table4[4] = serialized.consumer
metrics.consumer_status:inc(1, labels_table4)
end

if serialized.param_list then
local value
local args, err = ngx.req.get_uri_args()
for _, param in ipairs(serialized.param_list) do
if args[param] ~= nil and type(args[param]) ~= 'table' then
value = args[param]
break
end
end

if value ~= nil then
if serialized.param_extract ~= nil then
local match, err = ngx.re.match(value, serialized.param_extract, 'aio')
if err then
kong.log.err("prometheus: failed to extract param value becase of a regex error - " .. err)
value = nil
elseif match == nil or (not match[1] and not match['param']) then
value = nil
elseif match['param'] then
value = match['param']
else
value = match[1]
end
end

if value ~= nil then
if serialized.consumer ~= nil then
labels_table4[3] = value
labels_table4[4] = serialized.consumer
metrics.param_consumer_total:inc(1, labels_table4)
else
labels_table[3] = value
metrics.param_total:inc(1, labels_table)
end
end
end
end

if serialized.location then
local value = ngx.var.uri
if serialized.location_extract ~= nil then
local match, err = ngx.re.match(value, serialized.location_extract, 'aio')
if err then
kong.log.err("prometheus: failed to extract location portion becase of a regex error - " .. err)
value = nil
elseif match == nil or (not match[1] and not match['location']) then
value = nil
elseif match['location'] then
value = match['location']
else
value = match[1]
end
end

if value ~= nil then
if serialized.consumer ~= nil then
labels_table4[3] = value
labels_table4[4] = serialized.consumer
metrics.location_consumer_total:inc(1, labels_table4)
else
labels_table[3] = value
metrics.location_total:inc(1, labels_table)
end
end
end
end

else
Expand Down
15 changes: 13 additions & 2 deletions kong/plugins/prometheus/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,20 @@ function PrometheusHandler.init_worker()
end


function PrometheusHandler.log()
function PrometheusHandler.log(self, conf)
local message = kong.log.serialize()
prometheus.log(message)

local serialized = {
param_list = conf.param_collect_list,
param_extract = conf.param_value_extract,
location = conf.location_collect,
location_extract = conf.location_extract,
}
if conf.per_consumer and message.consumer ~= nil then
serialized.consumer = message.consumer.username
end

prometheus.log(message, serialized)
end


Expand Down
8 changes: 7 additions & 1 deletion kong/plugins/prometheus/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ return {
fields = {
{ config = {
type = "record",
fields = {},
fields = {
{ param_collect_list = { type = "array", elements = { type = "string", match = "^[a-z_]+$" }, }, },
{ param_value_extract = { type = "string" }, }, -- regex
{ location_collect = { type = "boolean", default = false }, },
{ location_extract = { type = "string" }, }, -- regex
{ per_consumer = { type = "boolean", default = false }, },
},
custom_validator = validate_shared_dict,
}, },
},
Expand Down