X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util%2Fstatistics.lua;h=263550265483516f4dddabdf523dffd60bed4cc8;hb=127df5431789381b960207d7c853df2a4f1b9cc9;hp=9d3320532e6ddc67c19486a4f33a22e2f86cdf56;hpb=9f08698ae41959c5708037545c51d3ab9aa0d4a8;p=prosody.git diff --git a/util/statistics.lua b/util/statistics.lua index 9d332053..26355026 100644 --- a/util/statistics.lua +++ b/util/statistics.lua @@ -8,7 +8,7 @@ local function percentile(arr, length, pc) local n = pc/100 * (length + 1); local k, d = m_floor(n), n%1; if k == 0 then - return arr[1]; + return arr[1] or 0; elseif k >= length then return arr[length]; end @@ -20,24 +20,45 @@ local function new_registry(config) local duration_sample_interval = config.duration_sample_interval or 5; local duration_max_samples = config.duration_max_stored_samples or 5000; + local function get_distribution_stats(events, n_actual_events, since, new_time, units) + local n_stored_events = #events; + t_sort(events); + local sum = 0; + for i = 1, n_stored_events do + sum = sum + events[i]; + end + + return { + samples = events; + sample_count = n_stored_events; + count = n_actual_events, + rate = n_actual_events/(new_time-since); + average = n_stored_events > 0 and sum/n_stored_events or 0, + min = events[1] or 0, + max = events[n_stored_events] or 0, + units = units, + }; + end + + local registry = {}; local methods; methods = { amount = function (name, initial) local v = initial or 0; - registry[name] = function () return "amount", v; end + registry[name..":amount"] = function () return "amount", v; end return function (new_v) v = new_v; end end; counter = function (name, initial) local v = initial or 0; - registry[name] = function () return "amount", v; end + registry[name..":amount"] = function () return "amount", v; end return function (delta) v = v + delta; end; end; rate = function (name) local since, n = time(), 0; - registry[name] = function () + registry[name..":rate"] = function () local t = time(); local stats = { rate = n/(t-since); @@ -50,41 +71,49 @@ local function new_registry(config) n = n + 1; end; end; - duration = function (name) + distribution = function (name, unit, type) + type = type or "distribution"; local events, last_event = {}, 0; local n_actual_events = 0; local since = time(); - registry[name] = function () - local n_stored_events = #events; - t_sort(events); - local sum = 0; - for i = 1, n_stored_events do - sum = sum + events[i]; - end - + registry[name..":"..type] = function () local new_time = time(); + local stats = get_distribution_stats(events, n_actual_events, since, new_time, unit); + events, last_event = {}, 0; + n_actual_events = 0; + since = new_time; + return type, stats.average, stats; + end; - local stats = { - samples = events; - sample_count = n_stored_events; - count = n_actual_events, - rate = n_actual_events/(new_time-since); - average = n_stored_events > 0 and sum/n_stored_events or 0, - min = events[1], - max = events[n_stored_events], - }; + return function (value) + n_actual_events = n_actual_events + 1; + if n_actual_events%duration_sample_interval == 1 then + last_event = (last_event%duration_max_samples) + 1; + events[last_event] = value; + end + end; + end; + sizes = function (name) + return methods.distribution(name, "bytes", "size"); + end; + times = function (name) + local events, last_event = {}, 0; + local n_actual_events = 0; + local since = time(); + registry[name..":duration"] = function () + local new_time = time(); + local stats = get_distribution_stats(events, n_actual_events, since, new_time, "seconds"); events, last_event = {}, 0; n_actual_events = 0; since = new_time; - return "duration", stats.average, stats; end; return function () n_actual_events = n_actual_events + 1; - if n_actual_events%duration_sample_interval > 0 then + if n_actual_events%duration_sample_interval ~= 1 then return nop_function; end @@ -111,7 +140,7 @@ return { n_buckets = n_buckets or 100; local events, n_events = duration.samples, duration.sample_count; if not (events and n_events) then - return nil, "not a valid duration stat"; + return nil, "not a valid distribution stat"; end local histogram = {}; @@ -124,7 +153,7 @@ return { get_percentile = function (duration, pc) local events, n_events = duration.samples, duration.sample_count; if not (events and n_events) then - return nil, "not a valid duration stat"; + return nil, "not a valid distribution stat"; end return percentile(events, n_events, pc); end;