From 7f7ff9f23778f5465fafc01687041d0f6bfdcd5f Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:06:28 +0800 Subject: [PATCH 01/15] metric_data with string.buffer --- kong/plugins/prometheus/prometheus.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index 0f8685ed3b0..88d61ee6be3 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -90,6 +90,9 @@ local TYPE_LITERAL = { -- Default metric name size for string.buffer.new() local NAME_BUFFER_SIZE_HINT = 256 +-- Default metric data size for string.buffer.new() +local DATA_BUFFER_SIZE_HINT = 4096 + -- Default name for error metric incremented by this library. local DEFAULT_ERROR_METRIC_NAME = "nginx_metric_errors_total" @@ -913,19 +916,19 @@ function Prometheus:metric_data(write_fn, local_only) table_sort(keys) local seen_metrics = {} - local output = {} + + local output = buffer.new(DATA_BUFFER_SIZE_HINT) local output_count = 0 local function buffered_print(data) if data then output_count = output_count + 1 - output[output_count] = data + output:put(data) end if output_count >= 100 or not data then - write_fn(output) + write_fn(output:get()) -- cosume the whole buffer output_count = 0 - tb_clear(output) end end From 889140073ac41215ccf29c40822d5ef75c120a8a Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:11:22 +0800 Subject: [PATCH 02/15] printable_metric_data in api.lua --- kong/plugins/prometheus/api.lua | 9 ++++----- kong/plugins/prometheus/prometheus.lua | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/kong/plugins/prometheus/api.lua b/kong/plugins/prometheus/api.lua index bf3e27d3ade..f73d03bc586 100644 --- a/kong/plugins/prometheus/api.lua +++ b/kong/plugins/prometheus/api.lua @@ -1,17 +1,16 @@ +local buffer = require("string.buffer") local exporter = require "kong.plugins.prometheus.exporter" -local tbl_insert = table.insert -local tbl_concat = table.concat local printable_metric_data = function(_) - local buffer = {} + local buf = buffer.new(4096) -- override write_fn, since stream_api expect response to returned -- instead of ngx.print'ed exporter.metric_data(function(new_metric_data) - tbl_insert(buffer, tbl_concat(new_metric_data, "")) + buf:put(new_metric_data) end) - return tbl_concat(buffer, "") + return buf:get() end diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index 88d61ee6be3..e9b4e9e12cb 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -70,7 +70,6 @@ local tostring = tostring local tonumber = tonumber local st_format = string.format local table_sort = table.sort -local tb_clear = require("table.clear") local yield = require("kong.tools.utils").yield @@ -917,6 +916,7 @@ function Prometheus:metric_data(write_fn, local_only) local seen_metrics = {} + -- the output is an integral string, not an array any more local output = buffer.new(DATA_BUFFER_SIZE_HINT) local output_count = 0 From e89bf62530a03b9ac661690bc1119406ba0b1ce8 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:18:55 +0800 Subject: [PATCH 03/15] seen_metrics --- kong/plugins/prometheus/prometheus.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index e9b4e9e12cb..f4e12933b29 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -70,6 +70,7 @@ local tostring = tostring local tonumber = tonumber local st_format = string.format local table_sort = table.sort +local tb_new = require("table.new") local yield = require("kong.tools.utils").yield @@ -914,7 +915,7 @@ function Prometheus:metric_data(write_fn, local_only) -- numerical order of their label values. table_sort(keys) - local seen_metrics = {} + local seen_metrics = tb_new(0, count) -- the output is an integral string, not an array any more local output = buffer.new(DATA_BUFFER_SIZE_HINT) From 6da9c7b7d18cb6a6382ed71fce2097aa9577acab Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:23:25 +0800 Subject: [PATCH 04/15] buffer:putf --- kong/plugins/prometheus/prometheus.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index f4e12933b29..435b4a5842e 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -921,10 +921,10 @@ function Prometheus:metric_data(write_fn, local_only) local output = buffer.new(DATA_BUFFER_SIZE_HINT) local output_count = 0 - local function buffered_print(data) + local function buffered_print(data, ...) if data then output_count = output_count + 1 - output:put(data) + output:putf(data, ...) end if output_count >= 100 or not data then @@ -954,12 +954,12 @@ function Prometheus:metric_data(write_fn, local_only) local m = self.registry[short_name] if m then if m.help then - buffered_print(st_format("# HELP %s%s %s\n", - self.prefix, short_name, m.help)) + buffered_print("# HELP %s%s %s\n", + self.prefix, short_name, m.help) end if m.typ then - buffered_print(st_format("# TYPE %s%s %s\n", - self.prefix, short_name, TYPE_LITERAL[m.typ])) + buffered_print("# TYPE %s%s %s\n", + self.prefix, short_name, TYPE_LITERAL[m.typ]) end end seen_metrics[short_name] = true @@ -967,7 +967,7 @@ function Prometheus:metric_data(write_fn, local_only) if not is_local_metrics then -- local metrics is always a gauge key = fix_histogram_bucket_labels(key) end - buffered_print(st_format("%s%s %s\n", self.prefix, key, value)) + buffered_print("%s%s %s\n", self.prefix, key, value) ::continue:: From e5520e5c50f4f3de46182c3990d1b5a60f13cf45 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:40:49 +0800 Subject: [PATCH 05/15] st_format --- kong/plugins/prometheus/prometheus.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index 435b4a5842e..bc8ee0f5b69 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -305,7 +305,7 @@ local function construct_bucket_format(buckets) for _, bucket in ipairs(buckets) do assert(type(bucket) == "number", "bucket boundaries should be numeric") -- floating point number with all trailing zeros removed - local as_string = string.format("%f", bucket):gsub("0*$", "") + local as_string = st_format("%f", bucket):gsub("0*$", "") local dot_idx = as_string:find(".", 1, true) max_order = math.max(max_order, dot_idx - 1) max_precision = math.max(max_precision, as_string:len() - dot_idx) @@ -364,7 +364,7 @@ local function lookup_or_create(self, label_values) local cnt = label_values and #label_values or 0 -- specially, if first element is nil, # will treat it as "non-empty" if cnt ~= self.label_count or (self.label_count > 0 and label_values[1] == nil) then - return nil, string.format("inconsistent labels count, expected %d, got %d", + return nil, st_format("inconsistent labels count, expected %d, got %d", self.label_count, cnt) end local t = self.lookup @@ -408,13 +408,13 @@ local function lookup_or_create(self, label_values) end for i, buc in ipairs(self.buckets) do - full_name[i+2] = string.format("%sle=\"%s\"}", bucket_pref, self.bucket_format:format(buc)) + full_name[i+2] = st_format("%sle=\"%s\"}", bucket_pref, self.bucket_format:format(buc)) end -- Last bucket. Note, that the label value is "Inf" rather than "+Inf" -- required by Prometheus. This is necessary for this bucket to be the last -- one when all metrics are lexicographically sorted. "Inf" will get replaced -- by "+Inf" in Prometheus:metric_data(). - full_name[self.bucket_count+3] = string.format("%sle=\"Inf\"}", bucket_pref) + full_name[self.bucket_count+3] = st_format("%sle=\"Inf\"}", bucket_pref) else full_name = full_metric_name(self.name, self.label_names, label_values) end From 97eab6de86a9176e9c0ffea2c2049b018fb491a2 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:46:00 +0800 Subject: [PATCH 06/15] param fmt --- kong/plugins/prometheus/prometheus.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index bc8ee0f5b69..f3becba740c 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -921,13 +921,13 @@ function Prometheus:metric_data(write_fn, local_only) local output = buffer.new(DATA_BUFFER_SIZE_HINT) local output_count = 0 - local function buffered_print(data, ...) - if data then + local function buffered_print(fmt, ...) + if fmt then output_count = output_count + 1 - output:putf(data, ...) + output:putf(fmt, ...) end - if output_count >= 100 or not data then + if output_count >= 100 or not fmt then write_fn(output:get()) -- cosume the whole buffer output_count = 0 end From fcc35b51e271c01275b71d05638a8213532b4aed Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 09:48:06 +0800 Subject: [PATCH 07/15] dont use iparis --- kong/plugins/prometheus/prometheus.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index f3becba740c..e443f50d407 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -933,9 +933,11 @@ function Prometheus:metric_data(write_fn, local_only) end end - for _, key in ipairs(keys) do + for i = 1, count do yield() + key = keys[i] + local value, err local is_local_metrics = true value = self.local_metrics[key] From 65a9617f61161546c9c738d2c41c8c3ea213b9fa Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 10:07:29 +0800 Subject: [PATCH 08/15] string.sub with -2 --- kong/plugins/prometheus/prometheus.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index e443f50d407..f57da6d86aa 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -402,7 +402,7 @@ local function lookup_or_create(self, label_values) local bucket_pref if self.label_count > 0 then -- strip last } - bucket_pref = self.name .. "_bucket" .. string.sub(labels, 1, #labels-1) .. "," + bucket_pref = self.name .. "_bucket" .. string.sub(labels, 1, -2) .. "," else bucket_pref = self.name .. "_bucket{" end From 25de6f366bd220200ad6951bbb79eacd88e8a12f Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 10:08:21 +0800 Subject: [PATCH 09/15] ngx.get_phase --- kong/plugins/prometheus/prometheus.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index f57da6d86aa..e9ba5119b36 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -704,8 +704,9 @@ end -- Returns: -- an object that should be used to register metrics. function Prometheus.init(dict_name, options_or_prefix) - if ngx.get_phase() ~= 'init' and ngx.get_phase() ~= 'init_worker' and - ngx.get_phase() ~= 'timer' then + local phase = ngx.get_phase() + if phase ~= 'init' and phase ~= 'init_worker' and + phase ~= 'timer' then error('Prometheus.init can only be called from ' .. 'init_by_lua_block, init_worker_by_lua_block or timer' , 2) end From 83abc7adfa3d3c7b7ae03cd2a93ec85c24acde3f Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 10:12:34 +0800 Subject: [PATCH 10/15] ngx.shared[shm] --- kong/plugins/prometheus/exporter.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/exporter.lua b/kong/plugins/prometheus/exporter.lua index 358d7597ce4..40a45a6b685 100644 --- a/kong/plugins/prometheus/exporter.lua +++ b/kong/plugins/prometheus/exporter.lua @@ -90,7 +90,7 @@ end local function init() local shm = "prometheus_metrics" - if not ngx.shared.prometheus_metrics then + if not ngx.shared[shm] then kong.log.err("prometheus: ngx shared dict 'prometheus_metrics' not found") return end From 2eb32398356d7a747dbc1a9894947544bf58ef87 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 10:14:00 +0800 Subject: [PATCH 11/15] lint fix --- kong/plugins/prometheus/prometheus.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index e9ba5119b36..60872f4a522 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -937,7 +937,7 @@ function Prometheus:metric_data(write_fn, local_only) for i = 1, count do yield() - key = keys[i] + local key = keys[i] local value, err local is_local_metrics = true From 250e372b0a5f539658c60892815a9f232c2a850c Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 10:26:36 +0800 Subject: [PATCH 12/15] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a598d51bd47..d068a65551d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ - The Prometheus plugin has been optimized to reduce proxy latency impacts during scraping. [#10949](https://github.com/Kong/kong/pull/10949) [#11040](https://github.com/Kong/kong/pull/11040) + [#11065](https://github.com/Kong/kong/pull/11065) ### Fixes From 29b9ded5b1c9934a0b7be051fb78ed0fa748c706 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 13:41:25 +0800 Subject: [PATCH 13/15] remove st_format --- kong/plugins/prometheus/prometheus.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index 60872f4a522..1757a2c7c85 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -68,7 +68,6 @@ local ipairs = ipairs local pairs = pairs local tostring = tostring local tonumber = tonumber -local st_format = string.format local table_sort = table.sort local tb_new = require("table.new") local yield = require("kong.tools.utils").yield @@ -305,7 +304,7 @@ local function construct_bucket_format(buckets) for _, bucket in ipairs(buckets) do assert(type(bucket) == "number", "bucket boundaries should be numeric") -- floating point number with all trailing zeros removed - local as_string = st_format("%f", bucket):gsub("0*$", "") + local as_string = string.format("%f", bucket):gsub("0*$", "") local dot_idx = as_string:find(".", 1, true) max_order = math.max(max_order, dot_idx - 1) max_precision = math.max(max_precision, as_string:len() - dot_idx) @@ -364,7 +363,7 @@ local function lookup_or_create(self, label_values) local cnt = label_values and #label_values or 0 -- specially, if first element is nil, # will treat it as "non-empty" if cnt ~= self.label_count or (self.label_count > 0 and label_values[1] == nil) then - return nil, st_format("inconsistent labels count, expected %d, got %d", + return nil, string.format("inconsistent labels count, expected %d, got %d", self.label_count, cnt) end local t = self.lookup @@ -408,13 +407,13 @@ local function lookup_or_create(self, label_values) end for i, buc in ipairs(self.buckets) do - full_name[i+2] = st_format("%sle=\"%s\"}", bucket_pref, self.bucket_format:format(buc)) + full_name[i+2] = string.format("%sle=\"%s\"}", bucket_pref, self.bucket_format:format(buc)) end -- Last bucket. Note, that the label value is "Inf" rather than "+Inf" -- required by Prometheus. This is necessary for this bucket to be the last -- one when all metrics are lexicographically sorted. "Inf" will get replaced -- by "+Inf" in Prometheus:metric_data(). - full_name[self.bucket_count+3] = st_format("%sle=\"Inf\"}", bucket_pref) + full_name[self.bucket_count+3] = string.format("%sle=\"Inf\"}", bucket_pref) else full_name = full_metric_name(self.name, self.label_names, label_values) end From 1bc473dc6912071ef1873a91b273fd1b225a2bb2 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 14 Jun 2023 13:43:42 +0800 Subject: [PATCH 14/15] typo fix --- kong/plugins/prometheus/prometheus.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index 1757a2c7c85..a04805b16af 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -928,7 +928,7 @@ function Prometheus:metric_data(write_fn, local_only) end if output_count >= 100 or not fmt then - write_fn(output:get()) -- cosume the whole buffer + write_fn(output:get()) -- consume the whole buffer output_count = 0 end end From 44899311bcadf144161b6d0b7ba432d708be6d40 Mon Sep 17 00:00:00 2001 From: chronolaw Date: Wed, 21 Jun 2023 10:39:11 +0800 Subject: [PATCH 15/15] buffer free --- kong/plugins/prometheus/api.lua | 6 +++++- kong/plugins/prometheus/prometheus.lua | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/kong/plugins/prometheus/api.lua b/kong/plugins/prometheus/api.lua index f73d03bc586..72762bfe034 100644 --- a/kong/plugins/prometheus/api.lua +++ b/kong/plugins/prometheus/api.lua @@ -10,7 +10,11 @@ local printable_metric_data = function(_) buf:put(new_metric_data) end) - return buf:get() + local str = buf:get() + + buf:free() + + return str end diff --git a/kong/plugins/prometheus/prometheus.lua b/kong/plugins/prometheus/prometheus.lua index a04805b16af..e837de1cdc3 100644 --- a/kong/plugins/prometheus/prometheus.lua +++ b/kong/plugins/prometheus/prometheus.lua @@ -976,6 +976,8 @@ function Prometheus:metric_data(write_fn, local_only) end buffered_print(nil) + + output:free() end -- Present all metrics in a text format compatible with Prometheus.