Class: DynamoAutoscale::Rule
- Inherits:
-
Object
- Object
- DynamoAutoscale::Rule
show all
- Includes:
- Logger
- Defined in:
- lib/dynamo-autoscale/rule.rb
Constant Summary
collapse
- CONDITIONS =
{
greater_than: Proc.new { |a, b| a > b },
less_than: Proc.new { |a, b| a < b },
}
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from Logger
included, logger, #logger, logger=
Constructor Details
#initialize(metric, opts, &block) ⇒ Rule
Returns a new instance of Rule.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/dynamo-autoscale/rule.rb', line 12
def initialize metric, opts, &block
@metric = metric
@opts = opts
@block = block
@count = Hash.new(0)
unless [:consumed_reads, :consumed_writes].include? @metric
raise ArgumentError.new("Invalid metric: #{@metric}. Must be either " +
":consumed_reads or :consumed_writes.")
end
if @opts[:greater_than].nil? and @opts[:less_than].nil?
raise ArgumentError.new("Must specify at least one of greater_than " +
"or less_than")
end
if @opts[:for].nil? and @opts[:last].nil?
raise ArgumentError.new("Need to specify at least one of :for and :last.")
end
if @opts[:greater_than] and @opts[:less_than] and
@opts[:greater_than].to_f >= @opts[:less_than].to_f
raise ArgumentError.new("greater_than cannot be greater than or " +
"equal to less_than. Rule will never trigger.")
end
if @opts[:greater_than] and @opts[:greater_than].to_f <= 0
raise ArgumentError.new("greater_than cannot be less than or equal to 0")
end
if @opts[:less_than] and @opts[:less_than].to_f <= 0
raise ArgumentError.new("less_than cannot be less than or equal to 0")
end
if @opts[:min] and @opts[:min] <= 0
raise ArgumentError.new("min cannot be less than or equal to 0")
end
if @opts[:max] and @opts[:max] <= 0
raise ArgumentError.new("max cannot be less than or equal to 0")
end
if @opts[:count] and @opts[:count] <= 0
raise ArgumentError.new("count cannot be less than or equal to 0")
end
if @opts[:scale].nil? and block.nil?
raise ArgumentError.new("no :scale option or block specified. Rule has no action.")
end
if @opts[:scale] and !@opts[:scale].is_a? Hash
raise ArgumentError.new(":scale option expects to be a hash.")
end
if @opts[:scale] and @opts[:scale][:on].nil? and @opts[:scale][:by].nil?
raise ArgumentError.new(":scale option expects :on and :by options.")
end
if @opts[:scale] and ![:consumed, :provisioned].include?(@opts[:scale][:on])
raise ArgumentError.new(":scale { :on } needs to be either :consumed " +
"or :provisioned")
end
if @opts[:scale] and @opts[:scale][:by] <= 0
raise ArgumentError.new(":scale { :by } needs to be greater than 0")
end
end
|
Instance Attribute Details
#metric ⇒ Object
Returns the value of attribute metric.
5
6
7
|
# File 'lib/dynamo-autoscale/rule.rb', line 5
def metric
@metric
end
|
#opts ⇒ Object
Returns the value of attribute opts.
5
6
7
|
# File 'lib/dynamo-autoscale/rule.rb', line 5
def opts
@opts
end
|
Instance Method Details
#reads? ⇒ Boolean
178
179
180
|
# File 'lib/dynamo-autoscale/rule.rb', line 178
def reads?
@metric == :consumed_reads
end
|
#serialize ⇒ Object
186
187
188
189
190
|
# File 'lib/dynamo-autoscale/rule.rb', line 186
def serialize
metric = @metric == :consumed_reads ? "reads" : "writes"
"#{metric}(#{@opts})"
end
|
#test(table) ⇒ Object
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/dynamo-autoscale/rule.rb', line 80
def test table
last_provisioned = table.last_provisioned_for(@metric)
CONDITIONS.each do |key, comparator|
if @opts[key]
value = @opts[key].to_f
if @opts[key].is_a? String and @opts[key].end_with? "%"
next if last_provisioned.nil?
value = (value / 100.0) * last_provisioned
end
duration = @opts[:for] || @opts[:last]
data = table.last(duration, @metric)
if !duration.is_a? ActiveSupport::Duration and data.length != duration
return false
end
if @opts[:max]
data = data.take(@opts[:max])
end
if @opts[:min]
return false unless data.length >= @opts[:min]
end
if data.all? { |datum| comparator.call(datum, value) }
@count[table.name] += 1
if @opts[:times].nil? or @count[table.name] == @opts[:times]
@count[table.name] = 0
logger.info "[rule] Triggered rule: #{self.to_english}"
table.triggered_rules[table.latest_data_time] = self
if scale = @opts[:scale]
new_val = table.send("last_#{scale[:on]}_for", @metric) * scale[:by]
DynamoAutoscale.actioners[table].set(@metric, new_val)
end
if @block
@block.call(table, self, DynamoAutoscale.actioners[table])
end
return true
else
return false
end
else
@count[table.name] = 0
end
end
end
false
end
|
#to_english ⇒ Object
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
# File 'lib/dynamo-autoscale/rule.rb', line 145
def to_english
message = "#{@metric} "
if @opts[:greater_than]
message << "were greater than " << @opts[:greater_than] << " "
end
if @opts[:less_than]
message << "and " if @opts[:greater_than]
message << "were less than " << @opts[:less_than] << " "
end
if @opts[:for] or @opts[:last]
val = @opts[:for] || @opts[:last]
if val.is_a? ActiveSupport::Duration
message << "for #{val.inspect} "
else
message << "for #{val} data points "
end
end
if @opts[:min]
message << "with a minimum of #{@opts[:min]} data points "
end
if @opts[:max]
message << "and " if @opts[:min]
message << "with a maximum of #{@opts[:max]} data points "
end
message
end
|
#writes? ⇒ Boolean
182
183
184
|
# File 'lib/dynamo-autoscale/rule.rb', line 182
def writes?
@metric == :consumed_writes
end
|