Skip to content

Commit

Permalink
Adding support for envvar DOCKER_SECRETS_PATH_GLOB
Browse files Browse the repository at this point in the history
This will allow docker installations to supply the config/secret
files holding secret tokens and input configuration using
path globs.

Also handled some New Relic errors.
  • Loading branch information
hammady committed Nov 12, 2017
1 parent fa216ee commit dd717b5
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 18 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ measure average response time in the past 3 minutes. Default value is 5.
- `LOG_LEVEL`: Accepted values here are: `DEBUG`, `INFO` (default), `WARN`, `ERROR`, `FATAL`.
Log output goes to stdout.

- `DOCKER_SECRETS_PATH_GLOB`: Path glob containing environment files to load.
This is useful if running from a docker swarm mode environment where one or more of the above
environment variables are set using `docker config` or `docker secret`.
These files should be in the form `VARIABLE=value`.
A typical value of this variable would be: `{/run/secrets/*,/config1,/config2}`

### Configuration file

The configuration file (determined by `-f FILE` command line parameter) should be in the following form:
Expand Down
25 changes: 25 additions & 0 deletions lib/scaltainer/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,42 @@ def self.parse(args)
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
puts "\nEnvironment variables: \n"
puts "- DOCKER_URL: defaults to local socket"
puts "- HIREFIRE_TOKEN"
puts "- NEW_RELIC_LICENSE_KEY"
puts "- RESPONSE_TIME_WINDOW: defaults to 5"
puts "- LOG_LEVEL: defaults to INFO"
puts "- DOCKER_SECRETS_PATH_GLOB: path glob containing env files to load"
exit
end
end.parse!

statefile = "#{configfile}.state" unless statefile

raise ConfigurationError.new("File not found: #{configfile}") unless File.exists?(configfile)

load_env

logger = Logger.new(STDOUT)
logger.level = %w(debug info warn error fatal unknown).find_index((ENV['LOG_LEVEL'] || '').downcase) || 1

return configfile, statefile, logger
end

private

def self.load_env
# load docker configs/secrets
path = ENV['DOCKER_SECRETS_PATH_GLOB']
unless path.nil?
files = Dir[path]
unless files.empty?
require 'dotenv'
Dotenv.load(*files)
puts ENV['NEW_RELIC_LICENSE_KEY']
end
end
end
end
end
9 changes: 6 additions & 3 deletions lib/scaltainer/newrelic/metrics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def get_avg_response_time(app_id, from, to)
http_call_count, http_average_call_time = response_array[0]["call_count"], response_array[0]["average_call_time"]
webfe_call_count, webfe_average_response_time = response_array[1]["call_count"], response_array[1]["average_response_time"]

http_average_call_time + (1.0 * webfe_call_count * webfe_average_response_time / http_call_count)
http_average_call_time + (1.0 * webfe_call_count * webfe_average_response_time / http_call_count) rescue 0.0/0
end

private
Expand All @@ -33,9 +33,12 @@ def request(conn, metric_names_array, time_range)
responses = conn.requests requests
responses.map {|response|
body = JSON.parse(response.body)
body["metric_data"]["metrics"][0]["timeslices"][0]["values"]
if body["error"] && body["error"]["title"]
raise body["error"]["title"]
else
body["metric_data"]["metrics"][0]["timeslices"][0]["values"] rescue {}
end
}
end

end
end
2 changes: 1 addition & 1 deletion lib/scaltainer/service_types/web.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def get_metrics(services)
begin
metric = nr.get_avg_response_time app_id, from, to
rescue => e
raise NetworkError.new "Could not retrieve metrics from New Relic API for #{service_name}.\n#{e.message}"
raise NetworkError.new "Could not retrieve metrics from New Relic API for #{service_name}: #{e.message}"
end

hash.merge!(service_name => metric)
Expand Down
2 changes: 1 addition & 1 deletion lib/scaltainer/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Scaltainer
VERSION = "0.1.0"
VERSION = "0.1.1"
end
1 change: 1 addition & 0 deletions scaltainer.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ Gem::Specification.new do |spec|

spec.add_runtime_dependency 'excon', '>= 0.47.0'
spec.add_runtime_dependency "docker-api"
spec.add_runtime_dependency "dotenv"
end
65 changes: 52 additions & 13 deletions spec/scaltainer/newrelic/metrics_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@
let(:app_id) { 100 }
let(:http_query_regex) {/HttpDispatcher/}
let(:webfe_query_regex) {/WebFrontend\/QueueTime/}
let(:http_response) {
'{"metric_data":{"metrics":[{"timeslices":[{"values":{
"average_call_time":100,"call_count":100000}}]}]}}'
}
let(:webfe_response) {
'{"metric_data":{"metrics":[{"timeslices":[{"values":{
"average_response_time":10,"call_count":100000}}]}]}}'
}
let(:from){ Time.now }
let(:to){ Time.now }

Expand All @@ -24,16 +16,63 @@
path: "/v2/applications/#{app_id}/metrics/data.json"
}, lambda {|request_params|
if request_params[:query].match(http_query_regex)
{body: http_response, status: 200}
{body: http_response_body, status: http_response_code}
elsif request_params[:query].match(webfe_query_regex)
{body: webfe_response, status: 200}
{body: webfe_response_body, status: webfe_response_code}
end
})
}

it 'computes correct average response time' do
expect(Newrelic::Metrics.new(nil).get_avg_response_time(app_id, from, to)).to \
eq 110
context 'when no metrics returned' do
let(:http_response_body) {
'{"metric_data":{"metrics":[]}}'
}
let(:http_response_code) { 200 }
let(:webfe_response_body) {
'{"metric_data":{"metrics":[]}}'
}
let(:webfe_response_code) { 200 }
let(:nan) { 0.0/0 }

it 'returns NaN' do
expect(Newrelic::Metrics.new(nil).get_avg_response_time(app_id, from, to).nan?).to \
eq true
end
end

context 'when error returned' do
let(:http_response_body) {
'{"error":{"title":"NEWRELIC_ERROR"}}'
}
let(:http_response_code) { 400 }
let(:webfe_response_body) {
'{"error":{"title":"NEWRELIC_ERROR"}}'
}
let(:webfe_response_code) { 400 }
let(:nan) { 0.0/0 }

it 'raises the error' do
expect{Newrelic::Metrics.new(nil).get_avg_response_time(app_id, from, to)}.to \
raise_error /NEWRELIC_ERROR/
end
end

context 'when valid metrics returned' do
let(:http_response_body) {
'{"metric_data":{"metrics":[{"timeslices":[{"values":{
"average_call_time":100,"call_count":100000}}]}]}}'
}
let(:http_response_code) { 200 }
let(:webfe_response_body) {
'{"metric_data":{"metrics":[{"timeslices":[{"values":{
"average_response_time":10,"call_count":100000}}]}]}}'
}
let(:webfe_response_code) { 200 }

it 'computes correct average response time' do
expect(Newrelic::Metrics.new(nil).get_avg_response_time(app_id, from, to)).to \
eq 110
end
end
end
end # describe Metrics

0 comments on commit dd717b5

Please sign in to comment.