rearview 1.1.2-jruby → 1.2.0-jruby
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|