]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add preliminary version of maps stats plugin
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 28 Apr 2018 17:53:28 +0000 (18:53 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 28 Apr 2018 17:53:28 +0000 (18:53 +0100)
src/plugins/lua/maps_stats.lua [new file with mode: 0644]

diff --git a/src/plugins/lua/maps_stats.lua b/src/plugins/lua/maps_stats.lua
new file mode 100644 (file)
index 0000000..d2f094b
--- /dev/null
@@ -0,0 +1,116 @@
+--[[
+Copyright (c) 2011-2015, Vsevolod Stakhov <vsevolod@highsecure.ru>
+
+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