dynamo-autoscale 0.3 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby-version +1 -0
- data/CHANGELOG +5 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +26 -2
- data/USAGE +14 -0
- data/bin/dynamo-autoscale +29 -2
- data/config/environment/common.rb +0 -1
- data/lib/dynamo-autoscale/local_actioner.rb +0 -1
- data/lib/dynamo-autoscale/scale_report.rb +8 -2
- data/lib/dynamo-autoscale/version.rb +1 -1
- data/rlib/dynamodb_graph.r +2 -0
- data/script/email_test +68 -0
- metadata +8 -3
- data/aws.sample.yml +0 -16
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p392
|
data/CHANGELOG
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dynamo-autoscale (0.1
|
4
|
+
dynamo-autoscale (0.3.1)
|
5
5
|
activesupport
|
6
6
|
aws-sdk
|
7
7
|
colored
|
@@ -44,6 +44,7 @@ GEM
|
|
44
44
|
coderay (~> 1.0.5)
|
45
45
|
method_source (~> 0.8)
|
46
46
|
slop (~> 3.4)
|
47
|
+
rake (10.0.4)
|
47
48
|
rbtree (0.4.1)
|
48
49
|
ripl (0.7.0)
|
49
50
|
bond (~> 0.4.2)
|
@@ -72,6 +73,7 @@ PLATFORMS
|
|
72
73
|
DEPENDENCIES
|
73
74
|
dynamo-autoscale!
|
74
75
|
pry
|
76
|
+
rake
|
75
77
|
ripl
|
76
78
|
rspec
|
77
79
|
timecop
|
data/README.md
CHANGED
@@ -118,8 +118,9 @@ reads for: 2.hours, less_than: "50%", min: 2, scale: { on: :consumed, by: 2 }
|
|
118
118
|
writes for: 2.hours, less_than: "50%", min: 2, scale: { on: :consumed, by: 2 }
|
119
119
|
```
|
120
120
|
|
121
|
-
You would put this ruleset in a file and then
|
122
|
-
|
121
|
+
You would put this ruleset in a file and then add the path to the ruleset to
|
122
|
+
your `dynamo-autoscale` config. If you specify a relative path, the program will
|
123
|
+
assume a path relative to its `Dir.pwd`.
|
123
124
|
|
124
125
|
The first two rules are designed to deal with spikes. They are saying that if
|
125
126
|
the consumed capacity units is greater than 90% of the provisioned throughput
|
@@ -241,6 +242,22 @@ row, scale by the amount consumed multiplied by 1.5. A new check will only
|
|
241
242
|
happen when the table receives new data from cloud watch, which means that the
|
242
243
|
10 minute windows could potentially overlap.
|
243
244
|
|
245
|
+
### Table-specific rules
|
246
|
+
|
247
|
+
If you only want some rules to apply to certain tables, you can do the
|
248
|
+
following:
|
249
|
+
|
250
|
+
``` ruby
|
251
|
+
table "my_table_name" do
|
252
|
+
reads for: 2.hours, less_than: 10, scale: { on: :consumed, by: 2 }
|
253
|
+
end
|
254
|
+
|
255
|
+
reads for: 2, less_than: "20%", scale: { on: :consumed, by: 2 }
|
256
|
+
```
|
257
|
+
|
258
|
+
Anything outside of a `table` block will apply to all tables you specify in your
|
259
|
+
config.
|
260
|
+
|
244
261
|
## Downscale grouping
|
245
262
|
|
246
263
|
You can downscale reads or writes individually and this will cost you one of
|
@@ -432,6 +449,13 @@ Report Issues/Feature requests on
|
|
432
449
|
it can be ignored when we pull)
|
433
450
|
* Send a pull request. Bonus points for topic branches.
|
434
451
|
|
452
|
+
### About InvisibleHand
|
453
|
+
|
454
|
+
InvisibleHand is a price comparison API and browser extension which provides real-time
|
455
|
+
prices for millions of products at hundreds of retailers, and automatic price comparison.
|
456
|
+
|
457
|
+
For more information about our API and technologies, please read our [DevBlog](http://devblog.getinvisiblehand.com/).
|
458
|
+
|
435
459
|
### Copyright
|
436
460
|
|
437
461
|
Copyright (c) 2013 InvisibleHand Software Ltd. See
|
data/USAGE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Usage: dynamo-autoscale <path/to/config.yml>
|
2
|
+
dynamo-autoscale [-v|--version]
|
3
|
+
dynamo-autoscale [-h|--help]
|
4
|
+
|
5
|
+
Available options are:
|
6
|
+
|
7
|
+
--version prints out the version number of dynamo-autoscale
|
8
|
+
--help prints out this documentation
|
9
|
+
|
10
|
+
Details of what a configuration file should look to can be found at the
|
11
|
+
following url: https://github.com/invisiblehand/dynamo-autoscale.
|
12
|
+
|
13
|
+
For any queries, please email developers@getinvisiblehand.com.
|
14
|
+
|
data/bin/dynamo-autoscale
CHANGED
@@ -1,16 +1,43 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
# This OptionParser block is here to ensure the queries to --version are
|
6
|
+
# actually fast and don't have to go through all of the Ruby requiring lark.
|
7
|
+
begin
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.on('--version', 'Prints the version of this application.') do
|
10
|
+
require_relative '../lib/dynamo-autoscale/version'
|
11
|
+
puts DynamoAutoscale::VERSION
|
12
|
+
exit 0
|
13
|
+
end
|
14
|
+
|
15
|
+
opts.on('--help', 'Shows this documentation.') do
|
16
|
+
puts File.read(File.join(File.dirname(__FILE__), '..', 'USAGE'))
|
17
|
+
exit 0
|
18
|
+
end
|
19
|
+
end.parse!
|
20
|
+
rescue OptionParser::InvalidOption => e
|
21
|
+
STDERR.puts e.message
|
22
|
+
STDERR.puts
|
23
|
+
|
24
|
+
STDERR.puts File.read(File.join(File.dirname(__FILE__), '..', 'USAGE'))
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
3
28
|
require_relative '../config/environment/common'
|
4
29
|
|
30
|
+
|
5
31
|
if ARGV[0]
|
6
32
|
DynamoAutoscale.setup_from_config(ARGV[0])
|
7
33
|
elsif ARGV[0].nil?
|
8
|
-
STDERR.puts
|
34
|
+
STDERR.puts File.read(File.join(File.dirname(__FILE__), '..', 'USAGE'))
|
9
35
|
|
10
36
|
exit 1
|
11
37
|
elsif ARGV[0] and !File.exists?(ARGV[0])
|
12
|
-
STDERR.puts "Usage: dynamo-autoscale path/to/config.yml"
|
13
38
|
STDERR.puts "Error: The path you specified is to a file that does not exist."
|
39
|
+
STDERR.puts
|
40
|
+
STDERR.puts File.read(File.join(File.dirname(__FILE__), '..', 'USAGE'))
|
14
41
|
|
15
42
|
exit 1
|
16
43
|
end
|
@@ -39,7 +39,6 @@ module DynamoAutoscale
|
|
39
39
|
end
|
40
40
|
|
41
41
|
actioner.provisioned_writes.reverse_each do |wtime, writes|
|
42
|
-
logger.debug "Checking if #{time} > #{wtime}"
|
43
42
|
if time > wtime
|
44
43
|
logger.debug "[filter] Faked provisioned_writes to be #{writes} at #{time}"
|
45
44
|
datum[:provisioned_writes] = writes
|
@@ -8,7 +8,9 @@ module DynamoAutoscale
|
|
8
8
|
@table = table
|
9
9
|
@erb = ERB.new(File.read(TEMPLATE))
|
10
10
|
|
11
|
-
if
|
11
|
+
if DynamoAutoscale.config[:dry_run]
|
12
|
+
@enabled = false
|
13
|
+
elsif config = DynamoAutoscale.config[:email]
|
12
14
|
@enabled = true
|
13
15
|
Pony.options = config
|
14
16
|
else
|
@@ -16,6 +18,10 @@ module DynamoAutoscale
|
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
def email_subject
|
22
|
+
"Scale event for #{@table.name}"
|
23
|
+
end
|
24
|
+
|
19
25
|
def email_content
|
20
26
|
@erb.result(binding)
|
21
27
|
end
|
@@ -24,7 +30,7 @@ module DynamoAutoscale
|
|
24
30
|
return false unless @enabled
|
25
31
|
|
26
32
|
result = Pony.mail({
|
27
|
-
subject:
|
33
|
+
subject: email_subject,
|
28
34
|
body: email_content,
|
29
35
|
})
|
30
36
|
|
data/rlib/dynamodb_graph.r
CHANGED
@@ -8,6 +8,8 @@ data$time = strptime(data$time, "%Y-%m-%dT%H:%M:%SZ")
|
|
8
8
|
measure.vars = c('provisioned_reads','provisioned_writes',
|
9
9
|
'consumed_reads','consumed_writes')
|
10
10
|
|
11
|
+
# measure.vars = c('consumed_reads','consumed_writes')
|
12
|
+
|
11
13
|
ive.melted = melt(data, id.vars='time', measure.vars = measure.vars)
|
12
14
|
|
13
15
|
g = ggplot(ive.melted, aes(x=time, y=value, color=variable)) + geom_line()
|
data/script/email_test
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../config/environment/common'
|
4
|
+
include DynamoAutoscale
|
5
|
+
|
6
|
+
# This script is for testing the output of emails and configuration of email
|
7
|
+
# servers to send mail from this gem.
|
8
|
+
#
|
9
|
+
# If you invoke this script with a config path, it will try and send the email
|
10
|
+
# using your email configuration.
|
11
|
+
#
|
12
|
+
# If you invoke this script without a config path, it will just print the email
|
13
|
+
# content to STDOUT.
|
14
|
+
|
15
|
+
table = TableTracker.new("fake_table")
|
16
|
+
|
17
|
+
rulepool = RuleSet.new do
|
18
|
+
reads last: 2, greater_than: "90%", scale: { on: :consumed, by: 1.7 }
|
19
|
+
reads last: 2, greater_than: "80%", scale: { on: :consumed, by: 1.5 }
|
20
|
+
|
21
|
+
writes last: 2, greater_than: "90%", scale: { on: :consumed, by: 1.7 }
|
22
|
+
writes last: 2, greater_than: "80%", scale: { on: :consumed, by: 1.5 }
|
23
|
+
|
24
|
+
reads for: 2.hours, less_than: "20%", min: 10, scale: { on: :consumed, by: 1.8 }
|
25
|
+
reads for: 2.hours, less_than: "30%", min: 10, scale: { on: :consumed, by: 1.8 }
|
26
|
+
|
27
|
+
writes for: 2.hours, less_than: "20%", min: 10, scale: { on: :consumed, by: 1.8 }
|
28
|
+
writes for: 2.hours, less_than: "30%", min: 10, scale: { on: :consumed, by: 1.8 }
|
29
|
+
end.rules.values.flatten
|
30
|
+
|
31
|
+
20.times do
|
32
|
+
table.tick(rand(1..100).minutes.ago, {
|
33
|
+
:provisioned_reads => rand(1..1000),
|
34
|
+
:provisioned_writes => rand(1..1000),
|
35
|
+
:consumed_reads => rand(1..1000),
|
36
|
+
:consumed_writes => rand(1..1000),
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
10.times do
|
41
|
+
table.triggered_rules[rand(1..100).minutes.ago] = rulepool[rand(rulepool.length)]
|
42
|
+
end
|
43
|
+
|
44
|
+
10.times do
|
45
|
+
table.scale_events[rand(1..100).minutes.ago] = {
|
46
|
+
reads_from: rand(1..1000),
|
47
|
+
reads_to: rand(1..1000),
|
48
|
+
writes_from: rand(1..1000),
|
49
|
+
writes_to: rand(1..1000),
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
report = ScaleReport.new(table)
|
54
|
+
|
55
|
+
if ARGV[0]
|
56
|
+
DynamoAutoscale.setup_from_config(ARGV[0], dry_run: false)
|
57
|
+
|
58
|
+
report.send
|
59
|
+
elsif ARGV[0].nil?
|
60
|
+
puts "Subject: #{report.email_subject}"
|
61
|
+
puts
|
62
|
+
puts report.email_content
|
63
|
+
elsif ARGV[0] and !File.exists?(ARGV[0])
|
64
|
+
STDERR.puts "Usage: script/email_test [path/to/config.yml]"
|
65
|
+
STDERR.puts "Error: The path you specified is to a file that does not exist."
|
66
|
+
|
67
|
+
exit 1
|
68
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamo-autoscale
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir:
|
11
11
|
- bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-07-
|
13
|
+
date: 2013-07-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: aws-sdk
|
@@ -116,13 +116,14 @@ extensions: []
|
|
116
116
|
extra_rdoc_files: []
|
117
117
|
files:
|
118
118
|
- .gitignore
|
119
|
+
- .ruby-version
|
119
120
|
- CHANGELOG
|
120
121
|
- Gemfile
|
121
122
|
- Gemfile.lock
|
122
123
|
- LICENSE
|
123
124
|
- README.md
|
124
125
|
- Rakefile
|
125
|
-
-
|
126
|
+
- USAGE
|
126
127
|
- bin/dynamo-autoscale
|
127
128
|
- config/dynamo-autoscale-test.yml
|
128
129
|
- config/environment/common.rb
|
@@ -160,6 +161,7 @@ files:
|
|
160
161
|
- rulesets/gradual_tail.rb
|
161
162
|
- rulesets/none.rb
|
162
163
|
- script/console
|
164
|
+
- script/email_test
|
163
165
|
- script/historic_data
|
164
166
|
- script/hourly_wastage
|
165
167
|
- script/monitor
|
@@ -191,6 +193,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
193
|
- - ! '>='
|
192
194
|
- !ruby/object:Gem::Version
|
193
195
|
version: '0'
|
196
|
+
segments:
|
197
|
+
- 0
|
198
|
+
hash: 3081011429766319992
|
194
199
|
requirements:
|
195
200
|
- If you want to graph your tables, you'll need R with the ggplot and reshape packages
|
196
201
|
installed.
|
data/aws.sample.yml
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
default: &default
|
2
|
-
:access_key_id: your_id
|
3
|
-
:secret_access_key: your_key
|
4
|
-
|
5
|
-
development:
|
6
|
-
<<: *default
|
7
|
-
:dynamo_db_endpoint: dynamodb.us-east-1.amazonaws.com
|
8
|
-
|
9
|
-
test:
|
10
|
-
<<: *default
|
11
|
-
:dynamo_db_endpoint: localhost
|
12
|
-
:dynamo_db_port: 4568
|
13
|
-
|
14
|
-
production:
|
15
|
-
<<: *default
|
16
|
-
:dynamo_db_endpoint: dynamodb.us-east-1.amazonaws.com
|