vector 0.0.3 → 0.0.4
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.
- 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
|