Software / code / prosody
Comparison
util/openmetrics.lua @ 11929:85d51bfcf56b
mod_http_openmetrics: Imported from prosody-modules mod_prometheus @df2246b15075
This version has several changes from the earlier mod_prometheus:
- Conversion of metrics into the text-based OpenMetrics format is moved to
util.openmetrics
- Support for IP-based access control
- Compatibility with earlier Prosody versions removed
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Wed, 24 Nov 2021 16:03:05 +0000 |
| parent | 11600:a02c277eb97a |
| child | 12387:05c250fa335a |
comparison
equal
deleted
inserted
replaced
| 11928:16cf863b36c0 | 11929:85d51bfcf56b |
|---|---|
| 23 local select = select; | 23 local select = select; |
| 24 local array = require "util.array"; | 24 local array = require "util.array"; |
| 25 local log = require "util.logger".init("util.openmetrics"); | 25 local log = require "util.logger".init("util.openmetrics"); |
| 26 local new_multitable = require "util.multitable".new; | 26 local new_multitable = require "util.multitable".new; |
| 27 local iter_multitable = require "util.multitable".iter; | 27 local iter_multitable = require "util.multitable".iter; |
| 28 local t_concat, t_insert = table.concat, table.insert; | |
| 28 local t_pack, t_unpack = require "util.table".pack, table.unpack or unpack; --luacheck: ignore 113/unpack | 29 local t_pack, t_unpack = require "util.table".pack, table.unpack or unpack; --luacheck: ignore 113/unpack |
| 29 | 30 |
| 30 -- BEGIN of Utility: "metric proxy" | 31 -- BEGIN of Utility: "metric proxy" |
| 31 -- This allows to wrap a MetricFamily in a proxy which only provides the | 32 -- This allows to wrap a MetricFamily in a proxy which only provides the |
| 32 -- `with_labels` and `with_partial_label` methods. This allows to pre-set one | 33 -- `with_labels` and `with_partial_label` methods. This allows to pre-set one |
| 49 end | 50 end |
| 50 } | 51 } |
| 51 end | 52 end |
| 52 | 53 |
| 53 -- END of Utility: "metric proxy" | 54 -- END of Utility: "metric proxy" |
| 55 | |
| 56 -- BEGIN Rendering helper functions (internal) | |
| 57 | |
| 58 local function escape(text) | |
| 59 return text:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n"); | |
| 60 end | |
| 61 | |
| 62 local function escape_name(name) | |
| 63 return name:gsub("/", "__"):gsub("[^A-Za-z0-9_]", "_"):gsub("^[^A-Za-z_]", "_%1"); | |
| 64 end | |
| 65 | |
| 66 local function repr_help(metric, docstring) | |
| 67 docstring = docstring:gsub("\\", "\\\\"):gsub("\n", "\\n"); | |
| 68 return "# HELP "..escape_name(metric).." "..docstring.."\n"; | |
| 69 end | |
| 70 | |
| 71 local function repr_unit(metric, unit) | |
| 72 if not unit then | |
| 73 unit = "" | |
| 74 else | |
| 75 unit = unit:gsub("\\", "\\\\"):gsub("\n", "\\n"); | |
| 76 end | |
| 77 return "# UNIT "..escape_name(metric).." "..unit.."\n"; | |
| 78 end | |
| 79 | |
| 80 -- local allowed_types = { counter = true, gauge = true, histogram = true, summary = true, untyped = true }; | |
| 81 -- local allowed_types = { "counter", "gauge", "histogram", "summary", "untyped" }; | |
| 82 local function repr_type(metric, type_) | |
| 83 -- if not allowed_types:contains(type_) then | |
| 84 -- return; | |
| 85 -- end | |
| 86 return "# TYPE "..escape_name(metric).." "..type_.."\n"; | |
| 87 end | |
| 88 | |
| 89 local function repr_label(key, value) | |
| 90 return key.."=\""..escape(value).."\""; | |
| 91 end | |
| 92 | |
| 93 local function repr_labels(labelkeys, labelvalues, extra_labels) | |
| 94 local values = {} | |
| 95 if labelkeys then | |
| 96 for i, key in ipairs(labelkeys) do | |
| 97 local value = labelvalues[i] | |
| 98 t_insert(values, repr_label(escape_name(key), escape(value))); | |
| 99 end | |
| 100 end | |
| 101 if extra_labels then | |
| 102 for key, value in pairs(extra_labels) do | |
| 103 t_insert(values, repr_label(escape_name(key), escape(value))); | |
| 104 end | |
| 105 end | |
| 106 if #values == 0 then | |
| 107 return ""; | |
| 108 end | |
| 109 return "{"..t_concat(values, ",").."}"; | |
| 110 end | |
| 111 | |
| 112 local function repr_sample(metric, labelkeys, labelvalues, extra_labels, value) | |
| 113 return escape_name(metric)..repr_labels(labelkeys, labelvalues, extra_labels).." "..string.format("%.17g", value).."\n"; | |
| 114 end | |
| 115 | |
| 116 -- END Rendering helper functions (internal) | |
| 54 | 117 |
| 55 local function render_histogram_le(v) | 118 local function render_histogram_le(v) |
| 56 if v == 1/0 then | 119 if v == 1/0 then |
| 57 -- I-D-00: 4.1.2.2.1: | 120 -- I-D-00: 4.1.2.2.1: |
| 58 -- Exposers MUST produce output for positive infinity as +Inf. | 121 -- Exposers MUST produce output for positive infinity as +Inf. |
| 284 | 347 |
| 285 function metric_registry_mt:get_metric_families() | 348 function metric_registry_mt:get_metric_families() |
| 286 return self.families | 349 return self.families |
| 287 end | 350 end |
| 288 | 351 |
| 352 function metric_registry_mt:render() | |
| 353 local answer = {}; | |
| 354 for metric_family_name, metric_family in pairs(self:get_metric_families()) do | |
| 355 t_insert(answer, repr_help(metric_family_name, metric_family.description)) | |
| 356 t_insert(answer, repr_unit(metric_family_name, metric_family.unit)) | |
| 357 t_insert(answer, repr_type(metric_family_name, metric_family.type_)) | |
| 358 for labelset, metric in metric_family:iter_metrics() do | |
| 359 for suffix, extra_labels, value in metric:iter_samples() do | |
| 360 t_insert(answer, repr_sample(metric_family_name..suffix, metric_family.label_keys, labelset, extra_labels, value)) | |
| 361 end | |
| 362 end | |
| 363 end | |
| 364 t_insert(answer, "# EOF\n") | |
| 365 return t_concat(answer, ""); | |
| 366 end | |
| 367 | |
| 289 -- END of MetricRegistry implementation | 368 -- END of MetricRegistry implementation |
| 290 | 369 |
| 291 -- BEGIN of general helpers for implementing high-level APIs on top of OpenMetrics | 370 -- BEGIN of general helpers for implementing high-level APIs on top of OpenMetrics |
| 292 | 371 |
| 293 local function timed(metric) | 372 local function timed(metric) |