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
@@ -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
|