Software /
code /
prosody
Comparison
core/statsmanager.lua @ 7533:4ef37ac69562
statsmanager: Refactor to simplify logic. Notably renames 'statistics_provider' to 'statistics', and external libs now just begin with ':'
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 29 Jul 2016 13:20:02 +0100 |
parent | 7524:b6f32bb3b584 |
child | 7664:4f145a9f1477 |
comparison
equal
deleted
inserted
replaced
7531:2db68d1a6eeb | 7533:4ef37ac69562 |
---|---|
2 local config = require "core.configmanager"; | 2 local config = require "core.configmanager"; |
3 local log = require "util.logger".init("stats"); | 3 local log = require "util.logger".init("stats"); |
4 local timer = require "util.timer"; | 4 local timer = require "util.timer"; |
5 local fire_event = prosody.events.fire_event; | 5 local fire_event = prosody.events.fire_event; |
6 | 6 |
7 local stats_config = config.get("*", "statistics_interval"); | 7 local stats_interval_config = config.get("*", "statistics_interval"); |
8 local stats_interval = tonumber(stats_config); | 8 local stats_interval = tonumber(stats_interval_config); |
9 if stats_config and not stats_interval then | 9 if stats_config and not stats_interval then |
10 log("error", "Invalid 'statistics_interval' setting, statistics will be disabled"); | 10 log("error", "Invalid 'statistics_interval' setting, statistics will be disabled"); |
11 end | 11 end |
12 | 12 |
13 local stats_provider_config = config.get("*", "statistics_provider"); | 13 local stats_provider_name; |
14 local stats_provider = stats_provider_config or "internal"; | 14 local stats_provider_config = config.get("*", "statistics"); |
15 local stats_provider = stats_provider_config; | |
16 | |
17 if not stats_provider and stats_interval then | |
18 stats_provider = "internal"; | |
19 elseif stats_provider and not stats_interval then | |
20 stats_interval = 60; | |
21 end | |
15 | 22 |
16 local builtin_providers = { | 23 local builtin_providers = { |
17 internal = "util.statistics"; | 24 internal = "util.statistics"; |
18 statsd = "util.statsd"; | 25 statsd = "util.statsd"; |
19 }; | 26 }; |
20 | 27 |
21 if stats_provider:match("^library:") then | 28 |
22 stats_provider = stats_provider:match(":(.+)$"); | 29 local stats, stats_err = false, nil; |
23 else | 30 |
24 stats_provider = builtin_providers[stats_provider]; | 31 if stats_provider then |
25 if not stats_provider then | 32 if stats_provider:sub(1,1) == ":" then |
26 log("error", "Unrecognized built-in statistics provider '%s', using internal instead", stats_provider_config); | 33 stats_provider = stats_provider:sub(2); |
27 stats_provider = builtin_providers["internal"]; | 34 stats_provider_name = "external "..stats_provider; |
35 elseif stats_provider then | |
36 stats_provider_name = "built-in "..stats_provider; | |
37 stats_provider = builtin_providers[stats_provider]; | |
38 if not stats_provider then | |
39 log("error", "Unrecognized statistics provider '%s', statistics will be disabled", stats_provider_config); | |
40 end | |
41 end | |
42 | |
43 local have_stats_provider, stats_lib = pcall(require, stats_provider); | |
44 if not have_stats_provider then | |
45 stats, stats_err = nil, stats_lib; | |
46 else | |
47 local stats_config = config.get("*", "statistics_config"); | |
48 stats, stats_err = stats_lib.new(stats_config); | |
49 stats_provider_name = stats_lib._NAME or stats_provider_name; | |
28 end | 50 end |
29 end | 51 end |
30 | 52 |
31 local have_stats_provider, stats_lib = pcall(require, stats_provider); | 53 if stats == nil then |
32 | |
33 local stats, stats_err; | |
34 | |
35 if not have_stats_provider then | |
36 stats, stats_err = nil, stats_lib; | |
37 else | |
38 local stats_config = config.get("*", "statistics_config"); | |
39 stats, stats_err = stats_lib.new(stats_config); | |
40 end | |
41 | |
42 if not stats then | |
43 log("error", "Error loading statistics provider '%s': %s", stats_provider, stats_err); | 54 log("error", "Error loading statistics provider '%s': %s", stats_provider, stats_err); |
44 end | 55 end |
45 | 56 |
46 local measure, collect; | 57 local measure, collect; |
47 local latest_stats = {}; | 58 local latest_stats = {}; |
51 if stats then | 62 if stats then |
52 function measure(type, name) | 63 function measure(type, name) |
53 local f = assert(stats[type], "unknown stat type: "..type); | 64 local f = assert(stats[type], "unknown stat type: "..type); |
54 return f(name); | 65 return f(name); |
55 end | 66 end |
67 | |
68 if stats_interval then | |
69 log("debug", "Statistics enabled using %s provider, collecting every %d seconds", stats_provider_name, stats_interval); | |
70 | |
71 local mark_collection_start = measure("times", "stats.collection"); | |
72 local mark_processing_start = measure("times", "stats.processing"); | |
73 | |
74 function collect() | |
75 local mark_collection_done = mark_collection_start(); | |
76 fire_event("stats-update"); | |
77 mark_collection_done(); | |
78 | |
79 if stats.get_stats then | |
80 changed_stats, stats_extra = {}, {}; | |
81 for stat_name, getter in pairs(stats.get_stats()) do | |
82 local type, value, extra = getter(); | |
83 local old_value = latest_stats[stat_name]; | |
84 latest_stats[stat_name] = value; | |
85 if value ~= old_value then | |
86 changed_stats[stat_name] = value; | |
87 end | |
88 if extra then | |
89 stats_extra[stat_name] = extra; | |
90 end | |
91 end | |
92 local mark_processing_done = mark_processing_start(); | |
93 fire_event("stats-updated", { stats = latest_stats, changed_stats = changed_stats, stats_extra = stats_extra }); | |
94 mark_processing_done(); | |
95 end | |
96 return stats_interval; | |
97 end | |
98 timer.add_task(stats_interval, collect); | |
99 prosody.events.add_handler("server-started", function () collect() end, -1); | |
100 else | |
101 log("debug", "Statistics enabled using %s provider, collection is disabled", stats_provider_name); | |
102 end | |
103 else | |
104 log("debug", "Statistics disabled"); | |
105 function measure() return measure; end | |
56 end | 106 end |
57 | 107 |
58 if stats_interval then | |
59 log("debug", "Statistics collection is enabled every %d seconds", stats_interval); | |
60 | |
61 local mark_collection_start = measure("times", "stats.collection"); | |
62 local mark_processing_start = measure("times", "stats.processing"); | |
63 | |
64 function collect() | |
65 local mark_collection_done = mark_collection_start(); | |
66 fire_event("stats-update"); | |
67 mark_collection_done(); | |
68 | |
69 if stats.get_stats then | |
70 changed_stats, stats_extra = {}, {}; | |
71 for stat_name, getter in pairs(stats.get_stats()) do | |
72 local type, value, extra = getter(); | |
73 local old_value = latest_stats[stat_name]; | |
74 latest_stats[stat_name] = value; | |
75 if value ~= old_value then | |
76 changed_stats[stat_name] = value; | |
77 end | |
78 if extra then | |
79 stats_extra[stat_name] = extra; | |
80 end | |
81 end | |
82 local mark_processing_done = mark_processing_start(); | |
83 fire_event("stats-updated", { stats = latest_stats, changed_stats = changed_stats, stats_extra = stats_extra }); | |
84 mark_processing_done(); | |
85 end | |
86 return stats_interval; | |
87 end | |
88 timer.add_task(stats_interval, collect); | |
89 prosody.events.add_handler("server-started", function () collect() end, -1); | |
90 end | |
91 | |
92 if not stats_interval and stats_provider == "util.statistics" then | |
93 log("debug", "Statistics collection is disabled"); | |
94 -- nop | |
95 function measure() | |
96 return measure; | |
97 end | |
98 function collect() | |
99 end | |
100 end | |
101 | 108 |
102 return { | 109 return { |
103 measure = measure; | 110 measure = measure; |
104 get_stats = function () | 111 get_stats = function () |
105 return latest_stats, changed_stats, stats_extra; | 112 return latest_stats, changed_stats, stats_extra; |