mod_prometheus/mod_prometheus.lua
changeset 3135 ddd39ca7b953
parent 3132 a34e7bd87b39
child 3136 4ef28b6b4e87
equal deleted inserted replaced
3134:c47cd8dbd310 3135:ddd39ca7b953
     6 
     6 
     7 module:set_global();
     7 module:set_global();
     8 module:depends "http";
     8 module:depends "http";
     9 
     9 
    10 local tostring = tostring;
    10 local tostring = tostring;
    11 local s_format = string.format;
       
    12 local t_insert = table.insert;
    11 local t_insert = table.insert;
    13 local t_concat = table.concat;
    12 local t_concat = table.concat;
    14 local socket = require "socket";
    13 local socket = require "socket";
    15 local mt = require "util.multitable";
       
    16 
    14 
    17 local meta = mt.new(); meta.data = module:shared"meta";
    15 local data = {};
    18 local data = mt.new(); data.data = module:shared"data";
       
    19 
    16 
    20 local function escape(text)
    17 local function escape(text)
    21 	return text:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n");
    18 	return text:gsub("\\", "\\\\"):gsub("\"", "\\\""):gsub("\n", "\\n");
    22 end
    19 end
    23 
    20 
    63 	return escape_name(metric)..repr_labels(labels).." "..value.." "..timestamp.."\n";
    60 	return escape_name(metric)..repr_labels(labels).." "..value.." "..timestamp.."\n";
    64 end
    61 end
    65 
    62 
    66 module:hook("stats-updated", function (event)
    63 module:hook("stats-updated", function (event)
    67 	local all_stats, this = event.stats_extra;
    64 	local all_stats, this = event.stats_extra;
    68 	local host, sect, name, typ, key;
    65 	local host, sect, name, typ;
    69 	for stat, value in pairs(event.changed_stats) do
    66 	data = {};
       
    67 	for stat, value in pairs(event.stats) do
    70 		this = all_stats[stat];
    68 		this = all_stats[stat];
    71 		-- module:log("debug", "changed_stats[%q] = %s", stat, tostring(value));
    69 		-- module:log("debug", "changed_stats[%q] = %s", stat, tostring(value));
    72 		host, sect, name, typ = stat:match("^/([^/]+)/([^/]+)/(.+):(%a+)$");
    70 		host, sect, name, typ = stat:match("^/([^/]+)/([^/]+)/(.+):(%a+)$");
    73 		if host == nil then
    71 		if host == nil then
    74 			sect, name, typ, host = stat:match("^([^.]+)%.([^:]+):(%a+)$");
    72 			sect, name, typ = stat:match("^([^.]+)%.(.+):(%a+)$");
    75 		elseif host == "*" then
    73 		elseif host == "*" then
    76 			host = nil;
    74 			host = nil;
    77 		end
    75 		end
    78 		if sect:find("^mod_measure_.") then
    76 		if sect:find("^mod_measure_.") then
    79 			sect = sect:sub(13);
    77 			sect = sect:sub(13);
    80 		elseif sect:find("^mod_statistics_.") then
    78 		elseif sect:find("^mod_statistics_.") then
    81 			sect = sect:sub(16);
    79 			sect = sect:sub(16);
    82 		end
    80 		end
    83 		key = escape_name(s_format("%s_%s_%s", host or "global", sect, typ));
       
    84 
    81 
    85 		if not meta:get(key) then
    82 		local key = escape_name("prosody_"..sect.."_"..name);
    86 			if host then
    83 		local field = {
    87 				meta:set(key, "", "graph_title", s_format("%s %s on %s", sect, typ, host));
    84 			value = value,
    88 			else
    85 			labels = {},
    89 				meta:set(key, "", "graph_title", s_format("Global %s %s", sect, typ, host));
    86 			-- TODO: Use the other types where it makes sense.
    90 			end
    87 			typ = (typ == "rate" and "counter" or "gauge"),
    91 			meta:set(key, "", "graph_vlabel", this and this.units or typ);
    88 		};
    92 			meta:set(key, "", "graph_category", sect);
    89 		if host then
    93 
    90 			field.labels.host = host;
    94 			meta:set(key, name, "label", name);
       
    95 		elseif not meta:get(key, name, "label") then
       
    96 			meta:set(key, name, "label", name);
       
    97 		end
    91 		end
    98 
    92 		if data[key] == nil then
    99 		data:set(key, name, value);
    93 			data[key] = {};
       
    94 		end
       
    95 		t_insert(data[key], field);
   100 	end
    96 	end
   101 end);
    97 end);
   102 
    98 
   103 local function get_metrics(event)
    99 local function get_metrics(event)
   104 	local response = event.response;
   100 	local response = event.response;
   105 	response.headers.content_type = "text/plain; version=0.4.4";
   101 	response.headers.content_type = "text/plain; version=0.4.4";
   106 
   102 
   107 	local answer = {};
   103 	local answer = {};
   108 	local timestamp = tostring(get_timestamp());
   104 	local timestamp = tostring(get_timestamp());
   109 	for section, content in pairs(data.data) do
   105 	for key, fields in pairs(data) do
   110 		for key, value in pairs(content) do
   106 		t_insert(answer, repr_help(key, "TODO: add a description here."));
   111 			local name = "prosody_"..section.."_"..key;
   107 		t_insert(answer, repr_type(key, fields[1].typ));
   112 			t_insert(answer, repr_help(name, "TODO: add a description here."));
   108 		for _, field in pairs(fields) do
   113 			t_insert(answer, repr_type(name, "gauge"));
   109 			t_insert(answer, repr_sample(key, field.labels, field.value, timestamp));
   114 			t_insert(answer, repr_sample(name, {}, value, timestamp));
       
   115 		end
   110 		end
   116 	end
   111 	end
   117 	return t_concat(answer, "");
   112 	return t_concat(answer, "");
   118 end
   113 end
   119 
   114