rearview 1.1.2-jruby → 1.2.0-jruby
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -3
- data/app/controllers/rearview/application_controller.rb +11 -0
- data/app/controllers/rearview/dashboard_children_controller.rb +1 -1
- data/app/controllers/rearview/dashboards_controller.rb +1 -1
- data/app/controllers/rearview/home_controller.rb +1 -1
- data/app/controllers/rearview/jobs_controller.rb +33 -29
- data/app/controllers/rearview/monitor_controller.rb +16 -2
- data/app/controllers/rearview/user_controller.rb +2 -2
- data/app/helpers/rearview/application_helper.rb +3 -3
- data/app/mailers/rearview/alert_mailer.rb +0 -2
- data/app/mailers/rearview/metrics_validation_mailer.rb +12 -0
- data/app/models/rearview/job.rb +17 -13
- data/app/views/rearview/home/show.html.erb +2 -0
- data/app/views/rearview/jobs/_job.json.jbuilder +1 -0
- data/app/views/rearview/metrics_validation_mailer/validation_failed_email.text.erb +13 -0
- data/app/views/rearview/monitor/create.json.jbuilder +1 -0
- data/db/migrate/20131106162900_base_schema.rb +2 -2
- data/lib/generators/templates/rearview.rb +24 -7
- data/lib/graphite.rb +13 -0
- data/lib/graphite/cacerts.pem +2184 -0
- data/lib/graphite/client.rb +44 -0
- data/lib/graphite/graph.rb +35 -0
- data/lib/{rearview/graphite_parser.rb → graphite/raw_parser.rb} +2 -3
- data/lib/graphite/target.rb +9 -0
- data/lib/graphite/target_grammer.rb +114 -0
- data/lib/graphite/target_grammer.treetop +53 -0
- data/lib/graphite/target_parser.rb +50 -0
- data/lib/graphite/treetop_ext.rb +14 -0
- data/lib/rearview.rb +11 -3
- data/lib/rearview/alerts_handler.rb +2 -6
- data/lib/rearview/configuration.rb +44 -19
- data/lib/rearview/cron_expression_validator.rb +11 -0
- data/lib/rearview/metrics_validator.rb +52 -0
- data/lib/rearview/metrics_validator_service.rb +24 -0
- data/lib/rearview/metrics_validator_task.rb +56 -0
- data/lib/rearview/monitor_runner.rb +9 -7
- data/lib/rearview/monitor_service.rb +2 -0
- data/lib/rearview/stats_service.rb +4 -2
- data/lib/rearview/version.rb +1 -1
- data/lib/tasks/rearview_tasks.rake +7 -1
- data/public/{help → rearview-src/help}/alert.html +0 -0
- data/public/{help → rearview-src/help}/quick.html +0 -0
- data/public/rearview-src/js/app.js +9 -0
- data/public/rearview-src/js/model/user.js +6 -2
- data/public/rearview-src/js/view/addmonitor.js +13 -8
- data/public/rearview-src/js/view/alert.js +11 -4
- data/public/rearview-src/js/view/dashboard.js +4 -2
- data/public/rearview-src/js/view/expandedmonitor.js +22 -9
- data/public/rearview-src/js/view/settings.js +84 -0
- data/public/rearview-src/less/login.less +4 -4
- data/public/rearview-src/less/rearview.less +17 -10
- data/public/{monitors → rearview-src/monitors}/index.json +1 -1
- data/public/{monitors → rearview-src/monitors}/outage.rb +0 -0
- data/public/rearview-src/templates/alert.hbs +10 -2
- data/public/rearview-src/templates/primarynav.hbs +6 -6
- data/public/rearview-src/templates/schedulemonitor.hbs +2 -1
- data/public/rearview-src/templates/settings.hbs +23 -0
- data/public/rearview/build.txt +1 -0
- data/public/rearview/help/alert.html +20 -0
- data/public/rearview/help/quick.html +34 -0
- data/public/rearview/js/app.js +1 -1
- data/public/rearview/js/main.js +21 -21
- data/public/rearview/js/model/user.js +1 -1
- data/public/rearview/js/view/addmonitor.js +1 -1
- data/public/rearview/js/view/alert.js +1 -1
- data/public/rearview/js/view/dashboard.js +1 -1
- data/public/rearview/js/view/expandedmonitor.js +1 -1
- data/public/rearview/js/view/settings.js +1 -0
- data/public/rearview/less/login.less +4 -4
- data/public/rearview/less/rearview.less +17 -10
- data/public/rearview/monitors/index.json +3 -0
- data/public/rearview/monitors/outage.rb +2 -0
- data/public/rearview/templates/alert.hbs +10 -2
- data/public/rearview/templates/primarynav.hbs +6 -6
- data/public/rearview/templates/schedulemonitor.hbs +2 -1
- data/public/rearview/templates/settings.hbs +23 -0
- data/spec/controllers/jobs_controller_spec.rb +1 -0
- data/spec/controllers/monitor_controller_spec.rb +3 -0
- data/spec/controllers/user_controller_spec.rb +5 -2
- data/spec/data/metrics.yml +598 -0
- data/spec/dummy/log/development.log +1044 -0
- data/spec/dummy/log/test.log +171716 -0
- data/spec/helpers/application_helper_spec.rb +33 -0
- data/spec/lib/graphite/client_spec.rb +126 -0
- data/spec/lib/graphite/graph_spec.rb +17 -0
- data/spec/lib/graphite/graphite_spec.rb +4 -0
- data/spec/lib/{rearview/graphite_parser_spec.rb → graphite/raw_parser.rb} +6 -5
- data/spec/lib/graphite/target_grammer_spec.rb +106 -0
- data/spec/lib/graphite/target_parser_spec.rb +124 -0
- data/spec/lib/graphite/target_spec.rb +5 -0
- data/spec/lib/rearview/configuration_spec.rb +69 -48
- data/spec/lib/rearview/metrics_validator_service_spec.rb +43 -0
- data/spec/lib/rearview/metrics_validator_spec.rb +84 -0
- data/spec/lib/rearview/metrics_validator_task_spec.rb +62 -0
- data/spec/lib/rearview/monitor_runner_spec.rb +3 -3
- data/spec/lib/rearview/stats_task_spec.rb +21 -0
- data/spec/mailers/metrics_validation_mailer_spec.rb +46 -0
- data/spec/models/job_spec.rb +82 -9
- data/spec/spec_helper.rb +15 -4
- data/spec/support/json_factory.rb +1 -1
- data/spec/views/dashboards/show.json.jbuilder_spec.rb +3 -1
- data/spec/views/jobs/show.json.jbuilder_spec.rb +2 -1
- metadata +98 -11
- data/public/rearview-src/templates/test.txt +0 -1
- data/public/rearview/templates/test.txt +0 -1
@@ -9,65 +9,85 @@ describe Rearview::Configuration do
|
|
9
9
|
let(:config) { Rearview::Configuration.new }
|
10
10
|
|
11
11
|
context 'validation' do
|
12
|
-
it { should validate_presence_of(:graphite_url) }
|
13
|
-
it { should validate_presence_of(:pagerduty_url) }
|
14
12
|
it { should validate_presence_of(:default_from) }
|
15
|
-
it { should validate_presence_of(:sandbox_dir) }
|
16
13
|
it { should validate_presence_of(:sandbox_exec) }
|
17
14
|
it { should validate_presence_of(:sandbox_timeout) }
|
18
15
|
it { should validate_presence_of(:default_url_options) }
|
19
16
|
it { should validate_presence_of(:authentication) }
|
20
17
|
it { should validate_numericality_of(:sandbox_timeout).is_greater_than(4) }
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
context 'sandbox_dir' do
|
19
|
+
it { should validate_presence_of(:sandbox_dir) }
|
20
|
+
it "should be a directory" do
|
21
|
+
config.sandbox_dir="/__not_likely__"
|
22
|
+
config.valid?
|
23
|
+
expect(config.errors[:sandbox_dir]).to include("is not a directory")
|
24
|
+
config.sandbox_dir = File.dirname(__FILE__)
|
25
|
+
config.valid?
|
26
|
+
expect(config.errors[:sandbox_dir]).to be_empty
|
27
|
+
end
|
28
28
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
29
|
+
context 'graphite_connection' do
|
30
|
+
it { should validate_presence_of(:graphite_connection) }
|
31
|
+
it "should require url option to be a valid url" do
|
32
|
+
config.graphite_connection = { url: 'ssh://fooblah' }
|
33
|
+
config.valid?
|
34
|
+
expect(config.errors[:graphite_connection]).to include("does not contain a valid URL")
|
35
|
+
end
|
36
|
+
it "should require url option to be present" do
|
37
|
+
config.graphite_connection = { url: nil }
|
38
|
+
config.valid?
|
39
|
+
expect(config.errors[:graphite_connection]).to include("graphite URL can't be blank")
|
40
|
+
end
|
41
|
+
pending do
|
42
|
+
it "should require url option to be reachable" do
|
43
|
+
config.graphite_connection = { url: 'http://graphite6.graphitehosting.com' }
|
44
|
+
config.valid?
|
45
|
+
mock_client = mock(:reachable? => false)
|
46
|
+
Graphite::Client.expects(:new).returns(mock_client)
|
47
|
+
expect(config.errors[:graphite_connection]).to include("graphite cannot be reached")
|
48
|
+
end
|
49
|
+
end
|
41
50
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
51
|
+
context 'pagerduty_url' do
|
52
|
+
it { should validate_presence_of(:pagerduty_url) }
|
53
|
+
it "should require pagerduty_url to be a url" do
|
54
|
+
config.pagerduty_url="ftp://fooblah"
|
55
|
+
config.valid?
|
56
|
+
expect(config.errors[:pagerduty_url]).to include("is not a valid URL")
|
57
|
+
config.pagerduty_url="HTTPS://fooblah"
|
58
|
+
config.valid?
|
59
|
+
expect(config.errors[:pagerduty_url]).to be_empty
|
60
|
+
end
|
49
61
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
config.valid?
|
60
|
-
expect(config.errors[:graphite_url]).to be_empty
|
62
|
+
context 'statsd_connection' do
|
63
|
+
it "should be present if stats are enabled" do
|
64
|
+
config.enable_stats = false
|
65
|
+
config.valid?
|
66
|
+
expect(config.errors[:statsd_connection]).to be_empty
|
67
|
+
config.enable_stats = true
|
68
|
+
config.valid?
|
69
|
+
expect(config.errors[:statsd_connection]).to include("can't be blank")
|
70
|
+
end
|
61
71
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
72
|
+
context 'metrics_validator_schedule' do
|
73
|
+
it {
|
74
|
+
Rearview::Configuration.any_instance.stubs(:metrics_validator_enabled?).returns(true)
|
75
|
+
should_not allow_value('abc').for(:metrics_validator_schedule)
|
76
|
+
}
|
77
|
+
it {
|
78
|
+
Rearview::Configuration.any_instance.stubs(:metrics_validator_enabled?).returns(true)
|
79
|
+
should allow_value('0 * * * * ?').for(:metrics_validator_schedule)
|
80
|
+
}
|
81
|
+
it "should be present if metrics_validator is enabled" do
|
82
|
+
config.enable_metrics_validator = false
|
83
|
+
config.valid?
|
84
|
+
expect(config.errors[:metrics_validator_schedule]).to be_empty
|
85
|
+
config.enable_metrics_validator = true
|
86
|
+
config.metrics_validator_schedule = nil
|
87
|
+
config.valid?
|
88
|
+
expect(config.errors[:metrics_validator_schedule]).to include("can't be blank")
|
89
|
+
end
|
69
90
|
end
|
70
|
-
pending "should require sanbox_exec to be executable"
|
71
91
|
end
|
72
92
|
|
73
93
|
context '.new' do
|
@@ -80,6 +100,7 @@ describe Rearview::Configuration do
|
|
80
100
|
expect(config.enable_monitor).to be_true
|
81
101
|
expect(config.enable_stats).to be_false
|
82
102
|
expect(config.verify).to be_false
|
103
|
+
expect(config.graphite_connection).to eq({})
|
83
104
|
expect(config.authentication).to eq({strategy: :database})
|
84
105
|
expect(config.default_url_options).to eq({:host=>"localhost", :port=>"3000"})
|
85
106
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rearview::MetricsValidatorService do
|
4
|
+
before do
|
5
|
+
Celluloid.shutdown
|
6
|
+
Celluloid.boot
|
7
|
+
@service = Rearview::MetricsValidatorService.new
|
8
|
+
end
|
9
|
+
context '#startup' do
|
10
|
+
it "can only be started if stopped" do
|
11
|
+
Rearview::MetricsValidatorTask.stubs(:supervise).returns(mock)
|
12
|
+
@service.startup
|
13
|
+
expect { @service.startup }.to raise_error("service already started")
|
14
|
+
end
|
15
|
+
it "should create the supervised task" do
|
16
|
+
Rearview::MetricsValidatorTask.expects(:supervise)
|
17
|
+
@service.startup
|
18
|
+
end
|
19
|
+
end
|
20
|
+
context '#shutdown' do
|
21
|
+
it "can only be shutdown if started" do
|
22
|
+
expect { @service.shutdown }.to raise_error("service not started")
|
23
|
+
end
|
24
|
+
it "should terminate the supervised task" do
|
25
|
+
mock_task = mock
|
26
|
+
mock_task.expects(:terminate).once
|
27
|
+
Rearview::MetricsValidatorTask.stubs(:supervise).returns(stub(:actors => stub(:first => mock_task)))
|
28
|
+
@service.startup
|
29
|
+
@service.shutdown
|
30
|
+
end
|
31
|
+
end
|
32
|
+
context '#started?' do
|
33
|
+
it "should be true if the service is started" do
|
34
|
+
Rearview::MetricsValidatorTask.stubs(:supervise).returns(mock)
|
35
|
+
@service.startup
|
36
|
+
expect(@service.started?).to be_true
|
37
|
+
end
|
38
|
+
it "should be false if the service is not started" do
|
39
|
+
expect(@service.started?).to be_false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rearview::MetricsValidator do
|
4
|
+
|
5
|
+
context '#metric_valid?' do
|
6
|
+
let(:metrics_validator) { Rearview::MetricsValidator.new({ attributes: [:metrics] })}
|
7
|
+
context 'true' do
|
8
|
+
it 'when the metric is commented out' do
|
9
|
+
expect(metrics_validator.metric_valid?('#stats_count.foo')).to be_true
|
10
|
+
end
|
11
|
+
it 'when the metric is complex' do
|
12
|
+
mock_client = mock(:metric_exists? => true)
|
13
|
+
metrics_validator.stubs(:client).returns(mock_client)
|
14
|
+
expect(metrics_validator.metric_valid?(%q[alias(summarize(stats_counts.watson.summary_tables.run,"5min"),"Daily Watson Tables so far")])).to be_true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context 'false' do
|
18
|
+
it 'when the metric is not parseable' do
|
19
|
+
expect(metrics_validator.metric_valid?(%q[alias@(stats.x.y,"processed")])).to be_false
|
20
|
+
end
|
21
|
+
it 'when the metric cannot be extracted' do
|
22
|
+
mock_parser = mock
|
23
|
+
mock_parser.stubs(:parse)
|
24
|
+
mock_parser.stubs(:error?).returns(false)
|
25
|
+
mock_parser.stubs(:tree).returns(mock(:comment? => false,:metric => nil))
|
26
|
+
metrics_validator.stubs(:target_parser).returns(mock_parser)
|
27
|
+
expect(metrics_validator.metric_valid?('stats.garbage.ignored')).to be_false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
context '#validate_each' do
|
32
|
+
let(:job) { FactoryGirl.create(:job) }
|
33
|
+
let(:metrics_validator) { Rearview::MetricsValidator.new({ attributes: [:metrics] })}
|
34
|
+
context 'valid' do
|
35
|
+
it 'parses the metric' do
|
36
|
+
mock_client = mock(:metric_exists? => true)
|
37
|
+
metrics_validator.stubs(:client).returns(mock_client)
|
38
|
+
expect(metrics_validator.metric_valid?(%q[alias(summarize(stats_counts.watson.summary_tables.run,"5min"),"Daily Watson Tables so far")])).to be_true
|
39
|
+
end
|
40
|
+
it 'when all metrics exists' do
|
41
|
+
mock_client = mock(:metric_exists? => true)
|
42
|
+
metrics_validator.stubs(:client).returns(mock_client)
|
43
|
+
metrics_validator.validate_each(job,:metrics,job.metrics)
|
44
|
+
expect(job.errors[:metrics]).to be_empty
|
45
|
+
end
|
46
|
+
end
|
47
|
+
context 'invalid' do
|
48
|
+
it 'when one metric does not exist' do
|
49
|
+
job.metrics << "metric.fooey"
|
50
|
+
mock_client = mock
|
51
|
+
mock_client.expects(:metric_exists?).with("metric.fooey").returns(false)
|
52
|
+
mock_client.expects(:metric_exists?).with(job.metrics.first).returns(true)
|
53
|
+
metrics_validator.stubs(:client).returns(mock_client)
|
54
|
+
metrics_validator.validate_each(job,:metrics,job.metrics)
|
55
|
+
expect(job.errors[:metrics]).to include("contains an invalid metric: metric.fooey")
|
56
|
+
expect(job.errors[:metrics]).not_to include("contains an invalid metric: #{job.metrics.first}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context 'cache' do
|
60
|
+
context 'enabled' do
|
61
|
+
let(:caching_validator) { Rearview::MetricsValidator.new({ attributes: [:metrics], cache: true })}
|
62
|
+
it 'caches responses for metrics' do
|
63
|
+
job.metrics << job.metrics.first
|
64
|
+
mock_client = mock
|
65
|
+
mock_client.expects(:metric_exists?).with(job.metrics.first).once.returns(true)
|
66
|
+
caching_validator.stubs(:client).returns(mock_client)
|
67
|
+
caching_validator.validate_each(job,:metrics,job.metrics)
|
68
|
+
expect(job.errors[:metrics]).to be_empty
|
69
|
+
end
|
70
|
+
end
|
71
|
+
context 'disabled' do
|
72
|
+
it 'does not cache responses for metrics' do
|
73
|
+
job.metrics << job.metrics.first
|
74
|
+
mock_client = mock
|
75
|
+
mock_client.expects(:metric_exists?).with(job.metrics.first).twice.returns(true)
|
76
|
+
metrics_validator.stubs(:client).returns(mock_client)
|
77
|
+
metrics_validator.validate_each(job,:metrics,job.metrics)
|
78
|
+
expect(job.errors[:metrics]).to be_empty
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rearview::MetricsValidatorTask do
|
4
|
+
|
5
|
+
before do
|
6
|
+
now = Time.now
|
7
|
+
Timecop.freeze(Time.local(now.year,now.mon,now.day))
|
8
|
+
end
|
9
|
+
|
10
|
+
context '.initialize' do
|
11
|
+
it 'schedules itself by default' do
|
12
|
+
Rearview::MetricsValidatorTask.any_instance.expects(:schedule)
|
13
|
+
Rearview::MetricsValidatorTask.new('0 * * * * ?')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context '#schedule' do
|
18
|
+
it 'sets the delay to 60s if the cron expression is \'0 * * * * ?\'' do
|
19
|
+
task = Rearview::MetricsValidatorTask.new('0 * * * * ?',false)
|
20
|
+
task.expects(:after).with(60.0).once
|
21
|
+
task.schedule
|
22
|
+
end
|
23
|
+
it 'sets the delay to 300s if the cron expression is \'0 5 * * * ?\'' do
|
24
|
+
task = Rearview::MetricsValidatorTask.new('0 5 * * * ?',false)
|
25
|
+
task.expects(:after).with(300.0).once
|
26
|
+
task.schedule
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context '.run' do
|
31
|
+
let(:job1_invalid) {
|
32
|
+
job = FactoryGirl.create(:job)
|
33
|
+
job.errors.add(:metrics,"contains an invalid metric: #{job.metrics.first}")
|
34
|
+
job
|
35
|
+
}
|
36
|
+
let(:job2_valid) {
|
37
|
+
FactoryGirl.create(:job)
|
38
|
+
}
|
39
|
+
let(:job3_invalid) {
|
40
|
+
job = FactoryGirl.create(:job)
|
41
|
+
job.errors.add(:metrics,"contains an invalid metric: #{job.metrics.first}")
|
42
|
+
job
|
43
|
+
}
|
44
|
+
it 'still schedules if there is an exception' do
|
45
|
+
Rearview::Job.stubs(:schedulable).raises(StandardError,"oops")
|
46
|
+
task = Rearview::MetricsValidatorTask.new('0 5 * * * ?',false)
|
47
|
+
task.expects(:schedule).once
|
48
|
+
task.run
|
49
|
+
end
|
50
|
+
it 'mails alerts only for jobs with invalid metrics' do
|
51
|
+
Rearview::Job.stubs(:schedulable).returns(mock(:load => [job1_invalid,job2_valid,job3_invalid]))
|
52
|
+
Rearview::MetricsValidator.any_instance.stubs(:validate_each)
|
53
|
+
task = Rearview::MetricsValidatorTask.new('0 5 * * * ?',false)
|
54
|
+
task.expects(:schedule).once
|
55
|
+
task.expects(:alert_validation_failed).with(job1_invalid).once
|
56
|
+
task.expects(:alert_validation_failed).with(job2_valid).never
|
57
|
+
task.expects(:alert_validation_failed).with(job3_invalid).once
|
58
|
+
task.run
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -2,9 +2,9 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Rearview::MonitorRunner, :travis=>true do
|
4
4
|
|
5
|
-
artifact1 =
|
6
|
-
artifact2 =
|
7
|
-
artifact3 =
|
5
|
+
artifact1 = Graphite::RawParser.parse open("spec/data/monitor.dat").read
|
6
|
+
artifact2 = Graphite::RawParser.parse open("spec/data/test.dat").read
|
7
|
+
artifact3 = Graphite::RawParser.parse open("spec/data/large_set.dat").read
|
8
8
|
|
9
9
|
context 'create_from_to_dates' do
|
10
10
|
before do
|
@@ -39,6 +39,27 @@ describe Rearview::StatsTask do
|
|
39
39
|
stats_task.statsd.expects(:batch)
|
40
40
|
stats_task.run
|
41
41
|
end
|
42
|
+
it "sends the correct stats" do
|
43
|
+
statsd = mock
|
44
|
+
batch = mock
|
45
|
+
statsd.expects(:batch_size=)
|
46
|
+
Rearview::Statsd.stubs(:new).returns(statsd)
|
47
|
+
stats_task = Rearview::StatsTask.new(120,false)
|
48
|
+
statsd.expects(:batch).yields(batch)
|
49
|
+
batch.expects(:gauge).with('vm.total_memory',any_parameters)
|
50
|
+
batch.expects(:gauge).with('vm.free_memory',any_parameters)
|
51
|
+
batch.expects(:gauge).with('vm.max_memory',any_parameters)
|
52
|
+
batch.expects(:gauge).with('vm.heap.committed',any_parameters)
|
53
|
+
batch.expects(:gauge).with('vm.heap.init',any_parameters)
|
54
|
+
batch.expects(:gauge).with('vm.heap.max',any_parameters)
|
55
|
+
batch.expects(:gauge).with('vm.heap.used',any_parameters)
|
56
|
+
batch.expects(:gauge).with('vm.non_heap.committed',any_parameters)
|
57
|
+
batch.expects(:gauge).with('vm.non_heap.init',any_parameters)
|
58
|
+
batch.expects(:gauge).with('vm.non_heap.max',any_parameters)
|
59
|
+
batch.expects(:gauge).with('vm.non_heap.used',any_parameters)
|
60
|
+
batch.expects(:gauge).with('monitor.total',any_parameters)
|
61
|
+
stats_task.run
|
62
|
+
end
|
42
63
|
end
|
43
64
|
|
44
65
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rearview::MetricsValidationMailer do
|
4
|
+
|
5
|
+
let(:job) {
|
6
|
+
job = FactoryGirl.build(:job)
|
7
|
+
job.errors.add(:metrics,"contains an invalid metric: stats.my_count")
|
8
|
+
job
|
9
|
+
}
|
10
|
+
|
11
|
+
let(:mail) {
|
12
|
+
Rearview::MetricsValidationMailer.validation_failed_email("foo@foo.com",job)
|
13
|
+
}
|
14
|
+
|
15
|
+
context 'subject' do
|
16
|
+
it 'contains the job name' do
|
17
|
+
expect(mail.subject).to match(/#{job.name}/)
|
18
|
+
end
|
19
|
+
it 'contains subject tag' do
|
20
|
+
expect(mail.subject).to match(/\[Rearview ALERT\]/)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'body' do
|
25
|
+
it 'has the alert message' do
|
26
|
+
expect(mail.body.encoded).to match(/ALERT: Job has \(1\) invalid metric/)
|
27
|
+
end
|
28
|
+
it 'has the monitor name' do
|
29
|
+
expect(mail.body.encoded).to match(/Monitor: #{job.name}/)
|
30
|
+
end
|
31
|
+
it 'has the monitor description' do
|
32
|
+
expect(mail.body.encoded).to match(/Description: #{job.description}/)
|
33
|
+
end
|
34
|
+
it 'has the alerted on date' do
|
35
|
+
expect(mail.body.encoded).to match(/Alerted On: .*/)
|
36
|
+
end
|
37
|
+
it 'has a direct link' do
|
38
|
+
expect(mail.body.encoded).to match(%r{Direct Link: http://localhost:3000/rearview/#dash/#{job.app_id}/expand/#{job.id}})
|
39
|
+
end
|
40
|
+
it 'has the invalid metric name' do
|
41
|
+
expect(mail.body.encoded).to match(/^stats.my_count/)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
data/spec/models/job_spec.rb
CHANGED
@@ -10,26 +10,39 @@ describe Rearview::Job do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
describe 'validations' do
|
13
|
-
it { should validate_presence_of(:cron_expr) }
|
14
13
|
it { should validate_presence_of(:name) }
|
15
14
|
it { should validate_presence_of(:metrics) }
|
16
15
|
it { should validate_presence_of(:app_id) }
|
17
|
-
it { should_not allow_value('abc').for(:cron_expr) }
|
18
|
-
it { should allow_value('0 * * * * ?').for(:cron_expr) }
|
19
16
|
it { should ensure_inclusion_of(:status).in_array(Rearview::Job::Status.values) }
|
17
|
+
describe 'cron_expr' do
|
18
|
+
before do
|
19
|
+
Rearview::MetricsValidator.any_instance.stubs(:validate_each)
|
20
|
+
Rearview::Job.any_instance.stubs(:deep_validation?).returns(true)
|
21
|
+
end
|
22
|
+
it { should validate_presence_of(:cron_expr) }
|
23
|
+
it { should_not allow_value('abc').for(:cron_expr) }
|
24
|
+
it { should allow_value('0 * * * * ?').for(:cron_expr) }
|
25
|
+
end
|
20
26
|
describe 'alert_keys' do
|
21
|
-
|
27
|
+
before do
|
28
|
+
Rearview::MetricsValidator.any_instance.stubs(:validate_each)
|
29
|
+
end
|
30
|
+
let(:job) {
|
31
|
+
job = create(:job)
|
32
|
+
job.deep_validation = true
|
33
|
+
job
|
34
|
+
}
|
22
35
|
it "should require a valid URI" do
|
23
36
|
keys = ["htptptptpt://not_a_uri"]
|
24
37
|
job.alert_keys=keys
|
25
38
|
expect(job.valid?).to be_false
|
26
|
-
expect(job.errors[:alert_keys]).to include("invalid URI")
|
39
|
+
expect(job.errors[:alert_keys]).to include("#{keys.first} is an invalid URI")
|
27
40
|
end
|
28
41
|
it "should require it to be one of the supported schemes" do
|
29
42
|
keys = ["http://www.google.com"]
|
30
43
|
job.alert_keys=keys
|
31
44
|
expect(job.valid?).to be_false
|
32
|
-
expect(job.errors[:alert_keys]).to include("
|
45
|
+
expect(job.errors[:alert_keys]).to include("#{keys.first} is not a supported alert type")
|
33
46
|
end
|
34
47
|
it "should validate the scheme against the corresponding alert" do
|
35
48
|
keys = ["pagerduty:10101010101010101010101010101010","mailto:first.last@hungrymachine.com","campfire://first.last@hungrymachine.com?token=123&room=text"]
|
@@ -40,19 +53,19 @@ describe Rearview::Job do
|
|
40
53
|
keys = ["pagerduty:abcdefg"]
|
41
54
|
job.alert_keys=keys
|
42
55
|
expect(job.valid?).to be_false
|
43
|
-
expect(job.errors[:alert_keys]).to include("
|
56
|
+
expect(job.errors[:alert_keys]).to include("#{keys.first} is invalid for supported alert type")
|
44
57
|
end
|
45
58
|
it "should detect an invalid mail URI" do
|
46
59
|
keys = ["mailto:abcdefg"]
|
47
60
|
job.alert_keys=keys
|
48
61
|
expect(job.valid?).to be_false
|
49
|
-
expect(job.errors[:alert_keys]).to include("
|
62
|
+
expect(job.errors[:alert_keys]).to include("#{keys.first} is invalid for supported alert type")
|
50
63
|
end
|
51
64
|
it "should detect an invalid campfire URI" do
|
52
65
|
keys = ["campfire://first.last@hungrymachine.com"]
|
53
66
|
job.alert_keys=keys
|
54
67
|
expect(job.valid?).to be_false
|
55
|
-
expect(job.errors[:alert_keys]).to include("
|
68
|
+
expect(job.errors[:alert_keys]).to include("#{keys.first} is invalid for supported alert type")
|
56
69
|
end
|
57
70
|
end
|
58
71
|
end
|
@@ -133,13 +146,73 @@ describe Rearview::Job do
|
|
133
146
|
inactive_job.sync_monitor_service
|
134
147
|
end
|
135
148
|
end
|
149
|
+
describe '#set_defaults' do
|
150
|
+
context 'alert_keys' do
|
151
|
+
it "should set it to an empty array if not present" do
|
152
|
+
job = create(:job, { alert_keys: nil})
|
153
|
+
job.save!
|
154
|
+
expect(job.alert_keys).to eq([])
|
155
|
+
job = create(:job)
|
156
|
+
expect(job.alert_keys).not_to eq([])
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
describe '#delay' do
|
161
|
+
before do
|
162
|
+
now = Time.now
|
163
|
+
Timecop.freeze(Time.local(now.year,now.mon,now.day))
|
164
|
+
end
|
165
|
+
after do
|
166
|
+
Timecop.return
|
167
|
+
end
|
168
|
+
it "cron expression '0 * * * * ?' to be 60.0" do
|
169
|
+
job = build(:job,cron_expr: '0 * * * * ?')
|
170
|
+
expect(job.delay).to eq(60.0)
|
171
|
+
end
|
172
|
+
it "any cron expression other than '0 * * * * ?' to be calculated by Rearview::CronHelper" do
|
173
|
+
job = build(:job,cron_expr: '0 30 * * * ?')
|
174
|
+
Rearview::CronHelper.expects(:next_valid_time_after).with('0 30 * * * ?')
|
175
|
+
job.delay
|
176
|
+
end
|
177
|
+
end
|
178
|
+
describe '#translate_associated_event' do
|
179
|
+
let(:transition) { mock }
|
180
|
+
let(:job) { create(:job) }
|
181
|
+
it 'echos back any non-security error' do
|
182
|
+
transition.stubs(:event).returns(:foo)
|
183
|
+
expect(job.send(:translate_associated_event,transition)).to eq(:foo)
|
184
|
+
end
|
185
|
+
it 'translates it to an :error' do
|
186
|
+
transition.stubs(:event).returns(:security_error)
|
187
|
+
expect(job.send(:translate_associated_event,transition)).to eq(:error)
|
188
|
+
end
|
189
|
+
end
|
136
190
|
describe '#report_transition' do
|
191
|
+
let(:transition) { mock }
|
192
|
+
let(:job) { create(:job) }
|
193
|
+
before do
|
194
|
+
@statsd = mock
|
195
|
+
Rearview.config.stubs(:stats_enabled?).returns(true)
|
196
|
+
Rearview::Statsd.stubs(:statsd).returns(@statsd)
|
197
|
+
end
|
137
198
|
context 'success event' do
|
138
199
|
it "should increment monitor.success" do
|
200
|
+
transition.stubs(:event).returns(:success)
|
201
|
+
@statsd.expects(:increment).with("monitor.success")
|
202
|
+
job.send(:report_transition,transition)
|
139
203
|
end
|
140
204
|
end
|
141
205
|
context 'failure event' do
|
142
206
|
it "should increment monitor.failure" do
|
207
|
+
transition.stubs(:event).returns(:error)
|
208
|
+
@statsd.expects(:increment).with("monitor.failure")
|
209
|
+
job.send(:report_transition,transition)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
context 'exception' do
|
213
|
+
it "should not raise" do
|
214
|
+
transition.stubs(:event).raises
|
215
|
+
expect{job.send(:report_transition,transition)}.not_to raise_error
|
143
216
|
end
|
144
217
|
end
|
145
218
|
end
|