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) |