vector 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/vector.rb +1 -27
- data/lib/vector/functions/flexible_down_scaling.rb +58 -56
- data/lib/vector/functions/predictive_scaling.rb +70 -67
- data/lib/vector/version.rb +1 -1
- metadata +2 -2
data/lib/vector.rb
CHANGED
@@ -46,33 +46,7 @@ module Vector
|
|
46
46
|
|
47
47
|
def hlog(string)
|
48
48
|
return unless @@enabled
|
49
|
-
|
50
|
-
tmp_components = @components.dup
|
51
|
-
level = 0
|
52
|
-
if @last_components
|
53
|
-
@last_components.each do |last_c|
|
54
|
-
break if tmp_components.empty?
|
55
|
-
if last_c == tmp_components[0]
|
56
|
-
level += 1
|
57
|
-
tmp_components.shift
|
58
|
-
else
|
59
|
-
break
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
tmp_components.each do |component|
|
65
|
-
name = if component.respond_to? :name
|
66
|
-
component.name
|
67
|
-
else
|
68
|
-
component.to_s
|
69
|
-
end
|
70
|
-
puts "#{" " * level}#{name}"
|
71
|
-
level += 1
|
72
|
-
end
|
73
|
-
|
74
|
-
puts "#{" " * level}#{string}"
|
75
|
-
@last_components = @components.dup
|
49
|
+
puts "[#{@components.join ','}] #{string}"
|
76
50
|
end
|
77
51
|
end
|
78
52
|
end
|
@@ -15,66 +15,68 @@ module Vector
|
|
15
15
|
def run_for(group, ps_check_procs)
|
16
16
|
result = { :triggered => false }
|
17
17
|
|
18
|
-
hlog_ctx("
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# don't bother checking for a scaledown if desired capacity is
|
26
|
-
# already at the minimum size...
|
27
|
-
if group.desired_capacity == group.min_size
|
28
|
-
hlog("Group is already at minimum size, exiting")
|
29
|
-
return result
|
30
|
-
end
|
31
|
-
|
32
|
-
scaledown_policies = group.scaling_policies.select do |policy|
|
33
|
-
policy.scaling_adjustment < 0
|
34
|
-
end
|
35
|
-
|
36
|
-
scaledown_policies.each do |policy|
|
37
|
-
hlog_ctx("policy: #{policy.name}") do
|
38
|
-
# TODO: support adjustment types other than ChangeInCapacity here
|
39
|
-
if policy.adjustment_type == "ChangeInCapacity" &&
|
40
|
-
ps_check_procs.any? {|ps_check_proc|
|
41
|
-
ps_check_proc.call(group.desired_capacity + policy.scaling_adjustment) }
|
42
|
-
hlog("Predictive scaleup would trigger a scaleup if group were shrunk")
|
43
|
-
next
|
44
|
-
end
|
45
|
-
|
46
|
-
alarms = policy.alarms.keys.map do |alarm_name|
|
47
|
-
@cloudwatch.alarms[alarm_name]
|
48
|
-
end
|
49
|
-
|
50
|
-
# only consider disabled alarms (enabled alarms will trigger
|
51
|
-
# the policy automatically)
|
52
|
-
disabled_alarms = alarms.select do |alarm|
|
53
|
-
!alarm.enabled?
|
54
|
-
end
|
18
|
+
hlog_ctx("fds") do
|
19
|
+
hlog_ctx("group:#{group.name}") do
|
20
|
+
# don't check if no config was specified
|
21
|
+
if @up_down_cooldown.nil? && @down_down_cooldown.nil?
|
22
|
+
hlog("No cooldown periods specified, exiting")
|
23
|
+
return result
|
24
|
+
end
|
55
25
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
26
|
+
# don't bother checking for a scaledown if desired capacity is
|
27
|
+
# already at the minimum size...
|
28
|
+
if group.desired_capacity == group.min_size
|
29
|
+
hlog("Group is already at minimum size, exiting")
|
30
|
+
return result
|
31
|
+
end
|
60
32
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
33
|
+
scaledown_policies = group.scaling_policies.select do |policy|
|
34
|
+
policy.scaling_adjustment < 0
|
35
|
+
end
|
65
36
|
|
66
|
-
|
67
|
-
|
68
|
-
|
37
|
+
scaledown_policies.each do |policy|
|
38
|
+
hlog_ctx("policy:#{policy.name}") do
|
39
|
+
# TODO: support adjustment types other than ChangeInCapacity here
|
40
|
+
if policy.adjustment_type == "ChangeInCapacity" &&
|
41
|
+
ps_check_procs.any? {|ps_check_proc|
|
42
|
+
ps_check_proc.call(group.desired_capacity + policy.scaling_adjustment) }
|
43
|
+
hlog("Predictive scaleup would trigger a scaleup if group were shrunk")
|
44
|
+
next
|
45
|
+
end
|
46
|
+
|
47
|
+
alarms = policy.alarms.keys.map do |alarm_name|
|
48
|
+
@cloudwatch.alarms[alarm_name]
|
49
|
+
end
|
50
|
+
|
51
|
+
# only consider disabled alarms (enabled alarms will trigger
|
52
|
+
# the policy automatically)
|
53
|
+
disabled_alarms = alarms.select do |alarm|
|
54
|
+
!alarm.enabled?
|
55
|
+
end
|
56
|
+
|
57
|
+
unless disabled_alarms.all? {|alarm| alarm.state_value == "ALARM" }
|
58
|
+
hlog("Not all alarms are in ALARM state")
|
59
|
+
next
|
60
|
+
end
|
61
|
+
|
62
|
+
unless outside_cooldown_period(group)
|
63
|
+
hlog("Group is not outside the specified cooldown periods")
|
64
|
+
next
|
65
|
+
end
|
66
|
+
|
67
|
+
unless has_eligible_scaledown_instance(group)
|
68
|
+
hlog("Group does not have an instance eligible for scaledown due to max_sunk_cost")
|
69
|
+
next
|
70
|
+
end
|
71
|
+
|
72
|
+
hlog("Executing policy")
|
73
|
+
policy.execute(:honor_cooldown => true)
|
74
|
+
|
75
|
+
result[:triggered] = true
|
76
|
+
|
77
|
+
# no need to evaluate other scaledown policies
|
78
|
+
return result
|
69
79
|
end
|
70
|
-
|
71
|
-
hlog("Executing policy")
|
72
|
-
policy.execute(:honor_cooldown => true)
|
73
|
-
|
74
|
-
result[:triggered] = true
|
75
|
-
|
76
|
-
# no need to evaluate other scaledown policies
|
77
|
-
return result
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end
|
@@ -14,80 +14,83 @@ module Vector
|
|
14
14
|
def run_for(group)
|
15
15
|
result = { :check_procs => [], :triggered => false }
|
16
16
|
|
17
|
-
hlog_ctx "
|
18
|
-
|
17
|
+
hlog_ctx "ps" do
|
18
|
+
hlog_ctx "group:#{group.name}" do
|
19
|
+
return result if @lookback_windows.length == 0
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
scaleup_policies.each do |policy|
|
25
|
-
hlog_ctx "policy: #{policy.name}" do
|
26
|
-
|
27
|
-
policy.alarms.keys.each do |alarm_name|
|
28
|
-
alarm = @cloudwatch.alarms[alarm_name]
|
29
|
-
hlog_ctx "alarm: #{alarm.name} (metric #{alarm.metric.name})" do
|
30
|
-
|
31
|
-
unless alarm.enabled?
|
32
|
-
hlog "Skipping disabled alarm"
|
33
|
-
next
|
34
|
-
end
|
35
|
-
|
36
|
-
# Note that everywhere we say "load" what we mean is
|
37
|
-
# "metric value * number of nodes"
|
38
|
-
now_load, now_num = load_for(group, alarm.metric,
|
39
|
-
Time.now, @valid_period)
|
40
|
-
|
41
|
-
if now_load.nil?
|
42
|
-
hlog "Could not get current total for metric"
|
43
|
-
next
|
44
|
-
end
|
45
|
-
|
46
|
-
@lookback_windows.each do |window|
|
47
|
-
hlog_ctx "window: #{window.inspect}" do
|
48
|
-
then_load, = load_for(group, alarm.metric,
|
49
|
-
Time.now - window, @valid_period)
|
50
|
-
|
51
|
-
if then_load.nil?
|
52
|
-
hlog "Could not get past total value for metric"
|
53
|
-
next
|
54
|
-
end
|
55
|
-
|
56
|
-
# check that the past total utilization is within
|
57
|
-
# threshold% of the current total utilization
|
58
|
-
if @valid_threshold &&
|
59
|
-
!Vector.within_threshold(@valid_threshold, now_load, then_load)
|
60
|
-
hlog "Past metric total value not within threshold (current #{now_load}, then #{then_load})"
|
61
|
-
next
|
62
|
-
end
|
21
|
+
scaleup_policies = group.scaling_policies.select do |policy|
|
22
|
+
policy.scaling_adjustment > 0
|
23
|
+
end
|
63
24
|
|
64
|
-
|
65
|
-
|
66
|
-
alarm.period)
|
25
|
+
scaleup_policies.each do |policy|
|
26
|
+
hlog_ctx "policy:#{policy.name}" do
|
67
27
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
28
|
+
policy.alarms.keys.each do |alarm_name|
|
29
|
+
alarm = @cloudwatch.alarms[alarm_name]
|
30
|
+
hlog_ctx "alarm:#{alarm.name}" do
|
31
|
+
hlog "Metric #{alarm.metric.name}"
|
72
32
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
hlog "Predicted #{alarm.metric.name}: #{predicted_value} (#{num_nodes} nodes)"
|
78
|
-
|
79
|
-
check_alarm_threshold(alarm, predicted_value)
|
80
|
-
end
|
81
|
-
result[:check_procs] << check_proc
|
33
|
+
unless alarm.enabled?
|
34
|
+
hlog "Skipping disabled alarm"
|
35
|
+
next
|
36
|
+
end
|
82
37
|
|
83
|
-
|
84
|
-
|
85
|
-
|
38
|
+
# Note that everywhere we say "load" what we mean is
|
39
|
+
# "metric value * number of nodes"
|
40
|
+
now_load, now_num = load_for(group, alarm.metric,
|
41
|
+
Time.now, @valid_period)
|
86
42
|
|
87
|
-
|
43
|
+
if now_load.nil?
|
44
|
+
hlog "Could not get current total for metric"
|
45
|
+
next
|
46
|
+
end
|
88
47
|
|
89
|
-
|
90
|
-
|
48
|
+
@lookback_windows.each do |window|
|
49
|
+
hlog_ctx "window:#{window.inspect.gsub ' ', ''}" do
|
50
|
+
then_load, = load_for(group, alarm.metric,
|
51
|
+
Time.now - window, @valid_period)
|
52
|
+
|
53
|
+
if then_load.nil?
|
54
|
+
hlog "Could not get past total value for metric"
|
55
|
+
next
|
56
|
+
end
|
57
|
+
|
58
|
+
# check that the past total utilization is within
|
59
|
+
# threshold% of the current total utilization
|
60
|
+
if @valid_threshold &&
|
61
|
+
!Vector.within_threshold(@valid_threshold, now_load, then_load)
|
62
|
+
hlog "Past metric total value not within threshold (current #{now_load}, then #{then_load})"
|
63
|
+
next
|
64
|
+
end
|
65
|
+
|
66
|
+
past_load, = load_for(group, alarm.metric,
|
67
|
+
Time.now - window + @lookahead_window,
|
68
|
+
alarm.period)
|
69
|
+
|
70
|
+
if past_load.nil?
|
71
|
+
hlog "Could not get past + #{@lookahead_window.inspect} total value for metric"
|
72
|
+
next
|
73
|
+
end
|
74
|
+
|
75
|
+
# now take the past total load and divide it by the
|
76
|
+
# current number of instances to get the predicted value
|
77
|
+
check_proc = Proc.new do |num_nodes|
|
78
|
+
predicted_value = past_load.to_f / num_nodes
|
79
|
+
hlog "Predicted #{alarm.metric.name}: #{predicted_value} (#{num_nodes} nodes)"
|
80
|
+
|
81
|
+
check_alarm_threshold(alarm, predicted_value)
|
82
|
+
end
|
83
|
+
result[:check_procs] << check_proc
|
84
|
+
|
85
|
+
if check_proc.call(now_num)
|
86
|
+
hlog "Executing policy"
|
87
|
+
policy.execute(honor_cooldown: true)
|
88
|
+
|
89
|
+
result[:triggered] = true
|
90
|
+
|
91
|
+
# don't need to evaluate further windows or policies on this group
|
92
|
+
return result
|
93
|
+
end
|
91
94
|
end
|
92
95
|
end
|
93
96
|
end
|
data/lib/vector/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|