rails_api_benchmark 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 16e76dc43a1a8457ffc51885a838b224bbb2f37d
4
+ data.tar.gz: 44020a8c4cd7bae78d0c758653d1f45f0244b9ba
5
+ SHA512:
6
+ metadata.gz: 36f8f6ec137d2227ef6b9b9b7bc7759d0c4068aa7c094fad84c1d5c2226a9f54e4a0ac04b0ba10a4b3ed8f7885cf60f3a1b868070578c64ec99807a7b8e00d65
7
+ data.tar.gz: 57695424f8624fa90b5117b63e050fdd79c22d38ba2518612423e18a43e73f1eafed84cd5dadc8050975cf018f50320ed698e9a2199d91f75ba4637b77f7b265
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Doc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # RailsApiBenchmark
2
+
3
+ Work in progress, yet you can use it like this.
4
+
5
+ ## Usage
6
+
7
+ Run it with rake api:benchmark
8
+
9
+ ## Installation
10
+
11
+ Install gnuplot (Google)
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'rails_api_benchmark'
17
+ ```
18
+
19
+ And then execute:
20
+ ```bash
21
+ $ bundle
22
+ ```
23
+
24
+ Provide necessary configuration in initializer, example config (mine):
25
+
26
+ ```ruby
27
+ unless Rails.env.production?
28
+ RailsApiBenchmark.configure do |config|
29
+ # Try different configs. You may need to run the
30
+ # benchmark in a production ready environment to get reliable results
31
+ config.concurrency = 2
32
+ config.host = 'localhost:5000' # example.com
33
+ config.nb_requests = 3000
34
+ config.results_folder = 'benchmark'
35
+ config.auth_header = 'Authorization: Token token=benchToken'
36
+ # Use only if you want to log the responses
37
+ config.curl_cmd = 'curl -H "%{auth_header}" http://%{host}%{route}'
38
+ # Use Apache Bench
39
+ config.bench_cmd = 'ab -n %{nb_requests} -c %{concurrency} -g plot.tsv -e plot.csv -H "%{auth_header}" http://%{host}%{route}'
40
+ config.server_cmd = 'bundle exec puma'
41
+ config.env_vars = {
42
+ 'RAILS_MAX_THREADS' => '2',
43
+ 'SECRET_KEY_BASE' => 'bench',
44
+ 'RAILS_ENV' => 'production',
45
+ 'SSL_DISABLE' => 'yup',
46
+ 'PORT' => '5000'
47
+ }
48
+ config.regexps = [ # Used to get results from the output of benchmark tools
49
+ {
50
+ name: 'Average time per request (ms)',
51
+ regexp: /Time\s+per\s+request:\s+([0-9.]*).*\(mean\)/
52
+ }, {
53
+ name: 'Requests per second (#)',
54
+ regexp: /Requests\s+per\s+second:\s+([0-9.]*).*\(mean\)/
55
+ }
56
+ ]
57
+ config.routes = [
58
+ {
59
+ name: 'candidates_per_25',
60
+ route: '/candidates',
61
+ method: :get,
62
+ title: 'GET /candidates'
63
+ }
64
+ ].freeze
65
+ end
66
+ end
67
+ ```
68
+
69
+ Next, add this to your Rakefile:
70
+
71
+ ```ruby
72
+ require 'rails_api_benchmark/benchmark_tasks'
73
+ ```
74
+
75
+ You can now run `rake api:benchmark` !
76
+
77
+ ## Contributing
78
+ Contributions are welcome
79
+
80
+ ## License
81
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
82
+
83
+ ### TODO
84
+ * POST requests
85
+ * Create Formatter class to avoid dirty code in Endpoint
86
+ * Create markdown template to embed nicely on github (Mustache)
87
+ * Create generators (for config initializer first)
88
+ * Add simplecov to permit controller coverage for example
89
+ * Generate documentation page(s) (markdown) to list the results
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'RailsApiBenchmark'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ # require 'rake/testtask'
20
+
21
+ # Rake::TestTask.new(:test) do |t|
22
+ # t.libs << 'test'
23
+ # t.pattern = 'test/**/*_test.rb'
24
+ # t.verbose = false
25
+ # end
26
+
27
+ # task default: :test
@@ -0,0 +1,20 @@
1
+ module RailsApiBenchmark
2
+ class BenchmarkTasks
3
+ include Rake::DSL if defined? Rake::DSL
4
+
5
+ def install_tasks
6
+ namespace :api do
7
+ desc 'Runs Rails API benchmark'
8
+ task benchmark: :environment do # Gosh, that's dirty !
9
+ puts RailsApiBenchmark.config.all
10
+ RailsApiBenchmark::Server.run
11
+ sleep(3) # Leave time to boot
12
+ RailsApiBenchmark::Core.run
13
+ RailsApiBenchmark::Subprocess.kill_all
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ RailsApiBenchmark::BenchmarkTasks.new.install_tasks
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsApiBenchmark
4
+ class Core
5
+ include Logging
6
+
7
+ class << self
8
+ def run
9
+ logger.info 'Begin benchmark...'
10
+ RailsApiBenchmark.config.routes.each do |route|
11
+ puts route[:name]
12
+ Endpoint.new(route).benchmark
13
+ Endpoint.new(route).query
14
+ end
15
+ logger.info 'DONE!'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsApiBenchmark
4
+ class Endpoint
5
+ include Logging
6
+
7
+ attr_reader :name, :route, :method, :title
8
+
9
+ def initialize(opts)
10
+ @name = opts[:name]
11
+ @route = opts[:route]
12
+ @method = opts[:method]
13
+ @title = opts[:title]
14
+ @response = nil
15
+ @results = []
16
+ @results_folder = "#{RailsApiBenchmark.config.results_folder}/#{@name}"
17
+ end
18
+
19
+ def benchmark
20
+ benchmark_cmd = RailsApiBenchmark.config.bench_cmd
21
+ opts = RailsApiBenchmark.config.all.merge(route: @route)
22
+
23
+ output = `#{benchmark_cmd % opts}`
24
+
25
+ regexps = RailsApiBenchmark.config.regexps
26
+ regexps.each { |r| @results << output.scan(r[:regexp]) }
27
+ end
28
+
29
+ def query
30
+ curl_cmd = RailsApiBenchmark.config.curl_cmd
31
+ opts = RailsApiBenchmark.config.all.merge(route: @route)
32
+
33
+ @response = `#{curl_cmd % opts}`
34
+ end
35
+
36
+ private
37
+
38
+ def write_results
39
+ FileUtils.mkdir_p(@results_folder)
40
+ if @response
41
+ File.open(File.join(@results_folder, 'response.json'), 'w+') do |f|
42
+ f.write(@response)
43
+ end
44
+ end
45
+ unless @results.empty?
46
+ File.open(File.join(@results_folder, 'response.json'), 'w+') do |f|
47
+ f.write(@response)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,36 @@
1
+ # module RailsApiBenchmark
2
+ # module Logging
3
+ # def logger
4
+ # Logging.logger
5
+ # end
6
+ #
7
+ # def self.logger
8
+ # @logger ||= Logger.new(STDOUT)
9
+ # end
10
+ # end
11
+ # end
12
+
13
+ module RailsApiBenchmark
14
+ module Logging
15
+ class << self
16
+ def logger
17
+ @logger ||= Logger.new(STDOUT)
18
+ end
19
+
20
+ attr_writer :logger
21
+ end
22
+
23
+ # Addition
24
+ def self.included(base)
25
+ class << base
26
+ def logger
27
+ Logging.logger
28
+ end
29
+ end
30
+ end
31
+
32
+ def logger
33
+ Logging.logger
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsApiBenchmark
4
+ class Server
5
+ def initialize
6
+ @cmd = RailsApiBenchmark.config.server_cmd
7
+ @env = RailsApiBenchmark.config.env_vars
8
+ end
9
+
10
+ def run
11
+ Subprocess.new(@cmd, @env)
12
+ end
13
+
14
+ def self.run
15
+ new.run
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+
5
+ module RailsApiBenchmark
6
+ class Subprocess
7
+ def self.kill_all
8
+ # Tried things, didn't work. This kills evrything
9
+ Process.kill('INT', -Process.getpgrp)
10
+ end
11
+
12
+ def initialize(cmd, env)
13
+ Process.spawn(env, cmd)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module RailsApiBenchmark
2
+ VERSION = '0.1.1'.freeze
3
+ end
@@ -0,0 +1,31 @@
1
+ require 'rails_api_benchmark/logging'
2
+ require 'rails_api_benchmark/server'
3
+ require 'rails_api_benchmark/core'
4
+ require 'rails_api_benchmark/subprocess'
5
+ require 'rails_api_benchmark/endpoint'
6
+
7
+ module RailsApiBenchmark
8
+ class Config
9
+ attr_accessor :concurrency, :nb_requests, :auth_header,
10
+ :server_cmd, :bench_cmd, :curl_cmd, :results_folder,
11
+ :regexps, :env_vars, :routes, :host
12
+ def all
13
+ instance_variables.inject({}) do |h, v|
14
+ var = v.to_s.sub('@', '')
15
+ h.merge(var.to_sym => send(var))
16
+ end
17
+ end
18
+ end
19
+
20
+ class << self
21
+ attr_writer :config
22
+
23
+ def config
24
+ @config ||= Config.new
25
+ end
26
+
27
+ def configure
28
+ yield config
29
+ end
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_api_benchmark
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Terry Raimondo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-07-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 5.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 5.1.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: mustache
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 0.99.4
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 0.99.4
47
+ description: Benchmark your API endpoints and get the results fast ! This gem leverages
48
+ the power of ApacheBench, but can be configured with another benchmark tool
49
+ email:
50
+ - terry.raimondo@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - MIT-LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - lib/rails_api_benchmark.rb
59
+ - lib/rails_api_benchmark/benchmark_tasks.rb
60
+ - lib/rails_api_benchmark/core.rb
61
+ - lib/rails_api_benchmark/endpoint.rb
62
+ - lib/rails_api_benchmark/logging.rb
63
+ - lib/rails_api_benchmark/server.rb
64
+ - lib/rails_api_benchmark/subprocess.rb
65
+ - lib/rails_api_benchmark/version.rb
66
+ homepage: https://github.com/terry90/rails_api_benchmark
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.6.12
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: RailsApiBenchmark is a benchmark tool for your Rails API
90
+ test_files: []