From fe83d1456e2e42a4a6025ad8b6df7c83b3529cf5 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 28 Apr 2018 18:53:28 +0100 Subject: [PATCH] [Feature] Add preliminary version of maps stats plugin --- src/plugins/lua/maps_stats.lua | 116 +++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/plugins/lua/maps_stats.lua diff --git a/src/plugins/lua/maps_stats.lua b/src/plugins/lua/maps_stats.lua new file mode 100644 index 000000000..d2f094b91 --- /dev/null +++ b/src/plugins/lua/maps_stats.lua @@ -0,0 +1,116 @@ +--[[ +Copyright (c) 2011-2015, Vsevolod Stakhov + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +]]-- + +if confighelp then + rspamd_config:add_example(nil, 'maps_stats', + "Stores maps statistics in Redis", [[ +maps_stats { + # one iteration step per 2 minutes + interval = 2m; + # how many elements to store in Redis + count = 1k; + # common prefix for elements + prefix = 'rm_'; +} +]]) +end + +local redis_params +local rspamd_logger = require "rspamd_logger" +local lua_redis = require "lua_redis" +local N = "maps_stats" + +local settings = { + interval = 120, -- one iteration step per 2 minutes + count = 1000, -- how many elements to store in Redis + prefix = 'rm_', -- common prefix for elements +} + +local function process_map(map, ev_base, _) + if map:get_nelts() > 0 and map:get_uri() ~= 'static' then + local key = settings.prefix .. map:get_uri() + + local function redis_zrange_cb(err, data) + if err then + rspamd_logger.errx(rspamd_config, 'cannot delete extra elements in %s: %s', + key, err) + elseif data then + rspamd_logger.infox(rspamd_config, 'cleared %s elements from %s', + data, key) + end + end + local function redis_card_cb(err, data) + if err then + rspamd_logger.errx(rspamd_config, 'cannot get number of elements in %s: %s', + key, err) + elseif data then + if settings.count > 0 and tonumber(data) > settings.count then + lua_redis.rspamd_redis_make_request_taskless(ev_base, + rspamd_config, + redis_params, -- connect params + key, -- hash key + true, -- is write + redis_zrange_cb, --callback + 'ZREMRANGEBYRANK', -- command + {key, '0', tostring(-(settings.count) - 1)} -- arguments + ) + end + end + end + local ret, conn, _ = lua_redis.rspamd_redis_make_request_taskless(ev_base, + rspamd_config, + redis_params, -- connect params + key, -- hash key + true, -- is write + redis_card_cb, --callback + 'ZCARD', -- command + {key} -- arguments + ) + + if ret and conn then + local stats = map:get_stats(true) + for k,s in pairs(stats) do + conn:add_cmd('ZINCRBY', {key, tostring(s), k}) + end + end + end +end + +local opts = rspamd_config:get_all_opt(N) + +if opts then + for k,v in pairs(opts) do + settings[k] = v + end +end + +redis_params = lua_redis.parse_redis_server(N, opts) + + +if redis_params then + rspamd_config:add_on_load(function (_, ev_base, worker) + local maps = rspamd_config:get_maps() + + for _,m in ipairs(maps) do + rspamd_config:add_periodic(ev_base, + settings['interval'], + function () + process_map(m, ev_base, worker) + return true + end, true) + end + end) +end \ No newline at end of file -- 2.39.5