rails-autoscale-core 1.1.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50da5c684e5529550e1ca98e3fae5f691e6c570a22fcea50fa4c5835bd3f2b2b
4
- data.tar.gz: d92402f06b3e9274a23edd96568977f9833d64577728b4cc14b5d504c9b822d9
3
+ metadata.gz: 0a26698eaf5edca75ec2e8fd7bf1b5035f9b697c1a94fd81a062a9dfec80c636
4
+ data.tar.gz: 30476ecf0afa5774c3773c2b2abbd7c258ef1256fe3e0d086d44a6cca07b69ff
5
5
  SHA512:
6
- metadata.gz: 03d5797fd9590fb1588e7ccdb473643f03d306776d8d1a277557f9d2e8dd6b71b08155e6788f1de59cdcadb72d89f013ae32e114c28a7d5b1de1a8a5514df444
7
- data.tar.gz: bf3710593737f7286c7b05959b518a634c0f94da406eeb98828d3be52876908213339c6eb133476a55690976890af92ef372fd61e64a5ba44502fa154c3f06d6
6
+ metadata.gz: ae8ddf51539fee0296c875b579dc7a01014fe2001393ea63c2c81da56e1ff008b154d51b60e0d86a42767908d030000d2441019a74380c48386742cb2e4f0e18
7
+ data.tar.gz: 5e75546db2c28f54781d03b9c791731408e45f21a5055cddfe03fac7625131f194a4873fb50bcc5bca194754e035b07b1e6c686bbd0b0d932e0419ca65ae511e
data/Gemfile CHANGED
@@ -1,8 +1,9 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gemspec
3
+ gemspec name: "judoscale-ruby"
4
4
 
5
5
  gem "rake", ">= 12.3.3"
6
+ gem "rake-release"
6
7
  gem "minitest"
7
8
  gem "webmock"
8
9
  gem "debug"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails-autoscale-core (1.1.1)
