diff --git a/nginx-metrix/collectors.lua b/nginx-metrix/collectors.lua index 29d9bbf..8e3c1fc 100644 --- a/nginx-metrix/collectors.lua +++ b/nginx-metrix/collectors.lua @@ -12,53 +12,53 @@ table.remove(collectors, 1) -- removing dummy item -- @return bool --- local collector_exists = function(collector) - return index(collector.name, collectors_iter:map(function(c) return c.name end)) ~= nil + return index(collector.name, collectors_iter:map(function(c) return c.name end)) ~= nil end --- -- @param collector table --- local collector_validate = function(collector) - assert( - type(collector) == 'table', - ('Collector MUST be a table, got %s: %s'):format(type(collector), inspect(collector)) - ) - - assert( - type(collector.name) == 'string', - ('Collector must have string property "name", got %s: %s'):format(type(collector.name), inspect(collector)) - ) - - -- collector exists - assert( - not collector_exists(collector), - ('Collector<%s> already exists'):format(collector.name) - ) - - assert( - type(collector.ngx_phases) == 'table', - ('Collector<%s>.ngx_phases must be an array, given: %s'):format(collector.name, type(collector.ngx_phases)) - ) - - assert( - all(function(phase) return type(phase) == 'string' end, collector.ngx_phases), - ('Collector<%s>.ngx_phases must be an array of strings, given: %s'):format(collector.name, inspect(collector.ngx_phases)) - ) - - assert( - is.callable(collector.on_phase), - ('Collector<%s>:on_phase must be a function or callable table, given: %s'):format(collector.name, type(collector.on_phase)) - ) - - assert( - type(collector.fields) == 'table', - ('Collector<%s>.fields must be a table, given: %s'):format(collector.name, type(collector.fields)) - ) - - assert( - all(function(field, params) return type(field) == 'string' and type(params) == 'table' end, collector.fields), - ('Collector<%s>.fields must be an table[string, table], given: %s'):format(collector.name, inspect(collector.fields)) - ) + assert( + type(collector) == 'table', + ('Collector MUST be a table, got %s: %s'):format(type(collector), inspect(collector)) + ) + + assert( + type(collector.name) == 'string', + ('Collector must have string property "name", got %s: %s'):format(type(collector.name), inspect(collector)) + ) + + -- collector exists + assert( + not collector_exists(collector), + ('Collector<%s> already exists'):format(collector.name) + ) + + assert( + type(collector.ngx_phases) == 'table', + ('Collector<%s>.ngx_phases must be an array, given: %s'):format(collector.name, type(collector.ngx_phases)) + ) + + assert( + all(function(phase) return type(phase) == 'string' end, collector.ngx_phases), + ('Collector<%s>.ngx_phases must be an array of strings, given: %s'):format(collector.name, inspect(collector.ngx_phases)) + ) + + assert( + is.callable(collector.on_phase), + ('Collector<%s>:on_phase must be a function or callable table, given: %s'):format(collector.name, type(collector.on_phase)) + ) + + assert( + type(collector.fields) == 'table', + ('Collector<%s>.fields must be a table, given: %s'):format(collector.name, type(collector.fields)) + ) + + assert( + all(function(field, params) return type(field) == 'string' and type(params) == 'table' end, collector.fields), + ('Collector<%s>.fields must be an table[string, table], given: %s'):format(collector.name, inspect(collector.fields)) + ) end --- @@ -66,44 +66,44 @@ end -- @return table --- local collector_extend = function(collector) - local _metatable = { - init = function(self, storage) - self.storage = storage - end, - - handle_ngx_phase = function(self, phase) - self:on_phase(phase) - end, - - aggregate = function(self) - iter(self.fields):each(function(field, params) - if params.mean then - self.storage:mean_flush(field) - elseif params.cyclic then - self.storage:cyclic_flush(field) - end - end) - end, - - get_raw_stats = function(self) - return iter(self.fields):map(function(k, _) - return k, (self.storage:get(k) or 0) - end) - end, - - get_text_stats = function(self, output_helper) - return output_helper.render_stats(self) - end, - - get_html_stats = function(self, output_helper) - return output_helper.render_stats(self) + local _metatable = { + init = function(self, storage) + self.storage = storage + end, + + handle_ngx_phase = function(self, phase) + self:on_phase(phase) + end, + + aggregate = function(self) + iter(self.fields):each(function(field, params) + if params.mean then + self.storage:mean_flush(field) + elseif params.cyclic then + self.storage:cyclic_flush(field) end - } - _metatable.__index = _metatable + end) + end, - setmetatable(collector, _metatable) + get_raw_stats = function(self) + return iter(self.fields):map(function(k, _) + return k, (self.storage:get(k) or 0) + end) + end, - return collector + get_text_stats = function(self, output_helper) + return output_helper.render_stats(self) + end, + + get_html_stats = function(self, output_helper) + return output_helper.render_stats(self) + end + } + _metatable.__index = _metatable + + setmetatable(collector, _metatable) + + return collector end --- @@ -111,16 +111,16 @@ end -- @return table --- local collector_register = function(collector) - collector_validate(collector) + collector_validate(collector) - collector = collector_extend(collector) + collector = collector_extend(collector) - local storage = storage_collector_wrapper_factory.create(collector) - collector:init(storage) + local storage = storage_collector_wrapper_factory.create(collector) + collector:init(storage) - table.insert(collectors, collector) + table.insert(collectors, collector) - return collector + return collector end -------------------------------------------------------------------------------- @@ -130,19 +130,19 @@ exports.register = collector_register exports.all = collectors_iter if __TEST__ then - exports.__private__ = { - collectors = function(value) - if value ~= nil then - local count = length(collectors) - while count > 0 do table.remove(collectors); count = count - 1 end - iter(value):each(function(collector) table.insert(collectors, collector) end) - end - return collectors - end, - collector_exists = collector_exists, - collector_extend = collector_extend, - collector_validate = collector_validate, - } + exports.__private__ = { + collectors = function(value) + if value ~= nil then + local count = length(collectors) + while count > 0 do table.remove(collectors); count = count - 1 end + iter(value):each(function(collector) table.insert(collectors, collector) end) + end + return collectors + end, + collector_exists = collector_exists, + collector_extend = collector_extend, + collector_validate = collector_validate, + } end return exports diff --git a/nginx-metrix/lib/is.lua b/nginx-metrix/lib/is.lua index b9706ed..8b45467 100644 --- a/nginx-metrix/lib/is.lua +++ b/nginx-metrix/lib/is.lua @@ -2,22 +2,22 @@ local exports = {} local callable callable = function(obj) - return type(obj) == 'function' or type(obj) == 'table' and getmetatable(obj) and callable(getmetatable(obj).__call) + return type(obj) == 'function' or type(obj) == 'table' and getmetatable(obj) and callable(getmetatable(obj).__call) end exports.callable = callable setmetatable(exports, { - __call = function(t) - if _G.is == nil or type(_G.is) ~= 'table' then - _G.is = t - else - for k, v in pairs(t) do - _G.is[k] = v - end - end - return exports - end, + __call = function(t) + if _G.is == nil or type(_G.is) ~= 'table' then + _G.is = t + else + for k, v in pairs(t) do + _G.is[k] = v + end + end + return exports + end, }) -return exports \ No newline at end of file +return exports diff --git a/nginx-metrix/listener.lua b/nginx-metrix/listener.lua index 00df1c7..7ec409b 100644 --- a/nginx-metrix/listener.lua +++ b/nginx-metrix/listener.lua @@ -1,15 +1,15 @@ local inspect = require 'inspect' local phases = { - [[init]], - [[access]], - [[content]], - [[log]], - [[body-filter]], - [[header-filter]], - [[rewrite]], - [[ssl_certificate]], - [[init_worker]], + 'init', + 'access', + 'content', + 'log', + 'body-filter', + 'header-filter', + 'rewrite', + 'ssl_certificate', + 'init_worker', } local handlers = zip(phases, duplicate({})):tomap() @@ -18,30 +18,28 @@ local handlers = zip(phases, duplicate({})):tomap() -- @param collector table -- local attach_collector = function(collector) - iter(collector.ngx_phases):each(function(phase) - assert( - index(phase, phases) ~= nil, - ('Collector<%s>.ngx_phases[%s] invalid, phase "%s" does not exists'):format(collector.name, phase, phase) - ) - - table.insert(handlers[phase], collector) - end) + iter(collector.ngx_phases):each(function(phase) + assert(index(phase, phases) ~= nil, + ('Collector<%s>.ngx_phases[%s] invalid, phase "%s" does not exists'):format(collector.name, phase, phase)) + + table.insert(handlers[phase], collector) + end) end --- -- @param phase string --- local handle_phase = function(phase) - phase = phase or ngx.get_phase() + phase = phase or ngx.get_phase() - assert( - type(phase) == 'string' and index(phase, phases) ~= nil, - ('Invalid ngx phase %s (%s)'):format(inspect(phase), type(phase)) - ) + assert( + type(phase) == 'string' and index(phase, phases) ~= nil, + ('Invalid ngx phase %s (%s)'):format(inspect(phase), type(phase)) + ) - iter(handlers[phase]):each(function(collector) - collector:handle_ngx_phase(phase) - end) + iter(handlers[phase]):each(function(collector) + collector:handle_ngx_phase(phase) + end) end -------------------------------------------------------------------------------- @@ -52,10 +50,10 @@ exports.attach_collector = attach_collector exports.handle_phase = handle_phase if __TEST__ then - exports.__private__ = { - phases = phases, - get_handlers = function() return handlers end, - } + exports.__private__ = { + phases = phases, + get_handlers = function() return handlers end, + } end -return exports \ No newline at end of file +return exports diff --git a/nginx-metrix/logger.lua b/nginx-metrix/logger.lua index 6e457c1..9505cc3 100644 --- a/nginx-metrix/logger.lua +++ b/nginx-metrix/logger.lua @@ -1,51 +1,51 @@ local inspect = require 'inspect' local log = function(level, msg, ...) - if type(msg) ~= 'string' then - msg = inspect(msg) - end + if type(msg) ~= 'string' then + msg = inspect(msg) + end - if length({ ... }) > 0 then - msg = msg .. ' :: ' .. inspect({ ... }) - end + if length({ ... }) > 0 then + msg = msg .. ' :: ' .. inspect({ ... }) + end - ngx.log(level, msg) + ngx.log(level, msg) end local stderr = function(...) - log(ngx.STDERR, ...) + log(ngx.STDERR, ...) end local emerg = function(...) - log(ngx.EMERG, ...) + log(ngx.EMERG, ...) end local alert = function(...) - log(ngx.ALERT, ...) + log(ngx.ALERT, ...) end local crit = function(...) - log(ngx.CRIT, ...) + log(ngx.CRIT, ...) end local err = function(...) - log(ngx.ERR, ...) + log(ngx.ERR, ...) end local warn = function(...) - log(ngx.WARN, ...) + log(ngx.WARN, ...) end local notice = function(...) - log(ngx.NOTICE, ...) + log(ngx.NOTICE, ...) end local info = function(...) - log(ngx.INFO, ...) + log(ngx.INFO, ...) end local debug = function(...) - log(ngx.DEBUG, ...) + log(ngx.DEBUG, ...) end local exports = {} @@ -65,4 +65,4 @@ exports.notice = notice exports.info = info exports.debug = debug -return exports \ No newline at end of file +return exports diff --git a/nginx-metrix/main.lua b/nginx-metrix/main.lua index f7a0c35..fda2f58 100644 --- a/nginx-metrix/main.lua +++ b/nginx-metrix/main.lua @@ -26,19 +26,19 @@ local builtin_collectors = iter({ [[request]], [[status]], [[upstream]] }) -- @param collector --- local register_collector = function(collector) - collector = collectors.register(collector) + collector = collectors.register(collector) - listener.attach_collector(collector) - scheduler.attach_collector(collector) + listener.attach_collector(collector) + scheduler.attach_collector(collector) end --- -- local register_builtin_collectors = function(self) - builtin_collectors:each(function(name) - local collector = require('nginx-metrix.collectors.' .. name) - self.register_collector(collector) - end) + builtin_collectors:each(function(name) + local collector = require('nginx-metrix.collectors.' .. name) + self.register_collector(collector) + end) end -------------------------------------------------------------------------------- @@ -49,13 +49,13 @@ end -- @param phase string --- local handle_ngx_phase = function(phase) - namespaces.activate(ngx.var.server_name or ngx.var.hostname) + namespaces.activate(ngx.var.server_name or ngx.var.hostname) - if do_not_track then - do_not_track = false - else - listener.handle_phase(phase) - end + if do_not_track then + do_not_track = false + else + listener.handle_phase(phase) + end end -------------------------------------------------------------------------------- @@ -64,7 +64,7 @@ end --- -- local init_scheduler = function() - scheduler.start() + scheduler.start() end -------------------------------------------------------------------------------- @@ -74,12 +74,12 @@ end -- @param options bool default true --- local show = function(options) - options = options or {} - options.vhosts_filter = options.vhosts_filter or ngx.var.server_name or ngx.var.hostname + options = options or {} + options.vhosts_filter = options.vhosts_filter or ngx.var.server_name or ngx.var.hostname - output.render(options) + output.render(options) - do_not_track = true + do_not_track = true end -------------------------------------------------------------------------------- @@ -94,25 +94,25 @@ exports.init_scheduler = init_scheduler exports.show = show if __TEST__ then - exports.__private__ = { - collectors = collectors, - } + exports.__private__ = { + collectors = collectors, + } end setmetatable(exports, { - __call = function(self, options) - require('nginx-metrix.storage.dict').init(options) + __call = function(self, options) + require('nginx-metrix.storage.dict').init(options) - if options.vhosts ~= nil then - namespaces.init({namespaces=options.vhosts}) - end + if options.vhosts ~= nil then + namespaces.init({ namespaces = options.vhosts }) + end - if not options.skip_register_builtin_collectors then - self:register_builtin_collectors() - end + if not options.skip_register_builtin_collectors then + self:register_builtin_collectors() + end - return self - end, + return self + end, }) -return exports \ No newline at end of file +return exports diff --git a/nginx-metrix/output/helper.lua b/nginx-metrix/output/helper.lua index db3df34..89ccff2 100644 --- a/nginx-metrix/output/helper.lua +++ b/nginx-metrix/output/helper.lua @@ -5,63 +5,63 @@ local lust = require 'Lust' local logger = require 'nginx-metrix.logger' local formats2headers = { - ["text"] = "text/plain", - ["html"] = "text/html", - ["json"] = "application/json", + ["text"] = "text/plain", + ["html"] = "text/html", + ["json"] = "application/json", } local headers2formats = {} -for k,v in pairs(formats2headers) do - headers2formats[v]=k +for k, v in pairs(formats2headers) do + headers2formats[v] = k end local header_http_accept = function() - local _accept = {} - local accept_headers = ngx.req.get_headers().accept - if accept_headers then - for accept in string.gmatch(accept_headers, "%w+/%w+") do - table.insert(_accept, accept) - end + local _accept = {} + local accept_headers = ngx.req.get_headers().accept + if accept_headers then + for accept in string.gmatch(accept_headers, "%w+/%w+") do + table.insert(_accept, accept) end - return iter(_accept) + end + return iter(_accept) end --- -- @return string local get_format = function() - -- trying to get format from GET params - local uri_args = ngx.req.get_uri_args() - if uri_args["format"] and formats2headers[uri_args["format"]] then - return uri_args["format"] + -- trying to get format from GET params + local uri_args = ngx.req.get_uri_args() + if uri_args["format"] and formats2headers[uri_args["format"]] then + return uri_args["format"] + end + + for _, accept in header_http_accept() do + if headers2formats[accept] then + return headers2formats[accept] end + end - for _, accept in header_http_accept() do - if headers2formats[accept] then - return headers2formats[accept] - end - end - - -- default is text - return 'text' + -- default is text + return 'text' end --- -- @param content_type string --- local set_content_type_header = function(content_type) - if ngx.headers_sent then - logger.warn('Can not set Content-type header because headers already sent') - else - ngx.header.content_type = content_type or formats2headers[get_format()] - end + if ngx.headers_sent then + logger.warn('Can not set Content-type header because headers already sent') + else + ngx.header.content_type = content_type or formats2headers[get_format()] + end end local title = function() - return 'Nginx Metrix' + return 'Nginx Metrix' end local title_version = function() - return title() .. ' v' .. version + return title() .. ' v' .. version end --------------------------- @@ -69,11 +69,11 @@ end --------------------------- local format_value = function(collector, name, value) - if value ~= nil and type(collector.fields) == 'table' and collector.fields[name] ~= nil and collector.fields[name].format ~= nil then - value = collector.fields[name].format:format(value) - end + if value ~= nil and type(collector.fields) == 'table' and collector.fields[name] ~= nil and collector.fields[name].format ~= nil then + value = collector.fields[name].format:format(value) + end - return value + return value end --------------------------- @@ -81,108 +81,108 @@ end --------------------------- local html_page_template = function(body) - local tpl = lust{[[ - - - - - - - - - @if(title)<title>else<default_title> - - -
-
-

@if(title)else<default_title></h1> - @body - </div> - </div> - <script src="https://yastatic.net/jquery/1.12.0/jquery.min.js"></script> - <script src="https://yastatic.net/bootstrap/3.3.6/js/bootstrap.min.js" crossorigin="anonymous"></script> - </body> -</html> - ]], - title = [[$title]], - default_title = title() - } - - if body then - tpl.body = body - end + local tpl = lust { + [[ + <!DOCTYPE html> + <html lang="en"> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="stylesheet" href="https://yastatic.net/bootstrap/3.3.6/css/bootstrap.min.css" crossorigin="anonymous"> + <link rel="stylesheet" href="https://yastatic.net/bootstrap/3.3.6/css/bootstrap-theme.min.css" crossorigin="anonymous"> + <title>@if(title)<title>else<default_title> + + +
+
+

@if(title)else<default_title></h1> + @body + </div> + </div> + <script src="https://yastatic.net/jquery/1.12.0/jquery.min.js"></script> + <script src="https://yastatic.net/bootstrap/3.3.6/js/bootstrap.min.js" crossorigin="anonymous"></script> + </body> + </html> + ]], + title = [[$title]], + default_title = title() + } - return tpl + if body then + tpl.body = body + end + + return tpl end local html_section_template = function(body) - local tpl = lust{[[ - <div class="panel panel-@if(class)<class>else<default_class>"> - <div class="panel-heading"> - <h3 class="panel-title">$name</h3> - </div> - @if(with_body)<panel_body>else<body> - </div> - ]], - panel_body = [[ - <div class="panel-body"> - @body - </div> - ]], - class = [[$class]], - default_class = [[default]], - } - - if body then - tpl.body = body - end - - return tpl + local tpl = lust { + [[ + <div class="panel panel-@if(class)<class>else<default_class>"> + <div class="panel-heading"> + <h3 class="panel-title">$name</h3> + </div> + @if(with_body)<panel_body>else<body> + </div> + ]], + panel_body = [[ + <div class="panel-body"> + @body + </div> + ]], + class = [[$class]], + default_class = [[default]], + } + + if body then + tpl.body = body + end + + return tpl end local html_table_template = function() - return lust{[[ - <table class="table table-bordered table-condensed table-hover"> - @map{ item=items }:{{<tr><th class="col-md-2">$item.name</th><td>$item.value</td></tr>}} - </table> - ]]} + return lust { + [[ + <table class="table table-bordered table-condensed table-hover"> + @map{ item=items }:{{<tr><th class="col-md-2">$item.name</th><td>$item.value</td></tr>}} + </table> + ]] + } end local html_render_stats = function(collector) - return html_section_template( - html_table_template():gen{ - items = collector:get_raw_stats():map( - function(name, value) - return {name=name, value=format_value(collector, name, value)} - end - ):totable() - } - ):gen{name=collector.name, with_body=false} + return html_section_template(html_table_template():gen { + items = collector:get_raw_stats():map(function(name, value) + return { name = name, value = format_value(collector, name, value) } + end):totable() + }):gen { name = collector.name, with_body = false } end local text_header = function() - return lust("### $title ###\n"):gen{title = title_version()} + return lust("### $title ###\n"):gen { title = title_version() } end local text_section_template = function(stats) - local tpl = lust("\n[$namespace@$collector]\n@stats") - if stats then - tpl.stats = stats - end - return tpl + local tpl = lust("\n[$namespace@$collector]\n@stats") + if stats then + tpl.stats = stats + end + return tpl end local text_item_template = function() - return lust("$name=$value\n") + return lust("$name=$value\n") end local text_render_stats = function(collector) - return collector:get_raw_stats():reduce( - function(formated_stats, name, value) - return formated_stats .. text_item_template():gen{name=name, value=format_value(collector, name, value)} - end, - '' - ) + return collector:get_raw_stats():reduce( + function(formated_stats, name, value) + return formated_stats .. text_item_template():gen { name = name, value = format_value(collector, name, value) } + end, + '' + ) end -------------------------------------------------------------------------------- @@ -205,10 +205,10 @@ exports.text.item_template = text_item_template exports.text.render_stats = text_render_stats if __TEST__ then - exports.__private__ = { - header_http_accept = header_http_accept, - format_value = format_value - } + exports.__private__ = { + header_http_accept = header_http_accept, + format_value = format_value + } end return exports diff --git a/nginx-metrix/storage/collector_wrapper_factory.lua b/nginx-metrix/storage/collector_wrapper_factory.lua index 98c83ce..f103614 100644 --- a/nginx-metrix/storage/collector_wrapper_factory.lua +++ b/nginx-metrix/storage/collector_wrapper_factory.lua @@ -9,7 +9,7 @@ local key_sep_collector = '¦' -- @return string --- local normalize_string = function(str) - return str:gsub(key_sep_namespace, '_'):gsub(key_sep_collector, '_') + return str:gsub(key_sep_namespace, '_'):gsub(key_sep_collector, '_') end local wrapper_metatable = {} @@ -21,22 +21,22 @@ wrapper_metatable.__index = wrapper_metatable -- @return string --- wrapper_metatable.prepare_key = function(self, key) - assert(key ~= nil, ('key can not be nil')) - if type(key) ~= 'string' then key = tostring(key) end + assert(key ~= nil, ('key can not be nil')) + if type(key) ~= 'string' then key = tostring(key) end - key = normalize_string(key) + key = normalize_string(key) - local key_prefix = '' + local key_prefix = '' - if self.collector_name ~= nil then - key_prefix = normalize_string(self.collector_name) .. key_sep_collector .. key_prefix - end + if self.collector_name ~= nil then + key_prefix = normalize_string(self.collector_name) .. key_sep_collector .. key_prefix + end - if namespaces.active() ~= nil then - key_prefix = normalize_string(namespaces.active()) .. key_sep_namespace .. key_prefix - end + if namespaces.active() ~= nil then + key_prefix = normalize_string(namespaces.active()) .. key_sep_namespace .. key_prefix + end - return key_prefix .. key + return key_prefix .. key end --- @@ -44,7 +44,7 @@ end -- @return mixed,int --- wrapper_metatable.get = function(self, key) - return storage_dict.get(self:prepare_key(key)) + return storage_dict.get(self:prepare_key(key)) end --- @@ -52,7 +52,7 @@ end -- @return mixed,int,bool ---- wrapper_metatable.get_stale = function(self, key) - return storage_dict.get_stale(self:prepare_key(key)) + return storage_dict.get_stale(self:prepare_key(key)) end --- @@ -63,7 +63,7 @@ end -- @return mixed --- wrapper_metatable.set = function(self, key, value, exptime, flags) - return storage_dict.set(self:prepare_key(key), value, exptime, flags) + return storage_dict.set(self:prepare_key(key), value, exptime, flags) end --- @@ -74,7 +74,7 @@ end -- @return mixed --- wrapper_metatable.safe_set = function(self, key, value, exptime, flags) - return storage_dict.safe_set(self:prepare_key(key), value, exptime, flags) + return storage_dict.safe_set(self:prepare_key(key), value, exptime, flags) end --- @@ -85,7 +85,7 @@ end -- @return mixed --- wrapper_metatable.add = function(self, key, value, exptime, flags) - return storage_dict.add(self:prepare_key(key), value, exptime, flags) + return storage_dict.add(self:prepare_key(key), value, exptime, flags) end --- @@ -96,7 +96,7 @@ end -- @return mixed --- wrapper_metatable.safe_add = function(self, key, value, exptime, flags) - return storage_dict.safe_add(self:prepare_key(key), value, exptime, flags) + return storage_dict.safe_add(self:prepare_key(key), value, exptime, flags) end --- @@ -107,14 +107,14 @@ end -- @return mixed --- wrapper_metatable.replace = function(self, key, value, exptime, flags) - return storage_dict.replace(self:prepare_key(key), value, exptime, flags) + return storage_dict.replace(self:prepare_key(key), value, exptime, flags) end --- -- @param key string -- wrapper_metatable.delete = function(self, key) - storage_dict.delete(self:prepare_key(key)) + storage_dict.delete(self:prepare_key(key)) end --- @@ -123,7 +123,7 @@ end -- @return mixed --- wrapper_metatable.incr = function(self, key, value) - return storage_dict.incr(self:prepare_key(key), value) + return storage_dict.incr(self:prepare_key(key), value) end --- @@ -132,7 +132,7 @@ end -- @return mixed --- wrapper_metatable.safe_incr = function(self, key, value) - return storage_dict.safe_incr(self:prepare_key(key), value) + return storage_dict.safe_incr(self:prepare_key(key), value) end --- @@ -141,22 +141,22 @@ end -- @return mixed --- wrapper_metatable.mean_add = function(self, key, value) - key = self:prepare_key(key) - local prev_value, counter = storage_dict.get(key) - value = ((prev_value or 0) * counter + value) / (counter + 1) - return storage_dict.set(key, value, nil, counter + 1) + key = self:prepare_key(key) + local prev_value, counter = storage_dict.get(key) + value = ((prev_value or 0) * counter + value) / (counter + 1) + return storage_dict.set(key, value, nil, counter + 1) end --- -- @param key string --- wrapper_metatable.mean_flush = function(self, key) - key = self:prepare_key(key) - local prev_value, counter = storage_dict.get(key) - if counter > 0 then - counter = 1 - end - storage_dict.set(key, (prev_value or 0), 0, counter) + key = self:prepare_key(key) + local prev_value, counter = storage_dict.get(key) + if counter > 0 then + counter = 1 + end + storage_dict.set(key, (prev_value or 0), 0, counter) end --- @@ -165,18 +165,18 @@ end -- @return mixed --- wrapper_metatable.cyclic_incr = function(self, key, value) - return storage_dict.safe_incr(self:prepare_key(key) .. '^^next^^', value) + return storage_dict.safe_incr(self:prepare_key(key) .. '^^next^^', value) end --- -- @param key string --- wrapper_metatable.cyclic_flush = function(self, key) - key = self:prepare_key(key) - local next_key = key .. '^^next^^' - local next_value = storage_dict.get(next_key) or 0 - storage_dict.delete(next_key) - storage_dict.set(key, next_value, 0, 0) + key = self:prepare_key(key) + local next_key = key .. '^^next^^' + local next_value = storage_dict.get(next_key) or 0 + storage_dict.delete(next_key) + storage_dict.set(key, next_value, 0, 0) end --- @@ -184,13 +184,13 @@ end -- @param collector --- local create = function(collector) - local wrapper = { - collector_name = collector.name - } + local wrapper = { + collector_name = collector.name + } - setmetatable(wrapper, wrapper_metatable) + setmetatable(wrapper, wrapper_metatable) - return wrapper + return wrapper end -------------------------------------------------------------------------------- @@ -201,9 +201,9 @@ local exports = {} exports.create = create if __TEST__ then - exports.__private__ = { - wrapper_metatable = wrapper_metatable - } + exports.__private__ = { + wrapper_metatable = wrapper_metatable + } end return exports diff --git a/nginx-metrix/storage/dict.lua b/nginx-metrix/storage/dict.lua index 40ee295..0ec9614 100644 --- a/nginx-metrix/storage/dict.lua +++ b/nginx-metrix/storage/dict.lua @@ -7,28 +7,28 @@ local logger = require 'nginx-metrix.logger' -- @param options table --- local init = function(options) - local shared_dict = options.shared_dict + local shared_dict = options.shared_dict - if type(shared_dict) == 'string' then - assert(ngx.shared[shared_dict] ~= nil, ('lua_shared_dict "%s" does not defined.'):format(shared_dict)) - shared_dict = ngx.shared[shared_dict] - end + if type(shared_dict) == 'string' then + assert(ngx.shared[shared_dict] ~= nil, ('lua_shared_dict "%s" does not defined.'):format(shared_dict)) + shared_dict = ngx.shared[shared_dict] + end - assert(type(shared_dict) == 'table', ('Invalid shared_dict type. Expected string or table, got %s.'):format(type(shared_dict))) + assert(type(shared_dict) == 'table', ('Invalid shared_dict type. Expected string or table, got %s.'):format(type(shared_dict))) - local index = function(_, method) - if shared_dict[method] == nil then - logger.error(("dict method '%s' does not exists"):format(method)) - return nil - end + local index = function(_, method) + if shared_dict[method] == nil then + logger.error(("dict method '%s' does not exists"):format(method)) + return nil + end - return function(...) - return shared_dict[method](shared_dict, ...) - end + return function(...) + return shared_dict[method](shared_dict, ...) end + end - exports._shared = shared_dict - setmetatable(exports, {__index = index}) + exports._shared = shared_dict + setmetatable(exports, { __index = index }) end --- @@ -36,10 +36,10 @@ end -- @return string --- local normalize_key = function(key) - assert(key ~= nil, 'key can not be nil') - if type(key) ~= 'string' then key = tostring(key) end + assert(key ~= nil, 'key can not be nil') + if type(key) ~= 'string' then key = tostring(key) end - return key + return key end --- @@ -47,8 +47,8 @@ end -- @return mixed,int --- local get = function(key) - local value, flags = exports._shared:get(normalize_key(key)) - return serializer.unserialize(value), (flags or 0) + local value, flags = exports._shared:get(normalize_key(key)) + return serializer.unserialize(value), (flags or 0) end --- @@ -56,8 +56,8 @@ end -- @return mixed,int,bool ---- local get_stale = function(key) - local value, flags, stale = exports._shared:get_stale(normalize_key(key)) - return serializer.unserialize(value), (flags or 0), stale + local value, flags, stale = exports._shared:get_stale(normalize_key(key)) + return serializer.unserialize(value), (flags or 0), stale end --- @@ -68,7 +68,7 @@ end -- @return mixed --- local set = function(key, value, exptime, flags) - return exports._shared:set(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) + return exports._shared:set(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) end --- @@ -79,7 +79,7 @@ end -- @return mixed --- local safe_set = function(key, value, exptime, flags) - return exports._shared:safe_set(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) + return exports._shared:safe_set(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) end --- @@ -90,7 +90,7 @@ end -- @return mixed --- local add = function(key, value, exptime, flags) - return exports._shared:add(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) + return exports._shared:add(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) end --- @@ -101,7 +101,7 @@ end -- @return mixed --- local safe_add = function(key, value, exptime, flags) - return exports._shared:safe_add(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) + return exports._shared:safe_add(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) end --- @@ -112,14 +112,14 @@ end -- @return mixed --- local replace = function(key, value, exptime, flags) - return exports._shared:replace(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) + return exports._shared:replace(normalize_key(key), serializer.serialize(value), exptime or 0, flags or 0) end --- -- @param key string -- local delete = function(key) - exports._shared:delete(normalize_key(key)) + exports._shared:delete(normalize_key(key)) end --- @@ -128,8 +128,8 @@ end -- @return mixed --- local incr = function(key, value) - if value ~= nil and type(value) ~= 'number' then value = tonumber(value) end - return exports._shared:incr(normalize_key(key), value) + if value ~= nil and type(value) ~= 'number' then value = tonumber(value) end + return exports._shared:incr(normalize_key(key), value) end --- @@ -138,22 +138,22 @@ end -- @return mixed --- local safe_incr = function(key, value) - key = normalize_key(key) - if value == nil then value = 1 end - if type(value) ~= 'number' then value = tonumber(value) end - - local new_value, err, _ - new_value, err = exports.incr(key, value) - if err == 'not found' then - new_value = value - _, err = exports.add(key, new_value) - end - - if err == nil then - return new_value, nil - else - return nil, err - end + key = normalize_key(key) + if value == nil then value = 1 end + if type(value) ~= 'number' then value = tonumber(value) end + + local new_value, err, _ + new_value, err = exports.incr(key, value) + if err == 'not found' then + new_value = value + _, err = exports.add(key, new_value) + end + + if err == nil then + return new_value, nil + else + return nil, err + end end -------------------------------------------------------------------------------- @@ -173,9 +173,9 @@ exports.replace = replace exports.delete = delete if __TEST__ then - exports.__private__ = { - normalize_key = normalize_key - } + exports.__private__ = { + normalize_key = normalize_key + } end return exports diff --git a/nginx-metrix/storage/namespaces.lua b/nginx-metrix/storage/namespaces.lua index dc4977d..37f3b3f 100644 --- a/nginx-metrix/storage/namespaces.lua +++ b/nginx-metrix/storage/namespaces.lua @@ -9,69 +9,69 @@ local list_cache = {} -- @return table --- local list = function() - local namespaces = storage_dict.get(namespaces_list_key) - if type(namespaces) ~= 'table' then - namespaces = {} - end + local namespaces = storage_dict.get(namespaces_list_key) + if type(namespaces) ~= 'table' then + namespaces = {} + end - return namespaces + return namespaces end --- -- @param namespaces table --- local set = function(namespaces) - assert(type(namespaces) == 'table' or type(namespaces) == 'string', 'namespaces should be table of strings or single string, got' .. type(namespaces)) + assert(type(namespaces) == 'table' or type(namespaces) == 'string', 'namespaces should be table of strings or single string, got' .. type(namespaces)) - if type(namespaces) == 'string' then - namespaces = {namespaces} - end + if type(namespaces) == 'string' then + namespaces = { namespaces } + end - if all(function(namespace) return index(namespace, list_cache) ~= nil end, namespaces) then - return - end + if all(function(namespace) return index(namespace, list_cache) ~= nil end, namespaces) then + return + end - list_cache = list() + list_cache = list() - iter(namespaces):each(function(namespace) - if index(namespace, list_cache) == nil then - table.insert(list_cache, namespace) - end - end) + iter(namespaces):each(function(namespace) + if index(namespace, list_cache) == nil then + table.insert(list_cache, namespace) + end + end) - storage_dict.set(namespaces_list_key, list_cache) + storage_dict.set(namespaces_list_key, list_cache) end --- -- @param namespace --- local activate = function(namespace) - assert(namespace == nil or type(namespace) == 'string', 'Expected string or nil value for namespace, got ' .. type(namespace)) - active_namespace = namespace - set(namespace) + assert(namespace == nil or type(namespace) == 'string', 'Expected string or nil value for namespace, got ' .. type(namespace)) + active_namespace = namespace + set(namespace) end --- -- local reset_active = function() - active_namespace = nil + active_namespace = nil end --- -- local active = function() - return active_namespace + return active_namespace end --- -- @param options table --- local init = function(options) - if options.namespaces then - assert(type(options.namespaces) == 'table', ('Invalid namespaces type. Expected table, got %s.'):format(type(options.namespaces))) + if options.namespaces then + assert(type(options.namespaces) == 'table', ('Invalid namespaces type. Expected table, got %s.'):format(type(options.namespaces))) - set(options.namespaces) - end + set(options.namespaces) + end end -------------------------------------------------------------------------------- @@ -87,11 +87,11 @@ exports.list = list exports.set = set if __TEST__ then - exports.__private__ = { - namespaces_list_key = namespaces_list_key, - get_list_cache = function() return list_cache end, - set_list_cache = function(value) list_cache = value end, - } + exports.__private__ = { + namespaces_list_key = namespaces_list_key, + get_list_cache = function() return list_cache end, + set_list_cache = function(value) list_cache = value end, + } end return exports diff --git a/nginx-metrix/storage/serializer.lua b/nginx-metrix/storage/serializer.lua index 26c7606..c511687 100644 --- a/nginx-metrix/storage/serializer.lua +++ b/nginx-metrix/storage/serializer.lua @@ -8,10 +8,10 @@ local json = require 'dkjson' -- @return string --- local serialize = function(value) - if type(value) == 'table' then - value = serialized_table_token .. json.encode(value) - end - return value + if type(value) == 'table' then + value = serialized_table_token .. json.encode(value) + end + return value end --- @@ -19,15 +19,15 @@ end -- @return mixed --- local unserialize = function(value) - if type(value) == 'string' and value:sub(1, serialized_table_token:len()) == serialized_table_token then - local succ, decoded_value = pcall(function() - return json.decode(value:sub(serialized_table_token:len() + 1)) - end) - if succ then - value = decoded_value - end + if type(value) == 'string' and value:sub(1, serialized_table_token:len()) == serialized_table_token then + local succ, decoded_value = pcall(function() + return json.decode(value:sub(serialized_table_token:len() + 1)) + end) + if succ then + value = decoded_value end - return value + end + return value end -- /serializer @@ -38,4 +38,4 @@ end exports.serialize = serialize exports.unserialize = unserialize -return exports \ No newline at end of file +return exports diff --git a/tests/collectors/request_spec.lua b/tests/collectors/request_spec.lua index e35fe1e..5e1ed61 100644 --- a/tests/collectors/request_spec.lua +++ b/tests/collectors/request_spec.lua @@ -1,118 +1,118 @@ require('tests.bootstrap')(assert) describe('collectors.request', function() - local collector + local collector - setup(function() - package.loaded['nginx-metrix.collectors.request'] = nil - collector = require 'nginx-metrix.collectors.request' - collector.storage = mock({cyclic_incr = function() end, mean_add = function() end,}, true) - end) + setup(function() + package.loaded['nginx-metrix.collectors.request'] = nil + collector = require 'nginx-metrix.collectors.request' + collector.storage = mock({ cyclic_incr = function() end, mean_add = function() end, }, true) + end) - teardown(function() - collector = nil - package.loaded['nginx-metrix.collectors.request'] = nil - _G.ngx = nil - end) + teardown(function() + collector = nil + package.loaded['nginx-metrix.collectors.request'] = nil + _G.ngx = nil + end) - after_each(function() - mock.clear(collector.storage) - end) + after_each(function() + mock.clear(collector.storage) + end) - -- tests - it('valid structure', function() - assert.is_equal('request', collector.name) - assert.is_table(collector.fields) - assert.is_table(collector.fields.rps) - assert.is_table(collector.fields.time_ps) - assert.is_table(collector.fields.internal_rps) - assert.is_table(collector.fields.https_rps) - assert.is_table(collector.fields.length_ps) + -- tests + it('valid structure', function() + assert.is_equal('request', collector.name) + assert.is_table(collector.fields) + assert.is_table(collector.fields.rps) + assert.is_table(collector.fields.time_ps) + assert.is_table(collector.fields.internal_rps) + assert.is_table(collector.fields.https_rps) + assert.is_table(collector.fields.length_ps) - assert.is_table(collector.ngx_phases) - assert.is_function(collector.on_phase) - end) + assert.is_table(collector.ngx_phases) + assert.is_function(collector.on_phase) + end) - it('handles phase log #1', function() - _G.ngx = { - status = 200, - var = { - request_time = 0.01, - https = 'off', - request_length = nil, - }, - req = { - is_internal = function() return false end, - }, - } - collector:on_phase('log') + it('handles phase log #1', function() + _G.ngx = { + status = 200, + var = { + request_time = 0.01, + https = 'off', + request_length = nil, + }, + req = { + is_internal = function() return false end, + }, + } + collector:on_phase('log') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') - assert.spy(collector.storage.cyclic_incr).was.called(1) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) - assert.spy(collector.storage.mean_add).was.called(1) - end) + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') + assert.spy(collector.storage.cyclic_incr).was.called(1) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) + assert.spy(collector.storage.mean_add).was.called(1) + end) - it('handles phase log #2', function() - _G.ngx = { - status = 200, - var = { - request_time = 0.01, - https = 'off', - request_length = nil, - }, - req = { - is_internal = function() return true end, - }, - } - collector:on_phase('log') + it('handles phase log #2', function() + _G.ngx = { + status = 200, + var = { + request_time = 0.01, + https = 'off', + request_length = nil, + }, + req = { + is_internal = function() return true end, + }, + } + collector:on_phase('log') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'internal_rps') - assert.spy(collector.storage.cyclic_incr).was.called(2) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) - assert.spy(collector.storage.mean_add).was.called(1) - end) + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'internal_rps') + assert.spy(collector.storage.cyclic_incr).was.called(2) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) + assert.spy(collector.storage.mean_add).was.called(1) + end) - it('handles phase log #3', function() - _G.ngx = { - status = 200, - var = { - request_time = 0.01, - https = 'on', - request_length = nil, - }, - req = { - is_internal = function() return false end, - }, - } - collector:on_phase('log') + it('handles phase log #3', function() + _G.ngx = { + status = 200, + var = { + request_time = 0.01, + https = 'on', + request_length = nil, + }, + req = { + is_internal = function() return false end, + }, + } + collector:on_phase('log') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'https_rps') - assert.spy(collector.storage.cyclic_incr).was.called(2) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) - assert.spy(collector.storage.mean_add).was.called(1) - end) + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'https_rps') + assert.spy(collector.storage.cyclic_incr).was.called(2) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) + assert.spy(collector.storage.mean_add).was.called(1) + end) - it('handles phase log #4', function() - _G.ngx = { - status = 200, - var = { - request_time = 0.01, - https = 'off', - request_length = 123, - }, - req = { - is_internal = function() return false end, - }, - } - collector:on_phase('log') + it('handles phase log #4', function() + _G.ngx = { + status = 200, + var = { + request_time = 0.01, + https = 'off', + request_length = 123, + }, + req = { + is_internal = function() return false end, + }, + } + collector:on_phase('log') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') - assert.spy(collector.storage.cyclic_incr).was.called(1) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'length_ps', 123) - assert.spy(collector.storage.mean_add).was.called(2) - end) + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') + assert.spy(collector.storage.cyclic_incr).was.called(1) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'time_ps', 0.01) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'length_ps', 123) + assert.spy(collector.storage.mean_add).was.called(2) + end) end) diff --git a/tests/collectors/status_spec.lua b/tests/collectors/status_spec.lua index 1372b2b..1b744e7 100644 --- a/tests/collectors/status_spec.lua +++ b/tests/collectors/status_spec.lua @@ -1,37 +1,37 @@ require('tests.bootstrap')(assert) describe('collectors.status', function() - local collector - - setup(function() - package.loaded['nginx-metrix.collectors.status'] = nil - collector = require 'nginx-metrix.collectors.status' - end) - - teardown(function() - collector = nil - package.loaded['nginx-metrix.collectors.status'] = nil - _G.ngx = nil - end) - - -- tests - it('valid structure', function() - assert.is_equal('status', collector.name) - assert.is_table(collector.fields) - assert.is_table(collector.ngx_phases) - assert.is_function(collector.on_phase) - end) - - it('handles phase log', function() - assert.is_nil(collector.fields['499']) - - collector.storage = mock({cyclic_incr = function() end}, true) - _G.ngx = {status = 499} - collector:on_phase('log') - - assert.spy(collector.storage.cyclic_incr).was.called(1) - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 499) - - assert.is_table(collector.fields['499']) - end) + local collector + + setup(function() + package.loaded['nginx-metrix.collectors.status'] = nil + collector = require 'nginx-metrix.collectors.status' + end) + + teardown(function() + collector = nil + package.loaded['nginx-metrix.collectors.status'] = nil + _G.ngx = nil + end) + + -- tests + it('valid structure', function() + assert.is_equal('status', collector.name) + assert.is_table(collector.fields) + assert.is_table(collector.ngx_phases) + assert.is_function(collector.on_phase) + end) + + it('handles phase log', function() + assert.is_nil(collector.fields['499']) + + collector.storage = mock({ cyclic_incr = function() end }, true) + _G.ngx = { status = 499 } + collector:on_phase('log') + + assert.spy(collector.storage.cyclic_incr).was.called(1) + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 499) + + assert.is_table(collector.fields['499']) + end) end) diff --git a/tests/collectors/upstream_spec.lua b/tests/collectors/upstream_spec.lua index c705918..f8e4d71 100644 --- a/tests/collectors/upstream_spec.lua +++ b/tests/collectors/upstream_spec.lua @@ -1,65 +1,65 @@ require('tests.bootstrap')(assert) describe('collectors.upstream', function() - local collector + local collector - setup(function() - package.loaded['nginx-metrix.collectors.upstream'] = nil - collector = require 'nginx-metrix.collectors.upstream' - collector.storage = mock({cyclic_incr = function() end, mean_add = function() end,}, true) - end) + setup(function() + package.loaded['nginx-metrix.collectors.upstream'] = nil + collector = require 'nginx-metrix.collectors.upstream' + collector.storage = mock({ cyclic_incr = function() end, mean_add = function() end, }, true) + end) - teardown(function() - collector = nil - package.loaded['nginx-metrix.collectors.upstream'] = nil - _G.ngx = nil - end) + teardown(function() + collector = nil + package.loaded['nginx-metrix.collectors.upstream'] = nil + _G.ngx = nil + end) - after_each(function() - mock.clear(collector.storage) - end) + after_each(function() + mock.clear(collector.storage) + end) - -- tests - it('valid structure', function() - assert.is_equal('upstream', collector.name) - assert.is_table(collector.fields) - assert.is_table(collector.fields.rps) - assert.is_table(collector.fields.connect_time) - assert.is_table(collector.fields.header_time) - assert.is_table(collector.fields.response_time) + -- tests + it('valid structure', function() + assert.is_equal('upstream', collector.name) + assert.is_table(collector.fields) + assert.is_table(collector.fields.rps) + assert.is_table(collector.fields.connect_time) + assert.is_table(collector.fields.header_time) + assert.is_table(collector.fields.response_time) - assert.is_table(collector.ngx_phases) - assert.is_function(collector.on_phase) - end) + assert.is_table(collector.ngx_phases) + assert.is_function(collector.on_phase) + end) - it('handles phase log skipped', function() - _G.ngx = { - var = { - upstream_addr = nil, - }, - } - collector:on_phase('log') + it('handles phase log skipped', function() + _G.ngx = { + var = { + upstream_addr = nil, + }, + } + collector:on_phase('log') - assert.spy(collector.storage.cyclic_incr).was_not.called() - assert.spy(collector.storage.mean_add).was_not.called() - end) + assert.spy(collector.storage.cyclic_incr).was_not.called() + assert.spy(collector.storage.mean_add).was_not.called() + end) - it('handles phase log', function() - _G.ngx = { - var = { - upstream_addr = '127.0.0.1', - upstream_connect_time = 1, - upstream_header_time = 2, - upstream_response_time = 3 - }, - } - collector:on_phase('log') + it('handles phase log', function() + _G.ngx = { + var = { + upstream_addr = '127.0.0.1', + upstream_connect_time = 1, + upstream_header_time = 2, + upstream_response_time = 3 + }, + } + collector:on_phase('log') - assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') - assert.spy(collector.storage.cyclic_incr).was.called(1) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'connect_time', 1) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'header_time', 2) - assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'response_time', 3) - assert.spy(collector.storage.mean_add).was.called(3) - end) + assert.spy(collector.storage.cyclic_incr).was.called_with(collector.storage, 'rps') + assert.spy(collector.storage.cyclic_incr).was.called(1) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'connect_time', 1) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'header_time', 2) + assert.spy(collector.storage.mean_add).was.called_with(collector.storage, 'response_time', 3) + assert.spy(collector.storage.mean_add).was.called(3) + end) end) diff --git a/tests/collectors_spec.lua b/tests/collectors_spec.lua index b099f77..1c46e83 100644 --- a/tests/collectors_spec.lua +++ b/tests/collectors_spec.lua @@ -2,170 +2,166 @@ require('tests.bootstrap')(assert) describe('collectors', function() - local collectors - - setup(function() - collectors = require 'nginx-metrix.collectors'; - end) - - teardown(function() - package.loaded['nginx-metrix.collectors'] = nil - end) - - after_each(function() - collectors.__private__.collectors({}) - end) - - it('collector_exists', function() - assert.is_false(collectors.__private__.collector_exists({name='test-collector'})) - - collectors.__private__.collectors({{name='test-collector'}}) - - assert.is_true(collectors.__private__.collector_exists({name='test-collector'})) + local collectors + + setup(function() + collectors = require 'nginx-metrix.collectors'; + end) + + teardown(function() + package.loaded['nginx-metrix.collectors'] = nil + end) + + after_each(function() + collectors.__private__.collectors({}) + end) + + it('collector_exists', function() + assert.is_false(collectors.__private__.collector_exists({ name = 'test-collector' })) + + collectors.__private__.collectors({ { name = 'test-collector' } }) + + assert.is_true(collectors.__private__.collector_exists({ name = 'test-collector' })) + end) + + local validate_data_provider = { + { + collector = nil, + error = 'Collector MUST be a table, got nil: nil', + }, + { + collector = 'invalid collector type', + error = 'Collector MUST be a table, got string: "invalid collector type"', + }, + { + collector = {}, + error = 'Collector must have string property "name", got nil: {}', + }, + { + collector = { name = 13 }, + error = "Collector must have string property \"name\", got number: {\n name = 13\n}", + }, + { + collector = { name = 'existent-collector' }, + error = 'Collector<existent-collector> already exists', + }, + { + collector = { + name = 'test-collector', + ngx_phases = nil, + }, + error = 'Collector<test-collector>.ngx_phases must be an array, given: nil', + }, + { + collector = { + name = 'test-collector', + ngx_phases = 'invalid type', + }, + error = 'Collector<test-collector>.ngx_phases must be an array, given: string', + }, + { + collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]], 13 }, + }, + error = 'Collector<test-collector>.ngx_phases must be an array of strings, given: { "valid phase", 13 }', + }, + { + collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]] }, + on_phase = 'invalid type', + }, + error = 'Collector<test-collector>:on_phase must be a function or callable table, given: string', + }, + { + collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]] }, + on_phase = function() end, + fields = 'invalid type', + }, + error = 'Collector<test-collector>.fields must be a table, given: string', + }, + { + collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]] }, + on_phase = function() end, + fields = { testfield = 'invalid type' }, + }, + error = "Collector<test-collector>.fields must be an table[string, table], given: {\n testfield = \"invalid type\"\n}", + }, + } + + for k, data in pairs(validate_data_provider) do + it('collector_validate failed #' .. k, function() + collectors.__private__.collectors({ { name = 'existent-collector' } }) + + assert.has_error(function() + collectors.__private__.collector_validate(data.collector) + end, + data.error) end) - - local validate_data_provider = { - { - collector = nil, - error = 'Collector MUST be a table, got nil: nil', - }, - { - collector = 'invalid collector type', - error = 'Collector MUST be a table, got string: "invalid collector type"', - }, - { - collector = {}, - error = 'Collector must have string property "name", got nil: {}', - }, - { - collector = {name = 13}, - error = "Collector must have string property \"name\", got number: {\n name = 13\n}", - }, - { - collector = {name = 'existent-collector'}, - error = 'Collector<existent-collector> already exists', - }, - { - collector = { - name = 'test-collector', - ngx_phases = nil, - }, - error = 'Collector<test-collector>.ngx_phases must be an array, given: nil', - }, - { - collector = { - name = 'test-collector', - ngx_phases = 'invalid type', - }, - error = 'Collector<test-collector>.ngx_phases must be an array, given: string', - }, - { - collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]], 13}, - }, - error = 'Collector<test-collector>.ngx_phases must be an array of strings, given: { "valid phase", 13 }', - }, - { - collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]]}, - on_phase = 'invalid type', - }, - error = 'Collector<test-collector>:on_phase must be a function or callable table, given: string', - }, - { - collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]]}, - on_phase = function() end, - fields = 'invalid type', - }, - error = 'Collector<test-collector>.fields must be a table, given: string', - }, - { - collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]]}, - on_phase = function() end, - fields = {testfield = 'invalid type'}, - }, - error = "Collector<test-collector>.fields must be an table[string, table], given: {\n testfield = \"invalid type\"\n}", - }, + end + + it('collector_validate', function() + local test_collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]] }, + on_phase = function() end, + fields = { testfield = {} }, } - for k, data in pairs(validate_data_provider) do - it('collector_validate failed #' .. k, function() - collectors.__private__.collectors({{name = 'existent-collector'}}) - - assert.has_error( - function() - collectors.__private__.collector_validate(data.collector) - end, - data.error - ) - end) - end - - it('collector_validate', function() - local test_collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]]}, - on_phase = function() end, - fields = {testfield = {}}, - } - - assert.has_no.errors( - function() - collectors.__private__.collector_validate(test_collector) - end - ) - end) - - it('collector_extend', function() - local test_collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]]}, - on_phase = function() end, - fields = {testfield = {}}, - } - - local extended_test_collector = collectors.__private__.collector_extend(test_collector) - - assert.is_same(test_collector, extended_test_collector) - - local metatable = getmetatable(extended_test_collector) - assert.is_table(metatable) - assert.is_table(metatable.__index) - assert.is_equal(metatable, metatable.__index) - assert.is_function(metatable.init) - assert.is_function(metatable.handle_ngx_phase) - assert.is_function(metatable.aggregate) - assert.is_function(metatable.get_raw_stats) - assert.is_function(metatable.get_text_stats) - assert.is_function(metatable.get_html_stats) + assert.has_no.errors(function() + collectors.__private__.collector_validate(test_collector) end) + end) + + it('collector_extend', function() + local test_collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]] }, + on_phase = function() end, + fields = { testfield = {} }, + } - it('register', function() - local test_collector = { - name = 'test-collector', - ngx_phases = {[[valid phase]]}, - on_phase = function() end, - fields = {testfield = {}}, - } + local extended_test_collector = collectors.__private__.collector_extend(test_collector) + + assert.is_same(test_collector, extended_test_collector) + + local metatable = getmetatable(extended_test_collector) + assert.is_table(metatable) + assert.is_table(metatable.__index) + assert.is_equal(metatable, metatable.__index) + assert.is_function(metatable.init) + assert.is_function(metatable.handle_ngx_phase) + assert.is_function(metatable.aggregate) + assert.is_function(metatable.get_raw_stats) + assert.is_function(metatable.get_text_stats) + assert.is_function(metatable.get_html_stats) + end) + + it('register', function() + local test_collector = { + name = 'test-collector', + ngx_phases = { [[valid phase]] }, + on_phase = function() end, + fields = { testfield = {} }, + } - local extended_test_collector = collectors.register(test_collector) - assert.is_same(test_collector, extended_test_collector) + local extended_test_collector = collectors.register(test_collector) + assert.is_same(test_collector, extended_test_collector) - assert.is_same({test_collector}, collectors.__private__.collectors()) - end) + assert.is_same({ test_collector }, collectors.__private__.collectors()) + end) - it('all', function() - local test_collectors = {{name = 'existent-collector'}} - collectors.__private__.collectors(test_collectors) + it('all', function() + local test_collectors = { { name = 'existent-collector' } } + collectors.__private__.collectors(test_collectors) - assert.is_table(collectors.all) - assert.is_function(collectors.all.totable) - assert.is_same(test_collectors, collectors.all:totable{}) - end) + assert.is_table(collectors.all) + assert.is_function(collectors.all.totable) + assert.is_same(test_collectors, collectors.all:totable {}) + end) end) diff --git a/tests/listener_spec.lua b/tests/listener_spec.lua index 77300e7..dbc6032 100644 --- a/tests/listener_spec.lua +++ b/tests/listener_spec.lua @@ -2,75 +2,75 @@ require('tests.bootstrap')(assert) describe('listener', function() - local listener + local listener - before_each(function() - package.loaded['nginx-metrix.listener'] = nil - listener = require 'nginx-metrix.listener' - end) - - after_each(function() - package.loaded['nginx-metrix.listener'] = nil - _G.ngx = nil - end) + before_each(function() + package.loaded['nginx-metrix.listener'] = nil + listener = require 'nginx-metrix.listener' + end) - it('attach_collector failed on invalid collector', function() - local collector = { name = 'invalid-collector', ngx_phases = { [[invalid phase]] } } - assert.has_error( - function() - listener.attach_collector(collector) - end, - 'Collector<invalid-collector>.ngx_phases[invalid phase] invalid, phase "invalid phase" does not exists' - ) - end) + after_each(function() + package.loaded['nginx-metrix.listener'] = nil + _G.ngx = nil + end) - it('attach_collector', function() - local collector = { name = 'test-collector-attach', ngx_phases = { [[log]] } } - assert.has_no.errors(function() - listener.attach_collector(collector) - end) + it('attach_collector failed on invalid collector', function() + local collector = { name = 'invalid-collector', ngx_phases = { [[invalid phase]] } } + assert.has_error( + function() + listener.attach_collector(collector) + end, + 'Collector<invalid-collector>.ngx_phases[invalid phase] invalid, phase "invalid phase" does not exists' + ) + end) - assert.is_same({ collector }, listener.__private__.get_handlers().log) + it('attach_collector', function() + local collector = { name = 'test-collector-attach', ngx_phases = { [[log]] } } + assert.has_no.errors(function() + listener.attach_collector(collector) end) - it('handle_phase failed on invalid phase', function() - assert.has.error( - function() - listener.handle_phase('invalid_phase') - end, - 'Invalid ngx phase "invalid_phase" (string)' - ) - end) + assert.is_same({ collector }, listener.__private__.get_handlers().log) + end) - it('handle_phase with passed phase name', function() - local collector = mock({ - name = 'test-collector', - ngx_phases = { [[log]] }, - handle_ngx_phase = function() end - }) + it('handle_phase failed on invalid phase', function() + assert.has.error( + function() + listener.handle_phase('invalid_phase') + end, + 'Invalid ngx phase "invalid_phase" (string)' + ) + end) - assert.has_no.errors(function() - listener.attach_collector(collector) - listener.handle_phase('log') - end) + it('handle_phase with passed phase name', function() + local collector = mock({ + name = 'test-collector', + ngx_phases = { [[log]] }, + handle_ngx_phase = function() end + }) - assert.spy(collector.handle_ngx_phase).was.called_with(collector, 'log') + assert.has_no.errors(function() + listener.attach_collector(collector) + listener.handle_phase('log') end) - it('handle_phase without passed phase name', function() - local collector = mock({ - name = 'test-collector', - ngx_phases = { [[log]] }, - handle_ngx_phase = function() end - }) + assert.spy(collector.handle_ngx_phase).was.called_with(collector, 'log') + end) - _G.ngx = {get_phase = function() return 'log' end} + it('handle_phase without passed phase name', function() + local collector = mock({ + name = 'test-collector', + ngx_phases = { [[log]] }, + handle_ngx_phase = function() end + }) - assert.has_no.errors(function() - listener.attach_collector(collector) - listener.handle_phase() - end) + _G.ngx = { get_phase = function() return 'log' end } - assert.spy(collector.handle_ngx_phase).was.called_with(collector, 'log') + assert.has_no.errors(function() + listener.attach_collector(collector) + listener.handle_phase() end) + + assert.spy(collector.handle_ngx_phase).was.called_with(collector, 'log') + end) end) diff --git a/tests/logger_spec.lua b/tests/logger_spec.lua index ef92626..121bee2 100644 --- a/tests/logger_spec.lua +++ b/tests/logger_spec.lua @@ -2,122 +2,122 @@ require('tests.bootstrap')(assert) describe('logger', function() - local logger + local logger - setup(function() - local ngx = { - log = function() end, - STDERR = 'STDERR', - EMERG = 'EMERG', - ALERT = 'ALERT', - CRIT = 'CRIT', - ERR = 'ERR', - WARN = 'WARN', - NOTICE = 'NOTICE', - INFO = 'INFO', - DEBUG = 'DEBUG', - } - _G.ngx = mock(ngx) + setup(function() + local ngx = { + log = function() end, + STDERR = 'STDERR', + EMERG = 'EMERG', + ALERT = 'ALERT', + CRIT = 'CRIT', + ERR = 'ERR', + WARN = 'WARN', + NOTICE = 'NOTICE', + INFO = 'INFO', + DEBUG = 'DEBUG', + } + _G.ngx = mock(ngx) - logger = require 'nginx-metrix.logger'; - end) + logger = require 'nginx-metrix.logger'; + end) - after_each(function() - mock.clear(_G.ngx) - end) + after_each(function() + mock.clear(_G.ngx) + end) - teardown(function() - _G.ngx = nil - end) + teardown(function() + _G.ngx = nil + end) - it('log', function() - logger.log(ngx.INFO, 'msg') - assert.spy(_G.ngx.log).was.called_with(ngx.INFO, 'msg') + it('log', function() + logger.log(ngx.INFO, 'msg') + assert.spy(_G.ngx.log).was.called_with(ngx.INFO, 'msg') - logger.log(ngx.INFO, { msg = 'msg' }) - assert.spy(_G.ngx.log).was.called_with(ngx.INFO, "{\n msg = \"msg\"\n}") + logger.log(ngx.INFO, { msg = 'msg' }) + assert.spy(_G.ngx.log).was.called_with(ngx.INFO, "{\n msg = \"msg\"\n}") - logger.log(ngx.INFO, 'msg', 'another arg') - assert.spy(_G.ngx.log).was.called_with(ngx.INFO, 'msg :: { "another arg" }') + logger.log(ngx.INFO, 'msg', 'another arg') + assert.spy(_G.ngx.log).was.called_with(ngx.INFO, 'msg :: { "another arg" }') - assert.spy(_G.ngx.log).was.called(3) - end) + assert.spy(_G.ngx.log).was.called(3) + end) - it('stderr', function() - logger.stderr('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.STDERR, 'msg') + it('stderr', function() + logger.stderr('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.STDERR, 'msg') - logger.stderror('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.STDERR, 'msg') + logger.stderror('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.STDERR, 'msg') - assert.spy(_G.ngx.log).was.called(2) - end) + assert.spy(_G.ngx.log).was.called(2) + end) - it('emerg', function() - logger.emerg('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.EMERG, 'msg') + it('emerg', function() + logger.emerg('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.EMERG, 'msg') - logger.emergency('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.EMERG, 'msg') + logger.emergency('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.EMERG, 'msg') - assert.spy(_G.ngx.log).was.called(2) - end) + assert.spy(_G.ngx.log).was.called(2) + end) - it('alert', function() - logger.alert('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.ALERT, 'msg') + it('alert', function() + logger.alert('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.ALERT, 'msg') - assert.spy(_G.ngx.log).was.called(1) - end) + assert.spy(_G.ngx.log).was.called(1) + end) - it('crit', function() - logger.crit('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.CRIT, 'msg') + it('crit', function() + logger.crit('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.CRIT, 'msg') - logger.critical('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.CRIT, 'msg') + logger.critical('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.CRIT, 'msg') - assert.spy(_G.ngx.log).was.called(2) - end) + assert.spy(_G.ngx.log).was.called(2) + end) - it('err', function() - logger.err('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.ERR, 'msg') + it('err', function() + logger.err('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.ERR, 'msg') - logger.error('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.ERR, 'msg') + logger.error('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.ERR, 'msg') - assert.spy(_G.ngx.log).was.called(2) - end) + assert.spy(_G.ngx.log).was.called(2) + end) - it('warn', function() - logger.warn('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.WARN, 'msg') + it('warn', function() + logger.warn('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.WARN, 'msg') - logger.warning('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.WARN, 'msg') + logger.warning('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.WARN, 'msg') - assert.spy(_G.ngx.log).was.called(2) - end) + assert.spy(_G.ngx.log).was.called(2) + end) - it('notice', function() - logger.notice('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.NOTICE, 'msg') + it('notice', function() + logger.notice('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.NOTICE, 'msg') - assert.spy(_G.ngx.log).was.called(1) - end) + assert.spy(_G.ngx.log).was.called(1) + end) - it('info', function() - logger.info('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.INFO, 'msg') + it('info', function() + logger.info('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.INFO, 'msg') - assert.spy(_G.ngx.log).was.called(1) - end) + assert.spy(_G.ngx.log).was.called(1) + end) - it('debug', function() - logger.debug('msg') - assert.spy(_G.ngx.log).was.called_with(ngx.DEBUG, 'msg') + it('debug', function() + logger.debug('msg') + assert.spy(_G.ngx.log).was.called_with(ngx.DEBUG, 'msg') - assert.spy(_G.ngx.log).was.called(1) - end) + assert.spy(_G.ngx.log).was.called(1) + end) end) diff --git a/tests/main_spec.lua b/tests/main_spec.lua index 8eab8ed..fc4a103 100644 --- a/tests/main_spec.lua +++ b/tests/main_spec.lua @@ -1,158 +1,158 @@ require('tests.bootstrap')(assert) describe('main', function() - local match = require 'luassert.match' - - after_each(function() - if package.loaded then - grep('^nginx[-]metrix[.].+', package.loaded):each(function(k, _) - package.loaded[k] = nil - end) - end - end) + local match = require 'luassert.match' - -- tests - it('register_collector', function() - local test_collector = {name='test collector'} + after_each(function() + if package.loaded then + grep('^nginx[-]metrix[.].+', package.loaded):each(function(k, _) + package.loaded[k] = nil + end) + end + end) - local collectors = mock(require 'nginx-metrix.collectors', true) - local listener = mock(require 'nginx-metrix.listener', true) - local scheduler = mock(require 'nginx-metrix.scheduler', true) + -- tests + it('register_collector', function() + local test_collector = { name = 'test collector' } - local metrix = require 'nginx-metrix.main' - collectors.register.on_call_with(test_collector).returns(test_collector) + local collectors = mock(require 'nginx-metrix.collectors', true) + local listener = mock(require 'nginx-metrix.listener', true) + local scheduler = mock(require 'nginx-metrix.scheduler', true) - metrix.register_collector(test_collector) + local metrix = require 'nginx-metrix.main' + collectors.register.on_call_with(test_collector).returns(test_collector) - assert.spy(collectors.register).was.called(1) - assert.spy(collectors.register).was.called_with(test_collector) + metrix.register_collector(test_collector) - assert.spy(listener.attach_collector).was.called(1) - assert.spy(listener.attach_collector).was.called_with(test_collector) + assert.spy(collectors.register).was.called(1) + assert.spy(collectors.register).was.called_with(test_collector) - assert.spy(scheduler.attach_collector).was.called(1) - assert.spy(scheduler.attach_collector).was.called_with(test_collector) - end) + assert.spy(listener.attach_collector).was.called(1) + assert.spy(listener.attach_collector).was.called_with(test_collector) - it('register_builtin_collectors', function() - local metrix = require 'nginx-metrix.main' - spy.on(metrix, 'register_collector') + assert.spy(scheduler.attach_collector).was.called(1) + assert.spy(scheduler.attach_collector).was.called_with(test_collector) + end) - metrix:register_builtin_collectors() + it('register_builtin_collectors', function() + local metrix = require 'nginx-metrix.main' + spy.on(metrix, 'register_collector') - assert.spy(metrix.register_collector).was.called(3) - assert.spy(metrix.register_collector).was.called_with(match.is_table()) - end) + metrix:register_builtin_collectors() - it('init #1', function() - local options = { - skip_register_builtin_collectors = true, - shared_dict = {}, - } - local dict_mock = mock(require 'nginx-metrix.storage.dict', true) - local namespaces_mock = mock(require 'nginx-metrix.storage.namespaces', true) + assert.spy(metrix.register_collector).was.called(3) + assert.spy(metrix.register_collector).was.called_with(match.is_table()) + end) - local metrix = require 'nginx-metrix.main' + it('init #1', function() + local options = { + skip_register_builtin_collectors = true, + shared_dict = {}, + } + local dict_mock = mock(require 'nginx-metrix.storage.dict', true) + local namespaces_mock = mock(require 'nginx-metrix.storage.namespaces', true) - spy.on(metrix, 'register_builtin_collectors') + local metrix = require 'nginx-metrix.main' - assert.has_no.errors(function() - metrix = metrix(options) - end) + spy.on(metrix, 'register_builtin_collectors') - assert.spy(dict_mock.init).was.called(1) - assert.spy(dict_mock.init).was.called_with(options) - assert.spy(namespaces_mock.init).was_not.called() - assert.spy(metrix.register_builtin_collectors).was_not.called() + assert.has_no.errors(function() + metrix = metrix(options) end) - it('init #2', function() - - local vhosts = {[[vhost1]], [[vhost2]]} - local options = { - skip_register_builtin_collectors = false, - shared_dict = {}, - vhosts = vhosts, - } - local dict_mock = mock(require 'nginx-metrix.storage.dict', true) - local namespaces_mock = mock(require 'nginx-metrix.storage.namespaces', true) + assert.spy(dict_mock.init).was.called(1) + assert.spy(dict_mock.init).was.called_with(options) + assert.spy(namespaces_mock.init).was_not.called() + assert.spy(metrix.register_builtin_collectors).was_not.called() + end) - local metrix = require 'nginx-metrix.main' + it('init #2', function() - spy.on(metrix, 'register_builtin_collectors') + local vhosts = { [[vhost1]], [[vhost2]] } + local options = { + skip_register_builtin_collectors = false, + shared_dict = {}, + vhosts = vhosts, + } + local dict_mock = mock(require 'nginx-metrix.storage.dict', true) + local namespaces_mock = mock(require 'nginx-metrix.storage.namespaces', true) - assert.has_no.errors(function() - metrix = metrix(options) - end) + local metrix = require 'nginx-metrix.main' - assert.spy(dict_mock.init).was.called(1) - assert.spy(dict_mock.init).was.called_with(options) - assert.spy(namespaces_mock.init).was.called(1) - assert.spy(namespaces_mock.init).was.called_with({namespaces=vhosts}) - assert.spy(metrix.register_builtin_collectors).was.called(1) - end) - - it('init_scheduler', function() - local scheduler = mock(require 'nginx-metrix.scheduler', true) + spy.on(metrix, 'register_builtin_collectors') - local metrix = require 'nginx-metrix.main' - metrix.init_scheduler() - - assert.spy(scheduler.start).was.called(1) + assert.has_no.errors(function() + metrix = metrix(options) end) - it('handle_ngx_phase and show', function() - local ngx_mock = require 'tests.ngx_mock'() - - local shared_dict = ngx_mock.define_shared_dict('test-behavior-dict') - - local metrix = require 'nginx-metrix.main'({ - skip_register_builtin_collectors = true, - shared_dict = shared_dict, - vhosts = {'first.com', 'second.com', 'third.com'} - }) - - local test_collector = mock({ - name = 'test-collector', - ngx_phases = {[[log]]}, - on_phase = function() end, - fields = {testfield = {}}, - }) - - metrix.register_collector(test_collector) - - ngx.var.hostname = 'first.com' - metrix.handle_ngx_phase('log') - metrix.handle_ngx_phase('log') - ngx.var.hostname = 'second.com' - metrix.handle_ngx_phase('log') - - assert.spy(test_collector.on_phase).was.called_with(test_collector, 'log') - assert.spy(test_collector.on_phase).was.called(3) - - ngx.req.__URI_ARGS__.format = 'json' - - stub(ngx, 'say') - - metrix.show({vhosts_filter='.*'}) - assert.spy(ngx.say).was.called(1) - assert.spy(ngx.say).was.called_with(match.json_equal({ - ['service'] = "nginx-metrix", - ['first.com'] = {['test-collector'] = {['testfield'] = 0},['vhost'] = "first.com"}, - ['second.com'] = {['test-collector'] = {['testfield'] = 0},['vhost'] = "second.com"}, - ['third.com'] = {['test-collector'] = {['testfield'] = 0},['vhost'] = "third.com"}, - })) - ngx.say:revert() - - stub(ngx, 'say') - - metrix.show({vhosts_filter='first.com'}) - assert.spy(ngx.say).was.called(1) - assert.spy(ngx.say).was.called_with(match.json_equal({ - ['service'] = "nginx-metrix", - ['test-collector'] = {['testfield'] = 0}, - ['vhost'] = "first.com", - })) - ngx.say:revert() - end) + assert.spy(dict_mock.init).was.called(1) + assert.spy(dict_mock.init).was.called_with(options) + assert.spy(namespaces_mock.init).was.called(1) + assert.spy(namespaces_mock.init).was.called_with({ namespaces = vhosts }) + assert.spy(metrix.register_builtin_collectors).was.called(1) + end) + + it('init_scheduler', function() + local scheduler = mock(require 'nginx-metrix.scheduler', true) + + local metrix = require 'nginx-metrix.main' + metrix.init_scheduler() + + assert.spy(scheduler.start).was.called(1) + end) + + it('handle_ngx_phase and show', function() + local ngx_mock = require 'tests.ngx_mock'() + + local shared_dict = ngx_mock.define_shared_dict('test-behavior-dict') + + local metrix = require 'nginx-metrix.main'({ + skip_register_builtin_collectors = true, + shared_dict = shared_dict, + vhosts = { 'first.com', 'second.com', 'third.com' } + }) + + local test_collector = mock({ + name = 'test-collector', + ngx_phases = { [[log]] }, + on_phase = function() end, + fields = { testfield = {} }, + }) + + metrix.register_collector(test_collector) + + ngx.var.hostname = 'first.com' + metrix.handle_ngx_phase('log') + metrix.handle_ngx_phase('log') + ngx.var.hostname = 'second.com' + metrix.handle_ngx_phase('log') + + assert.spy(test_collector.on_phase).was.called_with(test_collector, 'log') + assert.spy(test_collector.on_phase).was.called(3) + + ngx.req.__URI_ARGS__.format = 'json' + + stub(ngx, 'say') + + metrix.show({ vhosts_filter = '.*' }) + assert.spy(ngx.say).was.called(1) + assert.spy(ngx.say).was.called_with(match.json_equal({ + ['service'] = "nginx-metrix", + ['first.com'] = { ['test-collector'] = { ['testfield'] = 0 }, ['vhost'] = "first.com" }, + ['second.com'] = { ['test-collector'] = { ['testfield'] = 0 }, ['vhost'] = "second.com" }, + ['third.com'] = { ['test-collector'] = { ['testfield'] = 0 }, ['vhost'] = "third.com" }, + })) + ngx.say:revert() + + stub(ngx, 'say') + + metrix.show({ vhosts_filter = 'first.com' }) + assert.spy(ngx.say).was.called(1) + assert.spy(ngx.say).was.called_with(match.json_equal({ + ['service'] = "nginx-metrix", + ['test-collector'] = { ['testfield'] = 0 }, + ['vhost'] = "first.com", + })) + ngx.say:revert() + end) end) diff --git a/tests/ngx_mock.lua b/tests/ngx_mock.lua index 7c6ba32..c5e0725 100644 --- a/tests/ngx_mock.lua +++ b/tests/ngx_mock.lua @@ -1,165 +1,165 @@ _G.ngx = {} local ngx_origin = { - header = { - content_type = nil - }, - localtime = function() return os.date ('%F %T') end, - req = { - __INTERNAL__ = false, - __URI_ARGS__ = {}, - __HEADERS__ = {['accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'}, - is_internal = function() return ngx.req.__INTERNAL__ end, - get_uri_args = function() return ngx.req.__URI_ARGS__ end, - get_headers = function() return ngx.req.__HEADERS__ end, - }, - say = function(...) print(require 'inspect'({...})); print(...) end, - shared = {}, - status = 200, - var = { - hostname = '_', - https = nil, - request_length = 128, - request_time = 0.123, - upstream_addr = nil, - upstream_connect_time = 0.01, - upstream_header_time = 0.02, - upstream_response_time = 0.321, - }, + header = { + content_type = nil + }, + localtime = function() return os.date('%F %T') end, + req = { + __INTERNAL__ = false, + __URI_ARGS__ = {}, + __HEADERS__ = { ['accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' }, + is_internal = function() return ngx.req.__INTERNAL__ end, + get_uri_args = function() return ngx.req.__URI_ARGS__ end, + get_headers = function() return ngx.req.__HEADERS__ end, + }, + say = function(...) print(require 'inspect'({ ... })); print(...) end, + shared = {}, + status = 200, + var = { + hostname = '_', + https = nil, + request_length = 128, + request_time = 0.123, + upstream_addr = nil, + upstream_connect_time = 0.01, + upstream_header_time = 0.02, + upstream_response_time = 0.321, + }, } local reset = function() - _G.ngx = copy(ngx_origin) + _G.ngx = copy(ngx_origin) end local create_shared_dict = function() - local function assert_key(key) - assert(type(key) == 'string', ('Invalid key type; Expected string; Got %s'):format(type(key))) - assert(key ~= '', 'key is empty') + local function assert_key(key) + assert(type(key) == 'string', ('Invalid key type; Expected string; Got %s'):format(type(key))) + assert(key ~= '', 'key is empty') + end + + local function assert_value(value) + local allowed_types = { ['nil'] = true, ['boolean'] = true, ['number'] = true, ['string'] = true, } + assert(allowed_types[type(value)], ('Invalid value type; Expected boolean, number, string or nil; Got %s'):format(type(value))) + end + + local function assert_flags(flags) + assert(flags == nil or type(flags) == 'number', ('Invalid flags type; Expected number; Got %s'):format(type(flags))) + end + + local shared_dict_meta_table = {} + + function shared_dict_meta_table:get(key) + assert_key(key) + local record = self[key] + local value = record and record['value'] + local flags = record and record['flags'] or 0 + return value, flags + end + + function shared_dict_meta_table:get_stale(key) + local value, flags = self:get(key) + return value, flags, false + end + + function shared_dict_meta_table:set(key, value, _, flags) + assert_key(key) + assert_value(value) + assert_flags(flags) + + self[key] = { ['value'] = value, ['flags'] = (flags or 0) } + return true, nil, false + end + + function shared_dict_meta_table:safe_set(key, value, exptime, flags) + local success, err, _ = self:set(key, value, exptime, flags) + return success, err + end + + function shared_dict_meta_table:add(key, value, exptime, flags) + assert_key(key) + assert_value(value) + assert_flags(flags) + + if self[key] ~= nil then + return false, 'exists' end - local function assert_value(value) - local allowed_types = {['nil']=true, ['boolean']=true, ['number']=true, ['string']=true,} - assert(allowed_types[type(value)], ('Invalid value type; Expected boolean, number, string or nil; Got %s'):format(type(value))) - end + return self:set(key, value, exptime, flags) + end - local function assert_flags(flags) - assert(flags == nil or type(flags) == 'number', ('Invalid flags type; Expected number; Got %s'):format(type(flags))) - end + function shared_dict_meta_table:safe_add(key, value, exptime, flags) + local success, err, _ = self:add(key, value, exptime, flags) + return success, err + end - local shared_dict_meta_table = {} + function shared_dict_meta_table:replace(key, value, exptime, flags) + assert_key(key) + assert_value(value) + assert_flags(flags) - function shared_dict_meta_table:get(key) - assert_key(key) - local record = self[key] - local value = record and record['value'] - local flags = record and record['flags'] or 0 - return value, flags + if self[key] == nil then + return false, 'not found' end - function shared_dict_meta_table:get_stale(key) - local value, flags = self:get(key) - return value, flags, false - end - - function shared_dict_meta_table:set(key, value, _, flags) - assert_key(key) - assert_value(value) - assert_flags(flags) - - self[key] = {['value']=value, ['flags']=(flags or 0)} - return true, nil, false - end + return self:set(key, value, exptime, flags) + end - function shared_dict_meta_table:safe_set(key, value, exptime, flags) - local success, err, _ = self:set(key, value, exptime, flags) - return success, err - end + function shared_dict_meta_table:delete(key) + assert_key(key) - function shared_dict_meta_table:add(key, value, exptime, flags) - assert_key(key) - assert_value(value) - assert_flags(flags) + self[key] = nil + end - if self[key] ~= nil then - return false, 'exists' - end + function shared_dict_meta_table:incr(key, value) + assert_key(key) + assert(type(value) == 'number', ('Invalid value type; Expected number; Got %s'):format(type(value))) - return self:set(key, value, exptime, flags) + if self[key] == nil then + return nil, 'not found' end - function shared_dict_meta_table:safe_add(key, value, exptime, flags) - local success, err, _ = self:add(key, value, exptime, flags) - return success, err + if type(self[key].value) ~= 'number' then + return nil, 'not a number' end - function shared_dict_meta_table:replace(key, value, exptime, flags) - assert_key(key) - assert_value(value) - assert_flags(flags) - - if self[key] == nil then - return false, 'not found' - end - - return self:set(key, value, exptime, flags) - end + self[key].value = self[key].value + value - function shared_dict_meta_table:delete(key) - assert_key(key) + return self[key].value, nil + end - self[key] = nil + function shared_dict_meta_table:flush_all() + for k, _ in pairs(self) do + self[k] = nil end + end - function shared_dict_meta_table:incr(key, value) - assert_key(key) - assert(type(value) == 'number', ('Invalid value type; Expected number; Got %s'):format(type(value))) + function shared_dict_meta_table.flush_expired() + end - if self[key] == nil then - return nil, 'not found' - end + function shared_dict_meta_table:get_keys() + local keyset = {} - if type(self[key].value) ~= 'number' then - return nil, 'not a number' - end - - self[key].value = self[key].value + value - - return self[key].value, nil + for k, _ in pairs(self) do + table.insert(keyset, k) end - function shared_dict_meta_table:flush_all() - for k,_ in pairs(self) do - self[k] = nil - end - end - - function shared_dict_meta_table.flush_expired() - end - - function shared_dict_meta_table:get_keys() - local keyset={} - - for k,_ in pairs(self) do - table.insert(keyset, k) - end - - return keyset - end + return keyset + end - -- -- -- -- -- - shared_dict_meta_table.__index = shared_dict_meta_table + -- -- -- -- -- + shared_dict_meta_table.__index = shared_dict_meta_table - local dict = {} - setmetatable(dict, shared_dict_meta_table) + local dict = {} + setmetatable(dict, shared_dict_meta_table) - return dict + return dict end local define_shared_dict = function(name) - ngx.shared[name] = create_shared_dict() + ngx.shared[name] = create_shared_dict() - return ngx.shared[name] + return ngx.shared[name] end local exports = {} @@ -168,10 +168,10 @@ exports.create_shared_dict = create_shared_dict exports.define_shared_dict = define_shared_dict setmetatable(exports, { - __call = function(_) - reset() - return exports - end, + __call = function(_) + reset() + return exports + end, }) return exports diff --git a/tests/storage/namespaces_spec.lua b/tests/storage/namespaces_spec.lua index 40e752d..f687af9 100644 --- a/tests/storage/namespaces_spec.lua +++ b/tests/storage/namespaces_spec.lua @@ -2,104 +2,102 @@ require('tests.bootstrap')(assert) describe('storage.namespaces', function() - local namespaces - local dict_mock - - setup(function() - package.loaded['nginx-metrix.storage.dict'] = nil - package.loaded['nginx-metrix.storage.namespaces'] = nil - dict_mock = mock(require 'nginx-metrix.storage.dict', true) - package.loaded['nginx-metrix.storage.dict'] = dict_mock - namespaces = require 'nginx-metrix.storage.namespaces' + local namespaces + local dict_mock + + setup(function() + package.loaded['nginx-metrix.storage.dict'] = nil + package.loaded['nginx-metrix.storage.namespaces'] = nil + dict_mock = mock(require 'nginx-metrix.storage.dict', true) + package.loaded['nginx-metrix.storage.dict'] = dict_mock + namespaces = require 'nginx-metrix.storage.namespaces' + end) + + teardown(function() + mock.revert(dict_mock) + package.loaded['nginx-metrix.storage.dict'] = nil + package.loaded['nginx-metrix.storage.namespaces'] = nil + end) + + after_each(function() + namespaces.__private__.set_list_cache({}) + end) + + it('init without namespaces list', function() + assert.has_no.errors(function() + namespaces.init({}) end) - teardown(function() - mock.revert(dict_mock) - package.loaded['nginx-metrix.storage.dict'] = nil - package.loaded['nginx-metrix.storage.namespaces'] = nil - end) + assert.spy(dict_mock.set).was_not.called() + end) - after_each(function() - namespaces.__private__.set_list_cache({}) - end) + it('init failed on invalid namespaces list type', function() + assert.has_error(function() + namespaces.init({ namespaces = 123123123 }) + end, + 'Invalid namespaces type. Expected table, got number.') + end) - it('init without namespaces list', function() - assert.has_no.errors(function() - namespaces.init({}) - end) + it('set/list', function() + local test_list = { [[ns_set_list]] } - assert.spy(dict_mock.set).was_not.called() - end) + local s = stub.new(dict_mock, 'get') + s.on_call_with(namespaces.__private__.namespaces_list_key).returns(test_list) - it('init failed on invalid namespaces list type', function() - assert.has_error( - function() - namespaces.init({namespaces = 123123123}) - end, - 'Invalid namespaces type. Expected table, got number.' - ) + assert.has_no.errors(function() + namespaces.set(test_list) end) - it('set/list', function() - local test_list = { [[ns_set_list]] } - - local s = stub.new(dict_mock, 'get') - s.on_call_with(namespaces.__private__.namespaces_list_key).returns(test_list) - - assert.has_no.errors(function() - namespaces.set(test_list) - end) - - assert.spy(dict_mock.get).was.called_with(namespaces.__private__.namespaces_list_key) - assert.spy(dict_mock.set).was.called_with(namespaces.__private__.namespaces_list_key, test_list) + assert.spy(dict_mock.get).was.called_with(namespaces.__private__.namespaces_list_key) + assert.spy(dict_mock.set).was.called_with(namespaces.__private__.namespaces_list_key, test_list) - local actual_list + local actual_list - assert.has_no.errors(function() - actual_list = namespaces.list() - end) - - assert.spy(dict_mock.get).was.called_with(namespaces.__private__.namespaces_list_key) - assert.is_table(actual_list) - assert.is_same(test_list, actual_list) + assert.has_no.errors(function() + actual_list = namespaces.list() + end) - namespaces.set(test_list) - namespaces.set(test_list) + assert.spy(dict_mock.get).was.called_with(namespaces.__private__.namespaces_list_key) + assert.is_table(actual_list) + assert.is_same(test_list, actual_list) - assert.spy(dict_mock.get).was.called(2) - assert.spy(dict_mock.set).was.called(1) - end) + namespaces.set(test_list) + namespaces.set(test_list) + assert.spy(dict_mock.get).was.called(2) + assert.spy(dict_mock.set).was.called(1) + end) - it('init with valid namespaces list', function() - local test_list = { [[ns1]], [[ns2]] } - stub.new(dict_mock, 'get').on_call_with(namespaces.__private__.namespaces_list_key).returns({}) + it('init with valid namespaces list', function() + local test_list = { [[ns1]], [[ns2]] } - assert.has_no.errors(function() - namespaces.init({ namespaces = test_list }) - end) + stub.new(dict_mock, 'get').on_call_with(namespaces.__private__.namespaces_list_key).returns({}) - assert.spy(dict_mock.get).was.called_with(namespaces.__private__.namespaces_list_key) - assert.spy(dict_mock.set).was.called_with(namespaces.__private__.namespaces_list_key, test_list) + assert.has_no.errors(function() + namespaces.init({ namespaces = test_list }) end) + assert.spy(dict_mock.get).was.called_with(namespaces.__private__.namespaces_list_key) + assert.spy(dict_mock.set).was.called_with(namespaces.__private__.namespaces_list_key, test_list) + end) - it('active/activate/reset_active', function() - local test_ns = 'ns_active' - assert.is_nil(namespaces.active()) + it('active/activate/reset_active', function() + local test_ns = 'ns_active' - assert.has_no.errors(function() - namespaces.activate(test_ns) - end) + assert.is_nil(namespaces.active()) - assert.is_equal(test_ns, namespaces.active()) + assert.has_no.errors(function() + namespaces.activate(test_ns) + end) - assert.has_no.errors(function() - namespaces.reset_active() - end) + assert.is_equal(test_ns, namespaces.active()) - assert.is_nil(namespaces.active()) + assert.has_no.errors(function() + namespaces.reset_active() end) + + assert.is_nil(namespaces.active()) + end) end)