Skip to content

Commit

Permalink
test: allow to count select requests on storages
Browse files Browse the repository at this point in the history
I don't want to lean on box.stat() information here, because I don't
control all iproto calls to storages: say, vshard rebalancer may perform
them in background.

Instead, I wrapped particular storage function I'm interested in.

The goal is to be able to determine how much storages are involved into
a select/pairs request.

It is implemented as a helper for testing, but hopefully we'll implement
some nice statistics as part of the module in a future (see #224).

Part of #220
  • Loading branch information
Totktonada committed Oct 18, 2021
1 parent d13fe63 commit a6e34e1
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 0 deletions.
70 changes: 70 additions & 0 deletions test/helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,76 @@ function helpers.call_on_servers(cluster, aliases, func)
end
end

-- Call given function for each server with the 'crud-storage'
-- role.
--
-- 'func' accepts a server object, a replicaset config and all
-- arguments passed after 'func'.
--
-- Usage example:
--
-- | local res = {}
-- | helpers.call_on_storages(g.cluster, function(server, replicaset, res)
-- | local instance_res = server.net_box:call(<...>)
-- | res[replicaset.alias] = res[replicaset.alias] + instance_res
-- | end)
-- | t.assert_equals(res, {['s-1'] = 5, ['s-2'] = 6})
function helpers.call_on_storages(cluster, func, ...)
-- Accumulate storages into a map from the storage alias to
-- the replicaset object. Only storages, skip other instances.
--
-- Example:
--
-- | {
-- | ['s1-master'] = {
-- | alias = 's-1',
-- | roles = <...>,
-- | servers = {
-- | {
-- | alias = 's1-master',
-- | env = <...>,
-- | instance_uuid = <...>,
-- | },
-- | <...>
-- | },
-- | uuid = <...>,
-- | }
-- | ['s1-replica'] = <...>,
-- | ['s2-master'] = <...>,
-- | ['s2-replica'] = <...>,
-- | }
--
-- NB: The 'servers' field contains server configs. They are
-- not the same as server objects: say, there is no 'net_box'
-- field here.
local alias_map = {}
for _, replicaset in ipairs(cluster.replicasets) do
-- Whether it is a storage replicaset?
local has_crud_storage_role = false
for _, role in ipairs(replicaset.roles) do
if role == 'crud-storage' then
has_crud_storage_role = true
break
end
end

-- If so, add servers of the replicaset into the mapping.
if has_crud_storage_role then
for _, server in ipairs(replicaset.servers) do
alias_map[server.alias] = replicaset
end
end
end

-- Call given function for each storage node.
for _, server in ipairs(cluster.servers) do
local replicaset_alias = alias_map[server.alias]
if replicaset_alias ~= nil then
func(server, replicaset_alias, ...)
end
end
end

function helpers.assert_ge(actual, expected, message)
if not (actual >= expected) then
local err = string.format('expected: %s >= %s', actual, expected)
Expand Down
98 changes: 98 additions & 0 deletions test/helpers/storage_stat.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
local checks = require('checks')
local helpers = require('test.helper')

local storage_stat = {}

-- Wrap crud's select_on_storage() function to count selects
-- and add storage_stat() function that returns resulting
-- statistics.
--
-- Call it after crud's initialization.
function storage_stat.init_on_storage()
assert(_G._crud.select_on_storage ~= nil)

-- Here we count requests.
local storage_stat_table = {
select_requests = 0,
}

-- Wrap select_on_storage() function.
local select_on_storage_saved = _G._crud.select_on_storage
_G._crud.select_on_storage = function(...)
local requests = storage_stat_table.select_requests
storage_stat_table.select_requests = requests + 1
return select_on_storage_saved(...)
end

-- Accessor for the statistics.
rawset(_G, 'storage_stat', function()
return storage_stat_table
end)
end

-- Accumulate statistics from storages.
--
-- The statistics is grouped by replicasets.
--
-- Example of a return value:
--
-- | {
-- | ['s-1'] = {
-- | select_requests = 1,
-- | },
-- | ['s-2'] = {
-- | select_requests = 0,
-- | },
-- | }
function storage_stat.collect(cluster)
checks('table')

local res = {}

helpers.call_on_storages(cluster, function(server, replicaset)
checks('table', 'table')

-- Collect the statistics.
local storage_stat = server.net_box:call('storage_stat')

-- Initialize if needed.
if res[replicaset.alias] == nil then
res[replicaset.alias] = {}
end

-- Accumulate the collected statistics.
for key, val in pairs(storage_stat) do
local old = res[replicaset.alias][key] or 0
res[replicaset.alias][key] = old + val
end
end)

return res
end

-- Difference between 'a' and 'b' storage statistics.
--
-- The return value structure is the same as for
-- storage_stat.collect().
function storage_stat.diff(a, b)
checks('table', 'table')

local diff = table.deepcopy(a)

for replicaset_alias, stat_b in pairs(b) do
-- Initialize if needed.
if diff[replicaset_alias] == nil then
diff[replicaset_alias] = {}
end

-- Substract 'b' statistics from 'a'.
for key, val in pairs(stat_b) do
local old = diff[replicaset_alias][key] or 0
diff[replicaset_alias][key] = old - val
end
end

return diff
end

return storage_stat

0 comments on commit a6e34e1

Please sign in to comment.