4
+ judoscale-ruby (1.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -10,17 +10,19 @@ GEM
10
10
  public_suffix (>= 2.0.2, < 6.0)
11
11
  crack (0.4.5)
12
12
  rexml
13
- debug (1.4.0)
14
- irb (>= 1.3.6)
15
- reline (>= 0.2.7)
13
+ debug (1.7.1)
14
+ irb (>= 1.5.0)
15
+ reline (>= 0.3.1)
16
16
  hashdiff (1.0.1)
17
- io-console (0.5.11)
18
- irb (1.4.1)
17
+ io-console (0.6.0)
18
+ irb (1.6.2)
19
19
  reline (>= 0.3.0)
20
- minitest (5.15.0)
21
- public_suffix (5.0.0)
20
+ minitest (5.17.0)
21
+ public_suffix (5.0.1)
22
22
  rake (13.0.6)
23
- reline (0.3.1)
23
+ rake-release (1.3.0)
24
+ bundler (>= 1.11, < 3)
25
+ reline (0.3.2)
24
26
  io-console (~> 0.5)
25
27
  rexml (3.2.5)
26
28
  webmock (3.18.1)
@@ -36,9 +38,10 @@ PLATFORMS
36
38
 
37
39
  DEPENDENCIES
38
40
  debug
41
+ judoscale-ruby!
39
42
  minitest
40
- rails-autoscale-core!
41
43
  rake (>= 12.3.3)
44
+ rake-release
42
45
  webmock
43
46
 
44
47
  BUNDLED WITH
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
3
+ require "rake/release"
4
4
  require "rake/testtask"
5
5
 
6
6
  Rake::TestTask.new(:test) do |t|
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "judoscale/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "judoscale-ruby"
7
+ spec.version = Judoscale::VERSION
8
+ spec.authors = ["Adam McCrea", "Carlos Antonio da Silva"]
9
+ spec.email = ["adam@adamlogic.com"]
10
+
11
+ spec.summary = "This gem works with the Judoscale Heroku add-on to automatically scale your web and worker dynos."
12
+ spec.homepage = "https://judoscale.com"
13
+ spec.license = "MIT"
14
+
15
+ spec.metadata = {
16
+ "homepage_uri" => "https://judoscale.com",
17
+ "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues",
18
+ "documentation_uri" => "https://judoscale.com/docs",
19
+ "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md",
20
+ "source_code_uri" => "https://github.com/judoscale/judoscale-ruby"
21
+ }
22
+
23
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.required_ruby_version = ">= 2.6.0"
27
+ end
@@ -3,9 +3,9 @@
3
3
  require "net/http"
4
4
  require "uri"
5
5
  require "json"
6
- require "rails_autoscale/logger"
6
+ require "judoscale/logger"
7
7
 
8
- module RailsAutoscale
8
+ module Judoscale
9
9
  class AdapterApi
10
10
  include Logger
11
11
 
@@ -3,7 +3,7 @@
3
3
  require "singleton"
4
4
  require "logger"
5
5
 
6
- module RailsAutoscale
6
+ module Judoscale
7
7
  class Config
8
8
  class Dyno
9
9
  attr_reader :name, :num
@@ -75,12 +75,12 @@ module RailsAutoscale
75
75
 
76
76
  def reset
77
77
  # Allow the API URL to be configured - needed for testing.
78
- @api_base_url = ENV["RAILS_AUTOSCALE_URL"] || ENV["JUDOSCALE_URL"]
79
- @log_tag = ENV["JUDOSCALE_URL"] ? "Judoscale" : "RailsAutoscale"
78
+ @api_base_url = ENV["JUDOSCALE_URL"] || ENV["RAILS_AUTOSCALE_URL"]
79
+ @log_tag = "Judoscale"
80
80
  self.dyno = ENV["DYNO"]
81
81
  @max_request_size_bytes = 100_000 # ignore request payloads over 100k since they skew the queue times
82
82
  @report_interval_seconds = 10
83
- self.log_level = ENV["RAILS_AUTOSCALE_LOG_LEVEL"] || ENV["JUDOSCALE_LOG_LEVEL"]
83
+ self.log_level = ENV["JUDOSCALE_LOG_LEVEL"] || ENV["RAILS_AUTOSCALE_LOG_LEVEL"]
84
84
  @logger = ::Logger.new($stdout)
85
85
 
86
86
  self.class.adapter_configs.each(&:reset)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RailsAutoscale
3
+ module Judoscale
4
4
  class JobMetricsCollector
5
5
  module ActiveRecordHelper
6
6
  # Cleanup any whitespace characters (including new lines) from the SQL for simpler logging.
@@ -14,14 +14,18 @@ module RailsAutoscale
14
14
 
15
15
  private
16
16
 
17
- def select_rows_silently(sql)
17
+ def run_silently(&block)
18
18
  if Config.instance.log_level && ::ActiveRecord::Base.logger.respond_to?(:silence)
19
- ::ActiveRecord::Base.logger.silence(Config.instance.log_level) { select_rows_tagged(sql) }
19
+ ::ActiveRecord::Base.logger.silence(Config.instance.log_level) { yield }
20
20
  else
21
- select_rows_tagged(sql)
21
+ yield
22
22
  end
23
23
  end
24
24
 
25
+ def select_rows_silently(sql)
26
+ run_silently { select_rows_tagged(sql) }
27
+ end
28
+
25
29
  def select_rows_tagged(sql)
26
30
  if ActiveRecord::Base.logger.respond_to?(:tagged)
27
31
  ActiveRecord::Base.logger.tagged(Config.instance.log_tag) { select_rows(sql) }
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "set"
4
- require "rails_autoscale/metrics_collector"
5
- require "rails_autoscale/logger"
4
+ require "judoscale/metrics_collector"
5
+ require "judoscale/logger"
6
6
 
7
- module RailsAutoscale
7
+ module Judoscale
8
8
  class JobMetricsCollector < MetricsCollector
9
- include RailsAutoscale::Logger
9
+ include Judoscale::Logger
10
10
 
11
11
  # It's redundant to report these metrics from every dyno, so only report from the first one.
12
12
  def self.collect?(config)
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails_autoscale/config"
3
+ require "judoscale/config"
4
4
  require "logger"
5
5
 
6
- module RailsAutoscale
6
+ module Judoscale
7
7
  module Logger
8
8
  def logger
9
9
  @logger ||= LoggerProxy.new(Config.instance.logger, Config.instance.log_level)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RailsAutoscale
3
+ module Judoscale
4
4
  class Metric < Struct.new(:identifier, :value, :time, :queue_name)
5
5
  # No queue_name is assumed to be a web request metric
6
6
  # Metrics: qt = queue time (default), qd = queue depth, busy
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RailsAutoscale
3
+ module Judoscale
4
4
  class MetricsCollector
5
5
  def self.collect?(config)
6
6
  true
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
- require "rails_autoscale/metric"
5
- require "rails_autoscale/report"
4
+ require "judoscale/metric"
5
+ require "judoscale/report"
6
6
 
7
- module RailsAutoscale
7
+ module Judoscale
8
8
  class MetricsStore
9
9
  include Singleton
10
10
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RailsAutoscale
3
+ module Judoscale
4
4
  class Report
5
5
  attr_reader :adapters, :config, :metrics
6
6
 
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
- require "rails_autoscale/config"
5
- require "rails_autoscale/logger"
6
- require "rails_autoscale/adapter_api"
7
- require "rails_autoscale/job_metrics_collector"
8
- require "rails_autoscale/web_metrics_collector"
4
+ require "judoscale/config"
5
+ require "judoscale/logger"
6
+ require "judoscale/adapter_api"
7
+ require "judoscale/job_metrics_collector"
8
+ require "judoscale/web_metrics_collector"
9
9
 
10
- module RailsAutoscale
10
+ module Judoscale
11
11
  class Reporter
12
12
  include Singleton
13
13
  include Logger
14
14
 
15
- def self.start(config = Config.instance, adapters = RailsAutoscale.adapters)
15
+ def self.start(config = Config.instance, adapters = Judoscale.adapters)
16
16
  instance.start!(config, adapters) unless instance.started?
17
17
  end
18
18
 
@@ -20,7 +20,7 @@ module RailsAutoscale
20
20
  @pid = Process.pid
21
21
 
22
22
  if !config.api_base_url
23
- logger.info "Reporter not started: RAILS_AUTOSCALE_URL is not set"
23
+ logger.info "Reporter not started: JUDOSCALE_URL is not set"
24
24
  return
25
25
  end
26
26
 
@@ -76,7 +76,7 @@ module RailsAutoscale
76
76
  private
77
77
 
78
78
  def report(config, metrics)
79
- report = Report.new(RailsAutoscale.adapters, config, metrics)
79
+ report = Report.new(Judoscale.adapters, config, metrics)
80
80
  logger.info "Reporting #{report.metrics.size} metrics"
81
81
  result = AdapterApi.new(config).report_metrics(report.as_json)
82
82
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module RailsAutoscale
3
+ module Judoscale
4
4
  class RequestMetrics
5
5
  attr_reader :request_id, :size, :network_time
6
6
 
@@ -18,11 +18,18 @@ module RailsAutoscale
18
18
 
19
19
  def started_at
20
20
  if @request_start_header
21
- # Heroku sets the header as an integer, measured in milliseconds.
22
- # If nginx is involved, it might be in seconds with fractional milliseconds,
23
- # and it might be preceeded by "t=". We can all cases by removing non-digits
24
- # and treating as milliseconds.
25
- Time.at(@request_start_header.gsub(/\D/, "").to_i / 1000.0)
21
+ # There are several variants of this header. We handle these:
22
+ # - whole milliseconds (Heroku)
23
+ # - whole nanoseconds (Render)
24
+ # - fractional seconds (NGINX)
25
+ # - preceeding "t=" (NGINX)
26
+ value = @request_start_header.gsub(/[^0-9.]/, "").to_f
27
+
28
+ case value
29
+ when 0..100_000_000_000 then Time.at(value)
30
+ when 100_000_000_000..100_000_000_000_000 then Time.at(value / 1000.0)
31
+ else Time.at(value / 1_000_000.0)
32
+ end
26
33
  end
27
34
  end
28
35
 
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails_autoscale/metrics_store"
4
- require "rails_autoscale/reporter"
5
- require "rails_autoscale/logger"
6
- require "rails_autoscale/request_metrics"
3
+ require "judoscale/metrics_store"
4
+ require "judoscale/reporter"
5
+ require "judoscale/logger"
6
+ require "judoscale/request_metrics"
7
7
 
8
- module RailsAutoscale
8
+ module Judoscale
9
9
  class RequestMiddleware
10
10
  include Logger
11
11
 
@@ -27,11 +27,11 @@ module RailsAutoscale
27
27
  store = MetricsStore.instance
28
28
 
29
29
  # NOTE: Expose queue time to the app
30
- env["rails_autoscale.queue_time"] = queue_time
30
+ env["judoscale.queue_time"] = queue_time
31
31
  store.push :qt, queue_time
32
32
 
33
33
  unless network_time.zero?
34
- env["rails_autoscale.network_time"] = network_time
34
+ env["judoscale.network_time"] = network_time
35
35
  store.push :nt, network_time
36
36
  end
37
37
 
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Judoscale
4
+ VERSION = "1.3.0"
5
+ end
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails_autoscale/metrics_collector"
4
- require "rails_autoscale/metrics_store"
3
+ require "judoscale/metrics_collector"
4
+ require "judoscale/metrics_store"
5
5
 
6
- module RailsAutoscale
6
+ module Judoscale
7
7
  class WebMetricsCollector < MetricsCollector
8
8
  def self.collect?(config)
9
9
  config.dyno.name == "web"
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "judoscale/config"
4
+ require "judoscale/version"
5
+
6
+ module Judoscale
7
+ # Allows configuring Rails Autoscale through a block, usually defined during application initialization.
8
+ #
9
+ # Example:
10
+ #
11
+ # Judoscale.configure do |config|
12
+ # config.logger = MyLogger.new
13
+ # end
14
+ def self.configure
15
+ yield Config.instance
16
+ end
17
+
18
+ @adapters = []
19
+ class << self
20
+ attr_reader :adapters
21
+ end
22
+
23
+ Adapter = Struct.new(:identifier, :adapter_info, :metrics_collector) do
24
+ def as_json
25
+ {identifier => adapter_info}
26
+ end
27
+ end
28
+
29
+ def self.add_adapter(identifier, adapter_info, metrics_collector: nil, expose_config: nil)
30
+ Config.expose_adapter_config(expose_config) if expose_config
31
+ @adapters << Adapter.new(identifier, adapter_info, metrics_collector)
32
+ end
33
+
34
+ add_adapter :"judoscale-ruby", {
35
+ adapter_version: VERSION,
36
+ language_version: RUBY_VERSION
37
+ }
38
+ end
39
+
40
+ RailsAutoscale = Judoscale
@@ -1,40 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rails_autoscale/config"
4
- require "rails_autoscale/version"
5
-
6
- module RailsAutoscale
7
- # Allows configuring Rails Autoscale through a block, usually defined during application initialization.
8
- #
9
- # Example:
10
- #
11
- # RailsAutoscale.configure do |config|
12
- # config.logger = MyLogger.new
13
- # end
14
- def self.configure
15
- yield Config.instance
16
- end
17
-
18
- @adapters = []
19
- class << self
20
- attr_reader :adapters
21
- end
22
-
23
- Adapter = Struct.new(:identifier, :adapter_info, :metrics_collector) do
24
- def as_json
25
- {identifier => adapter_info}
26
- end
27
- end
28
-
29
- def self.add_adapter(identifier, adapter_info, metrics_collector: nil, expose_config: nil)
30
- Config.expose_adapter_config(expose_config) if expose_config
31
- @adapters << Adapter.new(identifier, adapter_info, metrics_collector)
32
- end
33
-
34
- add_adapter :"rails-autoscale-core", {
35
- adapter_version: VERSION,
36
- language_version: RUBY_VERSION
37
- }
38
- end
39
-
40
- Judoscale = RailsAutoscale
3
+ require "judoscale-ruby"
@@ -1,23 +1,23 @@
1
1
  lib = File.expand_path("../lib", __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "rails_autoscale/version"
3
+ require "judoscale/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "rails-autoscale-core"
7
- spec.version = RailsAutoscale::VERSION
7
+ spec.version = Judoscale::VERSION
8
8
  spec.authors = ["Adam McCrea", "Carlos Antonio da Silva"]
9
9
  spec.email = ["adam@adamlogic.com"]
10
10
 
11
- spec.summary = "This gem works with the Rails Autoscale Heroku add-on to automatically scale your web and worker dynos."
12
- spec.homepage = "https://railsautoscale.com"
11
+ spec.summary = "This gem works with the Judoscale Heroku add-on to automatically scale your web and worker dynos."
12
+ spec.homepage = "https://judoscale.com"
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.metadata = {
16
- "homepage_uri" => "https://railsautoscale.com",
17
- "bug_tracker_uri" => "https://github.com/rails-autoscale/rails-autoscale-gems/issues",
18
- "documentation_uri" => "https://railsautoscale.com/docs",
19
- "changelog_uri" => "https://github.com/rails-autoscale/rails-autoscale-gems/blob/main/CHANGELOG.md",
20
- "source_code_uri" => "https://github.com/rails-autoscale/rails-autoscale-gems"
16
+ "homepage_uri" => "https://judoscale.com",
17
+ "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues",
18
+ "documentation_uri" => "https://judoscale.com/docs",
19
+ "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md",
20
+ "source_code_uri" => "https://github.com/judoscale/judoscale-ruby"
21
21
  }
22
22
 
23
23
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-autoscale-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam McCrea
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-11-14 00:00:00.000000000 Z
12
+ date: 2023-02-09 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email:
@@ -21,31 +21,33 @@ files:
21
21
  - Gemfile
22
22
  - Gemfile.lock
23
23
  - Rakefile
24
+ - judoscale-ruby.gemspec
25
+ - lib/judoscale-ruby.rb
26
+ - lib/judoscale/adapter_api.rb
27
+ - lib/judoscale/config.rb
28
+ - lib/judoscale/job_metrics_collector.rb
29
+ - lib/judoscale/job_metrics_collector/active_record_helper.rb
30
+ - lib/judoscale/logger.rb
31
+ - lib/judoscale/metric.rb
32
+ - lib/judoscale/metrics_collector.rb
33
+ - lib/judoscale/metrics_store.rb
34
+ - lib/judoscale/report.rb
35
+ - lib/judoscale/reporter.rb
36
+ - lib/judoscale/request_metrics.rb
37
+ - lib/judoscale/request_middleware.rb
38
+ - lib/judoscale/version.rb
39
+ - lib/judoscale/web_metrics_collector.rb
24
40
  - lib/rails-autoscale-core.rb
25
- - lib/rails_autoscale/adapter_api.rb
26
- - lib/rails_autoscale/config.rb
27
- - lib/rails_autoscale/job_metrics_collector.rb
28
- - lib/rails_autoscale/job_metrics_collector/active_record_helper.rb
29
- - lib/rails_autoscale/logger.rb
30
- - lib/rails_autoscale/metric.rb
31
- - lib/rails_autoscale/metrics_collector.rb
32
- - lib/rails_autoscale/metrics_store.rb
33
- - lib/rails_autoscale/report.rb
34
- - lib/rails_autoscale/reporter.rb
35
- - lib/rails_autoscale/request_metrics.rb
36
- - lib/rails_autoscale/request_middleware.rb
37
- - lib/rails_autoscale/version.rb
38
- - lib/rails_autoscale/web_metrics_collector.rb
39
41
  - rails-autoscale-core.gemspec
40
- homepage: https://railsautoscale.com
42
+ homepage: https://judoscale.com
41
43
  licenses:
42
44
  - MIT
43
45
  metadata:
44
- homepage_uri: https://railsautoscale.com
45
- bug_tracker_uri: https://github.com/rails-autoscale/rails-autoscale-gems/issues
46
- documentation_uri: https://railsautoscale.com/docs
47
- changelog_uri: https://github.com/rails-autoscale/rails-autoscale-gems/blob/main/CHANGELOG.md
48
- source_code_uri: https://github.com/rails-autoscale/rails-autoscale-gems
46
+ homepage_uri: https://judoscale.com
47
+ bug_tracker_uri: https://github.com/judoscale/judoscale-ruby/issues
48
+ documentation_uri: https://judoscale.com/docs
49
+ changelog_uri: https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md
50
+ source_code_uri: https://github.com/judoscale/judoscale-ruby
49
51
  post_install_message:
50
52
  rdoc_options: []
51
53
  require_paths:
@@ -64,6 +66,6 @@ requirements: []
64
66
  rubygems_version: 3.2.32
65
67
  signing_key:
66
68
  specification_version: 4
67
- summary: This gem works with the Rails Autoscale Heroku add-on to automatically scale
68
- your web and worker dynos.
69
+ summary: This gem works with the Judoscale Heroku add-on to automatically scale your
70
+ web and worker dynos.
69
71
  test_files: []
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RailsAutoscale
4
- VERSION = "1.1.1"
5
- end