Skip to content

Commit

Permalink
[prometheus] create prometheus exporter skeleton
Browse files Browse the repository at this point in the history
  • Loading branch information
mikz committed Feb 28, 2018
1 parent eb0e35e commit 780f029
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Error loading policy chain configuration JSON with null value [PR #626](https://github.com/3scale/apicast/pull/626)
- Splitted `resolv.conf` in lines,to avoid commented lines [PR #618](https://github.com/3scale/apicast/pull/618)

## Added

- New `metrics` phase that runs when prometheus is collecting metrics [PR #629](https://github.com/3scale/apicast/pull/629)

## [3.2.0-beta1] - 2018-02-20

## Added
Expand Down
1 change: 1 addition & 0 deletions gateway/Roverfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ luassert 1.7.10-0||testing
luasystem 0.2.1-0||testing
markdown 0.33-1||development
mediator_lua 1.1.2-0||testing
nginx-lua-prometheus 0.20171117-4||production
penlight 1.5.4-1||production,development,testing
router 2.1-0||production
say 1.3-1||testing
1 change: 1 addition & 0 deletions gateway/apicast-scm-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies = {
'liquid',
'argparse',
'penlight',
'nginx-lua-prometheus',
}
build = {
type = "make",
Expand Down
18 changes: 18 additions & 0 deletions gateway/conf/nginx.conf.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ http {
{% include "conf.d/apicast.conf" %}
}

{% if port.metrics %}
lua_shared_dict prometheus_metrics 16M;
server {
access_log off;
listen {{ port.metrics }};
server_name metrics prometheus _;

location /metrics {
content_by_lua_block { require('apicast.executor'):metrics() }
}

location /nginx_status {
internal;
stub_status;
}
}
{% endif %}

{% for file in "sites.d/*.conf" | filesystem %}
{% include file %}
{% endfor %}
Expand Down
3 changes: 2 additions & 1 deletion gateway/config/development.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ return {
lua_code_cache = 'on',
configuration_loader = 'lazy',
configuration_cache = 0,
configuration = data_url('application/json', configuration)
configuration = data_url('application/json', configuration),
port = { metrics = 9421 }, -- see https://github.com/prometheus/prometheus/wiki/Default-port-allocations
}
8 changes: 8 additions & 0 deletions gateway/src/apicast/executor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require('apicast.loader') -- to load code from deprecated paths
local PolicyChain = require('apicast.policy_chain')
local policy = require('apicast.policy')
local linked_list = require('apicast.linked_list')
local prometheus = require('apicast.prometheus')

local setmetatable = setmetatable

Expand Down Expand Up @@ -58,4 +59,11 @@ function _M:context(phase)
return shared_build_context(self)
end

local metrics = _M.metrics
--- Render metrics from all policies.
function _M:metrics(...)
metrics(self, ...)
return prometheus:collect()
end

return _M.new(PolicyChain.default())
2 changes: 1 addition & 1 deletion gateway/src/apicast/policy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ local PHASES = {
'rewrite', 'access',
'content', 'balancer',
'header_filter', 'body_filter',
'post_action', 'log'
'post_action', 'log', 'metrics',
}

local setmetatable = setmetatable
Expand Down
23 changes: 23 additions & 0 deletions gateway/src/apicast/prometheus.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
local prometheus = require('nginx.prometheus')
local assert = assert
local dict = 'prometheus_metrics'

if ngx.shared[dict] then
local init = prometheus.init(dict)

local metrics = { }
local __call = function(_, type, name, ...)
local metric_name = assert(name, 'missing metric name')

if not metrics[metric_name] then
metrics[metric_name] = init[assert(type, 'missing metric type')](init, metric_name, ...)
end

return metrics[metric_name]
end

return setmetatable({ }, { __call = __call, __index = init })
else
local noop = function() end
return setmetatable({ collect = noop }, { __call = noop })
end
2 changes: 1 addition & 1 deletion spec/policy_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('policy', function()
'rewrite', 'access',
'content', 'balancer',
'header_filter', 'body_filter',
'post_action', 'log'
'post_action', 'log', 'metrics'
}

describe('.new', function()
Expand Down
41 changes: 41 additions & 0 deletions spec/prometheus_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

describe('prometheus', function()
before_each(function() package.loaded['apicast.prometheus'] = nil end)

describe('shared dictionary is missing', function()
before_each(function() ngx.shared.prometheus_metrics = nil end)

it('can be called', function()
assert.is_nil(require('apicast.prometheus')())
end)

it('can be collected', function()
assert.is_nil(require('apicast.prometheus'):collect())
end)
end)

describe('shared dictionary is there', function()
before_each(function()
ngx.shared.prometheus_metrics = {
set = function() end,
get_keys = function() return {} end
}
end)

local prometheus

before_each(function()
prometheus = assert(require('apicast.prometheus'))
end)

it('can be called', function()
assert.is_table(prometheus('counter', 'some_metric'))
end)

it('can be collected', function()
ngx.header = { }
assert.is_nil(require('apicast.prometheus'):collect())
end)
end)

end)

0 comments on commit 780f029

Please sign in to comment.