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
@@ -0,0 +1,44 @@
|
|
1
|
+
module Graphite
|
2
|
+
class Client
|
3
|
+
extend Forwardable
|
4
|
+
attr_reader :connection
|
5
|
+
def_delegators :@connection, :get, :post
|
6
|
+
def initialize(options={})
|
7
|
+
default_options = {}
|
8
|
+
default_options[:ssl] = {
|
9
|
+
verify: true,
|
10
|
+
ca_file: File.expand_path('../cacerts.pem', __FILE__)
|
11
|
+
}
|
12
|
+
basic_auth = options.delete(:basic_auth)
|
13
|
+
@connection = Faraday.new(default_options.merge(options))
|
14
|
+
if basic_auth.present?
|
15
|
+
@connection.basic_auth(basic_auth[:user],basic_auth[:password])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
def render(params={})
|
19
|
+
connection.get('/render',params)
|
20
|
+
end
|
21
|
+
def find_metric(metric)
|
22
|
+
connection.get('/metrics/find',{ query: metric })
|
23
|
+
end
|
24
|
+
def metric_exists?(metric)
|
25
|
+
exists = false
|
26
|
+
response = find_metric(metric)
|
27
|
+
# Does this need to handle redirects?
|
28
|
+
if response.status == 200 && response.headers['content-type']=='application/json'
|
29
|
+
json = JSON.parse(response.body)
|
30
|
+
exists = true unless json.empty?
|
31
|
+
end
|
32
|
+
exists
|
33
|
+
end
|
34
|
+
def reachable?
|
35
|
+
reachable = false
|
36
|
+
begin
|
37
|
+
response = connection.get('/render')
|
38
|
+
reachable = response.status==200 && response.headers['content-type']=='image/png' && response.headers['content-length'].to_i > 0
|
39
|
+
rescue Exception => e
|
40
|
+
end
|
41
|
+
reachable
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Graphite
|
2
|
+
class Graph
|
3
|
+
attr_accessor :targets,:params
|
4
|
+
def initialize
|
5
|
+
@targets = []
|
6
|
+
@params = {}
|
7
|
+
end
|
8
|
+
def method_missing(sym)
|
9
|
+
if @params.has_key?(sym.to_s)
|
10
|
+
@params[sym.to_s]
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def self.from_url(url)
|
16
|
+
graph = self.new
|
17
|
+
uri = URI(url)
|
18
|
+
url_params = CGI.parse(uri.query)
|
19
|
+
target_parser = Graphite::TargetParser.new
|
20
|
+
url_params.delete("target").each do |t|
|
21
|
+
target_parser.parse!(t)
|
22
|
+
graph.targets << target_parser.tree.to_model
|
23
|
+
end
|
24
|
+
url_params.keys.inject(graph.params) { |acc,key|
|
25
|
+
acc[key] = if url_params[key].present? && url_params[key].size==1
|
26
|
+
url_params[key].first
|
27
|
+
else
|
28
|
+
url_params[key]
|
29
|
+
end
|
30
|
+
acc
|
31
|
+
}
|
32
|
+
graph
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,11 +1,10 @@
|
|
1
|
-
module
|
2
|
-
class
|
1
|
+
module Graphite
|
2
|
+
class RawParser
|
3
3
|
## returns an array of arrays of pairs with 2 elements timestamp and value (may be nil)
|
4
4
|
def self.parse(lines)
|
5
5
|
lines.strip.split("\n").map do |line|
|
6
6
|
metric, startTime, endTime, interval, dataStr = /(.*),(\d+),(\d+),(\d+)\|(.*)/.match(line)[1..-1]
|
7
7
|
data = dataStr.split(",")
|
8
|
-
|
9
8
|
0.upto(data.length - 1).map do |i|
|
10
9
|
value = data[i]
|
11
10
|
{
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Graphite
|
2
|
+
module TargetGrammer
|
3
|
+
|
4
|
+
class SyntaxNode < Treetop::Runtime::SyntaxNode
|
5
|
+
def text
|
6
|
+
self.text_value
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Target < SyntaxNode
|
11
|
+
def path?
|
12
|
+
elements[0].kind_of?(Graphite::TargetGrammer::Path)
|
13
|
+
end
|
14
|
+
def expression?
|
15
|
+
elements[0].kind_of?(Graphite::TargetGrammer::Expression)
|
16
|
+
end
|
17
|
+
def comment?
|
18
|
+
elements[0].kind_of?(Graphite::TargetGrammer::Comment)
|
19
|
+
end
|
20
|
+
def unknown?
|
21
|
+
!path? && !expression?
|
22
|
+
end
|
23
|
+
def color
|
24
|
+
unless @color
|
25
|
+
e = self.expressions.detect {|e| e.identifier.try(:text) == "color" }
|
26
|
+
if e && e.args && e.args.elements
|
27
|
+
color_val = e.args.elements.last.detect { |e| e.kind_of?(Graphite::TargetGrammer::StringLiteral) }
|
28
|
+
unless color_val.nil?
|
29
|
+
@color = color_val.text
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@color
|
34
|
+
end
|
35
|
+
def alias
|
36
|
+
unless @alias
|
37
|
+
e = self.expressions.detect {|e| e.identifier.try(:text) == "alias" }
|
38
|
+
if e && e.args && e.args.elements
|
39
|
+
alias_val = e.args.elements.last.detect { |e| e.kind_of?(Graphite::TargetGrammer::StringLiteral) }
|
40
|
+
unless alias_val.nil?
|
41
|
+
@alias = alias_val.text
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
@alias
|
46
|
+
end
|
47
|
+
def metric
|
48
|
+
unless @metric
|
49
|
+
@metric = if path?
|
50
|
+
self.elements[0].text
|
51
|
+
else
|
52
|
+
path = self.detect { |e| e.kind_of?(Graphite::TargetGrammer::Path) }
|
53
|
+
unless path.nil?
|
54
|
+
path.text
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
@metric
|
59
|
+
end
|
60
|
+
def functions
|
61
|
+
unless @functions
|
62
|
+
@functions = self.expressions.map { |e| e.identifier.text }
|
63
|
+
end
|
64
|
+
@functions
|
65
|
+
end
|
66
|
+
def expressions
|
67
|
+
unless @expressions
|
68
|
+
@expressions = self.find_all { |e| e.kind_of?(Graphite::TargetGrammer::Expression) }
|
69
|
+
end
|
70
|
+
@expressions
|
71
|
+
end
|
72
|
+
def to_model
|
73
|
+
Graphite::Target.new do |model|
|
74
|
+
model.alias = self.alias
|
75
|
+
model.color = self.color
|
76
|
+
model.metric = self.metric
|
77
|
+
model.functions = self.functions
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class IntegerLiteral < SyntaxNode
|
83
|
+
end
|
84
|
+
|
85
|
+
class StringLiteral < SyntaxNode
|
86
|
+
def text
|
87
|
+
eval self.text_value
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class FloatLiteral < SyntaxNode
|
92
|
+
end
|
93
|
+
|
94
|
+
class Identifier < SyntaxNode
|
95
|
+
end
|
96
|
+
|
97
|
+
class Expression < SyntaxNode
|
98
|
+
end
|
99
|
+
|
100
|
+
class PathSegment < SyntaxNode
|
101
|
+
end
|
102
|
+
|
103
|
+
class Path < SyntaxNode
|
104
|
+
end
|
105
|
+
|
106
|
+
class Arg < SyntaxNode
|
107
|
+
end
|
108
|
+
|
109
|
+
class Comment < SyntaxNode
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
grammar TargetGrammer
|
2
|
+
|
3
|
+
rule target
|
4
|
+
( comment / expression / path )* <Graphite::TargetGrammer::Target>
|
5
|
+
end
|
6
|
+
|
7
|
+
rule expression
|
8
|
+
identifier '(' args ')' <Graphite::TargetGrammer::Expression>
|
9
|
+
end
|
10
|
+
|
11
|
+
rule args
|
12
|
+
arg ( space* ',' space* arg )*
|
13
|
+
end
|
14
|
+
|
15
|
+
rule arg
|
16
|
+
( expression / path / string / integer / float / space )?
|
17
|
+
end
|
18
|
+
|
19
|
+
rule path
|
20
|
+
path_segment ( '.' path_segment )* <Graphite::TargetGrammer::Path>
|
21
|
+
end
|
22
|
+
|
23
|
+
rule path_segment
|
24
|
+
[a-zA-Z0-9_\*\-]+ <Graphite::TargetGrammer::PathSegment>
|
25
|
+
end
|
26
|
+
|
27
|
+
rule comment
|
28
|
+
'#' ( . )* <Graphite::TargetGrammer::Comment>
|
29
|
+
end
|
30
|
+
|
31
|
+
rule integer
|
32
|
+
('+' / '-')? [0-9]+ <Graphite::TargetGrammer::IntegerLiteral>
|
33
|
+
end
|
34
|
+
|
35
|
+
rule float
|
36
|
+
('+' / '-')? [0-9]+ (('.' [0-9]+) / ('e' [0-9]+)) <Graphite::TargetGrammer::FloatLiteral>
|
37
|
+
end
|
38
|
+
|
39
|
+
rule string
|
40
|
+
'"' ('\"' / !'"' .)* '"' <Graphite::TargetGrammer::StringLiteral>
|
41
|
+
/
|
42
|
+
"'" ('\"' / !"'" .)* "'" <Graphite::TargetGrammer::StringLiteral>
|
43
|
+
end
|
44
|
+
|
45
|
+
rule identifier
|
46
|
+
[a-zA-Z0-9_]* <Graphite::TargetGrammer::Identifier>
|
47
|
+
end
|
48
|
+
|
49
|
+
rule space
|
50
|
+
[\s]+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module Graphite
|
3
|
+
class TargetParser
|
4
|
+
class TargetParserError < StandardError
|
5
|
+
attr_accessor :parser_details
|
6
|
+
def initialize(parser_details)
|
7
|
+
@parser_details = parser_details
|
8
|
+
end
|
9
|
+
def to_s
|
10
|
+
"parse failure %{message}" % parser_details
|
11
|
+
end
|
12
|
+
end
|
13
|
+
attr_reader :parser,:tree
|
14
|
+
attr_accessor :data
|
15
|
+
def initialize(data=nil)
|
16
|
+
@data = data
|
17
|
+
@parser = TargetGrammerParser.new
|
18
|
+
end
|
19
|
+
def parse(data=nil)
|
20
|
+
if data.present?
|
21
|
+
@data = data
|
22
|
+
end
|
23
|
+
@tree = @parser.parse(@data)
|
24
|
+
end
|
25
|
+
def parse!(data=nil)
|
26
|
+
self.parse(data)
|
27
|
+
if error?
|
28
|
+
raise TargetParserError.new(error)
|
29
|
+
end
|
30
|
+
@tree
|
31
|
+
end
|
32
|
+
def self.parse(data)
|
33
|
+
inst = self.new(data)
|
34
|
+
inst.parse
|
35
|
+
inst
|
36
|
+
end
|
37
|
+
def error?
|
38
|
+
@tree.nil?
|
39
|
+
end
|
40
|
+
def error
|
41
|
+
{ message: @parser.failure_reason, line: @parser.failure_line, column: @parser.failure_column }
|
42
|
+
end
|
43
|
+
def self.grammer
|
44
|
+
File.expand_path("../target_grammer.treetop",__FILE__)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Treetop.load(Graphite::TargetParser.grammer)
|
50
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
class Treetop::Runtime::SyntaxNode
|
3
|
+
include Enumerable
|
4
|
+
def each(&block)
|
5
|
+
self.elements.each { |e| each_recursive(e,&block) }
|
6
|
+
end
|
7
|
+
def each_recursive(node,&block)
|
8
|
+
yield node
|
9
|
+
unless node.terminal?
|
10
|
+
node.elements.each { |e| each_recursive(e,&block) }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
data/lib/rearview.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'graphite'
|
2
|
+
|
1
3
|
require 'rearview/engine'
|
2
4
|
require 'rearview/concerns'
|
3
5
|
require 'rearview/ext/state_machine'
|
@@ -6,7 +8,6 @@ require 'rearview/constants_module_maker'
|
|
6
8
|
require 'rearview/logger'
|
7
9
|
require 'rearview/log_formatter'
|
8
10
|
require 'rearview/cron_helper'
|
9
|
-
require 'rearview/graphite_parser'
|
10
11
|
require 'rearview/results_handler'
|
11
12
|
require 'rearview/alerts_handler'
|
12
13
|
require 'rearview/url_helper'
|
@@ -16,6 +17,10 @@ require 'rearview/monitor_task'
|
|
16
17
|
require 'rearview/distribute'
|
17
18
|
require 'rearview/monitor_supervisor'
|
18
19
|
require 'rearview/monitor_service'
|
20
|
+
require 'rearview/metrics_validator'
|
21
|
+
require 'rearview/metrics_validator_task'
|
22
|
+
require 'rearview/metrics_validator_service'
|
23
|
+
require 'rearview/cron_expression_validator'
|
19
24
|
require 'rearview/configuration'
|
20
25
|
require 'rearview/vm'
|
21
26
|
require 'rearview/statsd'
|
@@ -27,7 +32,7 @@ module Rearview
|
|
27
32
|
include Rearview::Logger
|
28
33
|
|
29
34
|
class << self
|
30
|
-
attr_accessor :monitor_service,:stats_service,:alert_clients
|
35
|
+
attr_accessor :monitor_service,:stats_service,:validator_service,:alert_clients
|
31
36
|
end
|
32
37
|
|
33
38
|
module_function
|
@@ -70,10 +75,13 @@ module Rearview
|
|
70
75
|
logger.warn "monitor disabled!"
|
71
76
|
end
|
72
77
|
if config.stats_enabled?
|
73
|
-
logger.info "starting up stats service"
|
74
78
|
@stats_service = Rearview::StatsService.supervise
|
75
79
|
@stats_service.actors.first.startup
|
76
80
|
end
|
81
|
+
if config.metrics_validator_enabled?
|
82
|
+
@validator_service = Rearview::MetricsValidatorService.supervise
|
83
|
+
@validator_service.actors.first.startup
|
84
|
+
end
|
77
85
|
@alert_clients = Rearview::Alerts.registry.values
|
78
86
|
@booted = true
|
79
87
|
end
|
@@ -8,21 +8,17 @@ module Rearview
|
|
8
8
|
@monitor_results = monitor_results
|
9
9
|
end
|
10
10
|
def run
|
11
|
-
logger.info "#{self} run"
|
12
11
|
if Rearview.config.alerts_enabled?
|
13
12
|
Rearview.alert_clients.each do |client|
|
14
|
-
alert_agent = client.new
|
15
13
|
begin
|
14
|
+
alert_agent = client.new
|
16
15
|
alert_agent.alert(@job,@monitor_results)
|
17
16
|
rescue
|
18
|
-
logger.error "#{self} #{
|
17
|
+
logger.error "#{self} #{client} failed: #{$!}\n#{$@.join("\n")}"
|
19
18
|
end
|
20
19
|
end
|
21
20
|
end
|
22
21
|
self
|
23
|
-
rescue
|
24
|
-
logger.error "#{self} failed: #{$!}\n#{$@.join("\n")}"
|
25
|
-
self
|
26
22
|
end
|
27
23
|
end
|
28
24
|
end
|
@@ -8,49 +8,39 @@ module Rearview
|
|
8
8
|
|
9
9
|
class UrlValidator < ActiveModel::EachValidator
|
10
10
|
def validate_each(record, attribute, value)
|
11
|
+
passed = true
|
11
12
|
if value.present?
|
12
13
|
uri = URI.parse(value) rescue nil
|
13
14
|
unless uri.present? && uri.scheme.present? && (uri.scheme.downcase=="http" || uri.scheme.downcase=="https")
|
14
15
|
record.errors.add attribute, (options[:message] || "is not a valid URL")
|
15
|
-
|
16
|
-
if options[:reachable]
|
17
|
-
reachable = ReachableValidator.new(options.dup.merge(attributes: @attributes))
|
18
|
-
reachable.validate_each(record,attribute,value)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class ReachableValidator < ActiveModel::EachValidator
|
26
|
-
def validate_each(record, attribute, value)
|
27
|
-
if value.present?
|
28
|
-
response = HTTParty.get(value) rescue nil
|
29
|
-
unless response.present? && response.code == 200
|
30
|
-
record.errors.add attribute, (options[:message] || "is not a reachable URL")
|
16
|
+
passed = false
|
31
17
|
end
|
32
18
|
end
|
19
|
+
passed
|
33
20
|
end
|
34
21
|
end
|
35
22
|
|
36
23
|
class DirectoryValidator < ActiveModel::EachValidator
|
37
24
|
def validate_each(record, attribute, value)
|
25
|
+
passed = true
|
38
26
|
if value.present?
|
39
27
|
unless File.directory?(value)
|
40
28
|
record.errors.add attribute, (options[:message] || "is not a directory")
|
29
|
+
passed = false
|
41
30
|
end
|
42
31
|
end
|
43
32
|
end
|
44
33
|
end
|
45
34
|
|
46
|
-
ATTRIBUTES = [:default_from, :
|
35
|
+
ATTRIBUTES = [:default_from, :graphite_connection, :pagerduty_url, :sandbox_exec,
|
47
36
|
:sandbox_timeout, :sandbox_dir, :enable_alerts, :preload_jobs,
|
48
37
|
:logger, :enable_monitor, :verify, :default_url_options,
|
49
|
-
:authentication, :enable_stats, :statsd_connection
|
38
|
+
:authentication, :enable_stats, :statsd_connection,
|
39
|
+
:enable_metrics_validator, :metrics_validator_schedule]
|
50
40
|
|
51
41
|
attr_accessor *ATTRIBUTES
|
52
42
|
|
53
|
-
validates :
|
43
|
+
validates :graphite_connection, presence: true
|
54
44
|
validates :pagerduty_url, presence: true, url: true
|
55
45
|
validates :default_from, presence: true
|
56
46
|
validates :default_url_options, presence: true
|
@@ -59,8 +49,10 @@ module Rearview
|
|
59
49
|
validates :sandbox_timeout, presence: true, numericality: { greater_than: 4 }
|
60
50
|
validates :authentication, presence: true
|
61
51
|
validates :statsd_connection, presence: true, if: -> { self.stats_enabled? }
|
52
|
+
validates :metrics_validator_schedule, presence: true, :'rearview/cron_expression' => true, if: -> { self.metrics_validator_enabled? }
|
62
53
|
|
63
54
|
validate :validate_sandbox_execution
|
55
|
+
validate :validate_graphite_connection
|
64
56
|
|
65
57
|
def initialize(attributes={})
|
66
58
|
@default_from = "rearview@localhost"
|
@@ -73,6 +65,9 @@ module Rearview
|
|
73
65
|
@enable_stats = false
|
74
66
|
@default_url_options = {:host=>"localhost",:port=>"3000"}
|
75
67
|
@pagerduty_url = "https://events.pagerduty.com/generic/2010-04-15/create_event.json"
|
68
|
+
@graphite_connection = {}
|
69
|
+
@enable_metrics_validator = false
|
70
|
+
@metrics_validator_schedule = nil
|
76
71
|
super
|
77
72
|
end
|
78
73
|
|
@@ -84,6 +79,10 @@ module Rearview
|
|
84
79
|
enable_monitor
|
85
80
|
end
|
86
81
|
|
82
|
+
def metrics_validator_enabled?
|
83
|
+
enable_metrics_validator
|
84
|
+
end
|
85
|
+
|
87
86
|
def preload_jobs?
|
88
87
|
preload_jobs
|
89
88
|
end
|
@@ -102,6 +101,16 @@ module Rearview
|
|
102
101
|
opts.on("--[no-]alerts", "Enable/disable alerts") { |v| self.enable_alerts = v }
|
103
102
|
opts.on("--[no-]monitor", "Enable/disable monitor") { |v| self.enable_monitor = v }
|
104
103
|
opts.on("--[no-]verify", "Enable/disable verification") { |v| self.verify = v }
|
104
|
+
opts.on("--[no-]stats-service", "Enable/disable stats service") { |v| self.enable_stats = v }
|
105
|
+
opts.on("--[no-]validation-service", "Enable/disable validation service") { |v| self.enable_metrics_validator = v }
|
106
|
+
opts.on("--[no-]soft-boot", "Enable/disable soft boot") { |v|
|
107
|
+
if v
|
108
|
+
self.preload_jobs = false
|
109
|
+
self.enable_stats = false
|
110
|
+
self.enable_metrics_validator = false
|
111
|
+
self.enable_alerts = false
|
112
|
+
end
|
113
|
+
}
|
105
114
|
end.parse!(argv)
|
106
115
|
end
|
107
116
|
|
@@ -118,6 +127,22 @@ module Rearview
|
|
118
127
|
exit_code == 0
|
119
128
|
end
|
120
129
|
|
130
|
+
def validate_graphite_connection
|
131
|
+
if graphite_connection.present?
|
132
|
+
if !graphite_connection[:url].present?
|
133
|
+
self.errors.add(:graphite_connection, "graphite URL can't be blank")
|
134
|
+
else
|
135
|
+
url_validator = UrlValidator.new({ attributes: [:graphite_connection], message: "does not contain a valid URL" })
|
136
|
+
if url_validator.validate_each(self,:graphite_connection,graphite_connection[:url])
|
137
|
+
client = Graphite::Client.new(graphite_connection)
|
138
|
+
unless(client.reachable?)
|
139
|
+
self.errors.add(:graphite_connection, "graphite cannot be reached")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
121
146
|
def dump
|
122
147
|
ATTRIBUTES.sort.map { |attrib| "#{attrib.to_s}=#{(self.send(attrib).nil? ? "nil" : self.send(attrib))}" }.join("\n")
|
123
148
|
end
|