diff --git a/check_graphite.gemspec b/check_graphite.gemspec index 2532fa2..756db5b 100644 --- a/check_graphite.gemspec +++ b/check_graphite.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |s| # specify any dependencies here; for example: # s.add_development_dependency "rspec" - s.add_runtime_dependency "linear-regression" + s.add_runtime_dependency "linear-regression", "~> 0.0.2" s.add_runtime_dependency "nagios_check" s.add_development_dependency "rake" diff --git a/lib/attime.rb b/lib/attime.rb index be0b6c5..897288e 100644 --- a/lib/attime.rb +++ b/lib/attime.rb @@ -36,24 +36,26 @@ module CheckGraphite "year" => 365 * DAY, "years" => "year", } - EXPR = /([+-])?([0-9]*)(.*)/ + EXPR = /^([+-])?([0-9.]*)(.*)$/ def self.attime(text, time = Time.now) match = EXPR.match(text) raise "Unparseable time period #{text}" unless match sign, scalar, unit = match[1..3] - raise "Missing scalar in time #{text}" if scalar == "" - raise "Missing unit in #{text}" if unit == "" - time + Integer(scalar) * lookup(unit) * (sign == "-" ? -1 : 1) + raise "Missing scalar in time #{text}" if scalar.empty? + raise "Missing unit in #{text}" if unit.empty? + time + Float(scalar) * lookup(unit) * (sign == "-" ? -1 : 1) end private def self.lookup(unit) x = UNITS[unit.downcase] - raise "Bad unit #{unit}" unless x - if x.is_a? String + case x + when String lookup(x) + when nil + raise "Bad unit #{unit}" else x end diff --git a/lib/check_graphite/projection.rb b/lib/check_graphite/projection.rb index 722704d..3239626 100644 --- a/lib/check_graphite/projection.rb +++ b/lib/check_graphite/projection.rb @@ -7,8 +7,8 @@ module CheckGraphite module Projection def self.included(base) base.on '--projection FUTURE_TIMEFRAME', :default => '2days' do |timeframe| - options.send('processor=', method(:projected_value)) - options.send('timeframe=', timeframe) + options.send(:processor=, method(:projected_value)) + options.send(:timeframe=, timeframe) end end diff --git a/spec/attime_spec.rb b/spec/attime_spec.rb index c73ecb5..f49996e 100644 --- a/spec/attime_spec.rb +++ b/spec/attime_spec.rb @@ -1,17 +1,20 @@ require 'attime' -describe '#attime' do +describe 'CheckGraphite.attime' do subject do |example| delta = example.metadata[:description_args][0] - CheckGraphite.attime(delta) + CheckGraphite.attime(delta, now) end + let(:now) { Time.now } + def timedelta(n) - Time.now + n + now + n end it("10days") { should be_within(0.9).of(timedelta(10 * 86400)) } it("0days") { should be_within(0.9).of(timedelta(0)) } + it("1.5days") { should be_within(0.9).of(timedelta(1.5 * 86400)) } it("-10days") { should be_within(0.9).of(timedelta(-10 * 86400)) } it("5seconds") { should be_within(0.9).of(timedelta(5)) } it("5minutes") { should be_within(0.9).of(timedelta(5 * 60)) } @@ -26,6 +29,7 @@ def timedelta(n) it(1) { expect { subject }.to raise_error(/string/i) } it("Something") { expect { subject }.to raise_error(RuntimeError) } it("1m") { expect { subject }.to raise_error(/bad unit/i) } + it("1day 1day") { expect { subject }.to raise_error(/bad unit/i) } it("10") { expect { subject }.to raise_error(/unit/) } it("month") { expect { subject }.to raise_error(/scalar/) } end diff --git a/spec/projection_spec.rb b/spec/projection_spec.rb index c429c5a..17d8edc 100644 --- a/spec/projection_spec.rb +++ b/spec/projection_spec.rb @@ -1,7 +1,7 @@ require 'check_graphite/projection' require 'nagios_check' -describe describe CheckGraphite::Projection do +describe CheckGraphite::Projection do let :check do Class.new do attr_reader :values @@ -10,7 +10,7 @@ end.new end - describe 'primary value' do + describe 'when looking at the primary value' do subject do check.prepare check.send(:parse_options, ['--projection', projection]) @@ -33,7 +33,7 @@ end end - describe 'p-value' do + describe 'when looking at the p-value' do subject do check.prepare check.send(:parse_options, ['--projection', projection]) @@ -54,27 +54,27 @@ it { should eq("1.0") } end end +end - describe 'integration test' do - before do - FakeWeb.register_uri( - :get, "http://your.graphite.host/render?target=collectd.somebox.load.load.midterm&from=-30seconds&format=json", - :body => '[{"target": "collectd.somebox.load.load.midterm", "datapoints": [[1.0, 1339512060], [2.0, 1339512120], [6.0, 1339512180], [7.0, 1339512240]]}]', - :content_type => "application/json" - ) - end +describe 'when invoking graphite with --projection' do + before do + FakeWeb.register_uri( + :get, "http://your.graphite.host/render?target=collectd.somebox.load.load.midterm&from=-30seconds&format=json", + :body => '[{"target": "collectd.somebox.load.load.midterm", "datapoints": [[1.0, 1339512060], [2.0, 1339512120], [6.0, 1339512180], [7.0, 1339512240]]}]', + :content_type => "application/json" + ) + end - it 'should output value, projection interval and p-value' do - stub_const("ARGV", %w{ - -H http://your.graphite.host/render - -M collectd.somebox.load.load.midterm - -c 0:10 - --projection 5min - --name ze-name - }) - c = CheckGraphite::Command.new - STDOUT.should_receive(:puts).with(match(/ze-name.*in 5min.*p-value=0.9/)) - lambda { c.run }.should raise_error SystemExit - end + it 'outputs value, projection interval and p-value' do + stub_const("ARGV", %w{ + -H http://your.graphite.host/render + -M collectd.somebox.load.load.midterm + -c 0:10 + --projection 5min + --name ze-name + }) + c = CheckGraphite::Command.new + STDOUT.should_receive(:puts).with(match(/ze-name.*in 5min.*p-value=0.9/)) + lambda { c.run }.should raise_error SystemExit end end