Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

- Export targets not being stopped after removal from the role configuration (#47).
- Graphite exporters stop after a configuration reload that keeps the
`graphite` section unchanged.
- Requirement of metrics 1.7.0+ for an empty `graphite` section.

## 0.4.1 - 2026-05-07

Expand Down
16 changes: 10 additions & 6 deletions roles/metrics-export.lua
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,12 @@ local function validate_graphite_node(endpoint)
validate_graphite_send_interval(endpoint)
end

local function validate_graphite(conf)
local ok = pcall(require('metrics.plugins.graphite').stop)
if not ok then
error('ensure you have metrics 1.7.0+ (provided with Tarantool 3.7.0+ or can be ' ..
'installed as an external dependency)', 2)
end
local function is_graphite_supported()
local ok, graphite = pcall(require, 'metrics.plugins.graphite')
return ok and type(graphite) == "table" and type(graphite.stop) == "function"
end

local function validate_graphite(conf)
if conf ~= nil and type(conf) ~= "table" then
error("graphite configuration must be a table, got " .. type(conf), 2)
end
Expand All @@ -190,6 +189,11 @@ local function validate_graphite(conf)
error("graphite configuration must be an array, not a map", 2)
end

if next(conf) ~= nil and not is_graphite_supported() then
error('ensure you have metrics 1.7.0+ (provided with Tarantool 3.7.0+ or can be ' ..
'installed as an external dependency)', 2)
end

for _, graphite_node in ipairs(conf) do
validate_graphite_node(graphite_node)
end
Expand Down
63 changes: 63 additions & 0 deletions test/integration/reload_config_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,45 @@ g.test_reload_config_remove_http_target = function(cg)
t.assert_not(is_tcp_connect('127.0.0.1', 8082))
end

g.before_test('test_reload_config_remove_graphite_target', function(cg)
helpers.skip_if_graphite_unsupported()
fio.copyfile(fio.pathjoin('test', 'entrypoint', 'graphite_config.yaml'), cg.workdir)
end)

g.test_reload_config_remove_graphite_target = function(cg)
cg.server = server:new({
config_file = fio.pathjoin(cg.workdir, 'graphite_config.yaml'),
chdir = cg.workdir,
alias = 'master',
workdir = cg.workdir,
})
cg.server:start({wait_until_ready = true})
t.assert_ge(graphite_helpers.count_graphite_frames("master", "127.0.0.1", 44444, 1), 1)
t.assert_ge(graphite_helpers.count_graphite_frames("tarantool", "127.0.0.1", 2223, 2), 1)

local config_path = fio.pathjoin(cg.workdir, 'graphite_config.yaml')
local file = fio.open(config_path, {'O_RDONLY'})
t.assert(file ~= nil)
local cfg = yaml.decode(file:read())
file:close()

local role_cfg = cfg.groups['group-001'].replicasets['replicaset-001'].
instances.master.roles_cfg['roles.metrics-export']
role_cfg.graphite = nil

file = fio.open(config_path, {
'O_CREAT', 'O_WRONLY', 'O_TRUNC',
}, tonumber('644', 8))
t.assert(file ~= nil)
file:write(yaml.encode(cfg))
file:close()

cg.server:eval("require('config'):reload()")

t.assert_equals(graphite_helpers.count_graphite_frames("master", "127.0.0.1", 44444, 1), 0)
t.assert_equals(graphite_helpers.count_graphite_frames("tarantool", "127.0.0.1", 2223, 2), 0)
end

local function change_graphite_port_in_config(cg, new_port)
if new_port == nil then
new_port = '2222'
Expand Down Expand Up @@ -241,3 +280,27 @@ g.test_reload_config_graphite = function(cg)
t.assert_ge(graphite_helpers.count_graphite_frames("tarantool", "127.0.0.1", 3333, 2), 1)
t.assert_equals(graphite_helpers.count_graphite_frames("tarantool", "127.0.0.1", 2223, 2), 0)
end

g.before_test('test_reload_config_graphite_not_changed', function(cg)
helpers.skip_if_graphite_unsupported()
fio.copyfile(fio.pathjoin('test', 'entrypoint', 'graphite_config.yaml'), cg.workdir)
end)

g.test_reload_config_graphite_not_changed = function(cg)
cg.server = server:new({
config_file = fio.pathjoin(cg.workdir, 'graphite_config.yaml'),
chdir = cg.workdir,
alias = 'master',
workdir = cg.workdir,
})

cg.server:start({wait_until_ready = true})

t.assert_ge(graphite_helpers.count_graphite_frames("master", "127.0.0.1", 44444, 1), 1)

-- Reload the same configuration: the running exporters must survive it.
cg.server:eval("require('config'):reload()")

t.assert_ge(graphite_helpers.count_graphite_frames("master", "127.0.0.1", 44444, 1), 1)
t.assert_ge(graphite_helpers.count_graphite_frames("tarantool", "127.0.0.1", 2223, 2), 1)
end
9 changes: 8 additions & 1 deletion test/unit/validate_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,11 @@ local ok_cases = {
},
},
},
["graphite_empty"] = {
cfg = {
graphite = {},
},
},
["graphite_full"] = {
cfg = {
graphite = {{
Expand Down Expand Up @@ -1084,7 +1089,9 @@ local ok_cases = {

for name, case in pairs(ok_cases) do
g["test_validate_ok_" .. name] = function(gc)
if (case.cfg or {}).graphite ~= nil then
if next((case.cfg or {}).graphite or {}) ~= nil then
-- Skip if at least one endpoint exists. Empty table could
-- be possible.
helpers.skip_if_graphite_unsupported()
end

Expand Down
Loading