frankenstein 1.2.0 → 2.0.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
- SHA1:
3
- metadata.gz: f2e7a82ed23dd4f853c7d0eea1c8b0ac334977ec
4
- data.tar.gz: f2431b5567a6086f2c9cafa07f6496d1039ebccb
2
+ SHA256:
3
+ metadata.gz: 6ba12d5e4ad9e76a2bec62028b14952b2081b7ea16dbabf00eb14eb1db4b0ab6
4
+ data.tar.gz: 23d575919475820563f308fdb335e16089eb981c2350c3484e191330fc74d90d
5
5
  SHA512:
6
- metadata.gz: 942dafc43941ce8724b387116463f90128780d67e97ecfadd8dde579273c9477cf3bea3447244cf23cfeadf7e004ba23675392e1060dc8d2f9e9f1fdf64966b6
7
- data.tar.gz: 1a64333bb6f7c0ff58eebaeca68a921647b01e763e36362a7a6c3994127a3b3a1ca091b888806b713dda7fe9062decf89c66f09d6a4f45f4f78ec4f35815b250
6
+ metadata.gz: 6e8286ddd22170784525f2f81e76a0ff646e0ae91318539fb6fafac71c6fab537ffcdc33be5756ef048a16ea220a5ef5ce182c2ac5ab5dbdc956e4fd8d079676
7
+ data.tar.gz: f35c4da5e96629af26b9a49f47c4a639d3199025a437e63ab2ecd2f1ff2364529774935879f5c3014422e565aed4710727737848912cb1dc467b924f0f421248
@@ -27,22 +27,17 @@ Gem::Specification.new do |s|
27
27
 
28
28
  s.required_ruby_version = ">= 2.3.0"
29
29
 
30
- # prometheus-client provides no guaranteed backwards compatibility,
31
- # and in fact happily breaks things with no notice, so we're stuck
32
- # with hard-coding a specific version to avoid unexpected disaster.
33
- s.add_runtime_dependency "prometheus-client", "0.8.0"
30
+ s.add_runtime_dependency "prometheus-client", "~> 2.0"
34
31
  s.add_runtime_dependency "rack", "~> 2.0"
35
32
 
36
33
  s.add_development_dependency 'bundler'
37
34
  s.add_development_dependency 'github-release'
38
35
  s.add_development_dependency 'git-version-bump'
39
36
  s.add_development_dependency 'guard-rspec'
40
- s.add_development_dependency 'guard-rubocop'
41
37
  s.add_development_dependency 'rack-test'
42
38
  s.add_development_dependency 'rake', "~> 12.0"
43
39
  s.add_development_dependency 'redcarpet'
44
40
  s.add_development_dependency 'rspec'
45
- s.add_development_dependency 'rubocop'
46
41
  s.add_development_dependency 'simplecov'
47
42
  s.add_development_dependency 'yard'
48
43
  end
@@ -65,6 +65,9 @@ module Frankenstein
65
65
  #
66
66
  # @param docstring [#to_s] the descriptive help text for the metric.
67
67
  #
68
+ # @param labels [Array<Symbol>] the labels which all time series for this
69
+ # metric must possess.
70
+ #
68
71
  # @param type [Symbol] what type of metric you're returning. It's uncommon
69
72
  # to want anything other than `:gauge` here (the default), because
70
73
  # when you're collecting external data it's unlikely you'll be able to
@@ -87,8 +90,8 @@ module Frankenstein
87
90
  #
88
91
  # @param collector [Proc] the code to run on every scrape request.
89
92
  #
90
- def initialize(name, docstring, type: :gauge, logger: Logger.new('/dev/null'), registry: Prometheus::Client.registry, &collector)
91
- @validator = Prometheus::Client::LabelSetValidator.new
93
+ def initialize(name, docstring:, labels: [], type: :gauge, logger: Logger.new('/dev/null'), registry: Prometheus::Client.registry, &collector)
94
+ @validator = Prometheus::Client::LabelSetValidator.new(expected_labels: labels)
92
95
 
93
96
  validate_name(name)
94
97
  validate_docstring(docstring)
@@ -104,14 +107,14 @@ module Frankenstein
104
107
  @registry = registry
105
108
  @collector = collector
106
109
 
107
- @errors_metric = @registry.counter(:"#{@name}_collection_errors_total", "Errors encountered while collecting for #{@name}")
110
+ @errors_metric = @registry.counter(:"#{@name}_collection_errors_total", docstring: "Errors encountered while collecting for #{@name}")
108
111
  @registry.register(self)
109
112
  end
110
113
 
111
114
  # Retrieve the value for the given labelset.
112
115
  #
113
116
  def get(labels = {})
114
- @validator.validate(labels)
117
+ @validator.validate_labelset!(labels)
115
118
 
116
119
  values[labels]
117
120
  end
@@ -126,7 +129,7 @@ module Frankenstein
126
129
  @errors_metric.increment(class: "NotAHashError")
127
130
  return {}
128
131
  end
129
- results.keys.each { |labelset| @validator.validate(labelset) }
132
+ results.keys.each { |labelset| @validator.validate_labelset!(labelset) }
130
133
  end
131
134
  rescue StandardError => ex
132
135
  @logger.error(progname) { (["Exception in collection: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
@@ -18,7 +18,7 @@ module Frankenstein
18
18
  # @param logger [Logger] where to log any problems which some sort of
19
19
  #
20
20
  def self.register(registry = Prometheus::Client.registry, logger: Logger.new("/dev/null"))
21
- registry.gauge(:process_start_time_seconds, "Start time of the process since unix epoch in seconds").set({}, Time.now.to_f)
21
+ registry.gauge(:process_start_time_seconds, docstring: "Start time of the process since unix epoch in seconds").set(Time.now.to_f)
22
22
 
23
23
  page_size = Etc.sysconf(Etc::SC_PAGESIZE)
24
24
  hz = Etc.sysconf(Etc::SC_CLK_TCK)
@@ -26,17 +26,17 @@ module Frankenstein
26
26
  stat_file = "/proc/#{Process.pid}/stat".freeze
27
27
 
28
28
  if File.exist?(stat_file)
29
- Frankenstein::CollectedMetric.new(:process_cpu_seconds_total, "Total user and system CPU time spent in seconds", registry: registry, logger: logger) do
29
+ Frankenstein::CollectedMetric.new(:process_cpu_seconds_total, docstring: "Total user and system CPU time spent in seconds", registry: registry, logger: logger, labels: [:mode]) do
30
30
  stats = File.read(stat_file).split(" ")
31
31
  { { mode: "user" } => stats[13].to_f / hz, { mode: "system" } => stats[14].to_f / hz }
32
32
  end
33
33
 
34
- Frankenstein::CollectedMetric.new(:process_virtual_memory_bytes, "Virtual memory size in bytes", registry: registry, logger: logger) do
34
+ Frankenstein::CollectedMetric.new(:process_virtual_memory_bytes, docstring: "Virtual memory size in bytes", registry: registry, logger: logger) do
35
35
  stats = File.read(stat_file).split(" ")
36
36
  { {} => stats[22].to_i }
37
37
  end
38
38
 
39
- Frankenstein::CollectedMetric.new(:process_resident_memory_bytes, "Resident memory size in bytes", registry: registry, logger: logger) do
39
+ Frankenstein::CollectedMetric.new(:process_resident_memory_bytes, docstring: "Resident memory size in bytes", registry: registry, logger: logger) do
40
40
  stats = File.read(stat_file).split(" ")
41
41
  { {} => stats[23].to_i * page_size }
42
42
  end
@@ -45,23 +45,23 @@ module Frankenstein
45
45
  fd_dir = "/proc/#{Process.pid}/fd".freeze
46
46
 
47
47
  if File.exist?(fd_dir)
48
- Frankenstein::CollectedMetric.new(:process_open_fds, "Number of open file descriptors", registry: registry, logger: logger) do
48
+ Frankenstein::CollectedMetric.new(:process_open_fds, docstring: "Number of open file descriptors", registry: registry, logger: logger) do
49
49
  { {} => Dir["#{fd_dir}/*"].length }
50
50
  end
51
51
  end
52
52
 
53
53
  if Process.respond_to?(:getrlimit)
54
- Frankenstein::CollectedMetric.new(:process_max_fds, "Maximum number of open file descriptors", registry: registry, logger: logger) do
54
+ Frankenstein::CollectedMetric.new(:process_max_fds, docstring: "Maximum number of open file descriptors", registry: registry, logger: logger) do
55
55
  { {} => Process.getrlimit(:NOFILE).first }
56
56
  end
57
57
 
58
- Frankenstein::CollectedMetric.new(:process_virtual_memory_max_bytes, "Maximum amount of virtual memory available in bytes", registry: registry, logger: logger) do
58
+ Frankenstein::CollectedMetric.new(:process_virtual_memory_max_bytes, docstring: "Maximum amount of virtual memory available in bytes", registry: registry, logger: logger) do
59
59
  { {} => Process.getrlimit(:AS).first }
60
60
  end
61
61
  end
62
62
 
63
63
  if GC.respond_to?(:stat) && GC.stat[:heap_allocated_pages]
64
- Frankenstein::CollectedMetric.new(:process_heap_bytes, "Process heap size in bytes", registry: registry, logger: logger) do
64
+ Frankenstein::CollectedMetric.new(:process_heap_bytes, docstring: "Process heap size in bytes", registry: registry, logger: logger) do
65
65
  { {} => GC.stat[:heap_allocated_pages] * page_size }
66
66
  end
67
67
  end
@@ -0,0 +1,25 @@
1
+ module Frankenstein
2
+ # Mix-in to add #remove to Prometheus metrics
3
+ module RemoveTimeSeries
4
+ # Remove a time series from a metric.
5
+ #
6
+ # @param labels [Hash<Symbol, String>] the label set to remove.
7
+ #
8
+ def remove(labels)
9
+ @store.remove(labels)
10
+ end
11
+
12
+ # Mix-in to add #remove support to the default Synchronized metric store.
13
+ module SynchronizedMetricStore
14
+ # Remove a time series from the metric store.
15
+ #
16
+ # @private
17
+ def remove(labels)
18
+ @internal_store.delete(labels)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ Prometheus::Client::Metric.include(Frankenstein::RemoveTimeSeries)
25
+ Prometheus::Client::DataStores::Synchronized.const_get(:MetricStore).include(Frankenstein::RemoveTimeSeries::SynchronizedMetricStore)
@@ -65,17 +65,25 @@ module Frankenstein
65
65
  # It should be a singular and indefinite noun phrase, to maximise the
66
66
  # chances that it will fit neatly into the generated description text.
67
67
  #
68
+ # @param labels [Array<Symbol>] the names of the labels that will be
69
+ # set on most of the metrics created by this instance.
70
+ #
71
+ # @param duration_labels [Array<Symbol>] the names of the labels which will
72
+ # be set on the `_duration_seconds` histogram. By default, the value
73
+ # of the `labels` parameter will be used, but if you want to have a separate
74
+ # label set for your duration histogram, this is what you want.
75
+ #
68
76
  # @param registry [Prometheus::Client::Registry] the client registry in
69
77
  # which all the metrics will be created. The default will put all the
70
78
  # metrics in the Prometheus Client's default registry, which may or may
71
79
  # not be what you're up for. If you're using Frankenstein::Server, you
72
80
  # want `stats_server.registry`.
73
81
  #
74
- def initialize(prefix, outgoing: true, description: prefix, registry: Prometheus::Client.registry)
75
- @requests = registry.counter(:"#{prefix}_requests_total", "Number of #{description} requests #{outgoing ? 'sent' : 'received'}")
76
- @durations = registry.histogram(:"#{prefix}_request_duration_seconds", "Time taken to #{outgoing ? 'receive' : 'send'} a #{description} response")
77
- @exceptions = registry.counter(:"#{prefix}_exceptions_total", "Number of exceptions raised by the #{description} code")
78
- @current = registry.gauge(:"#{prefix}_in_progress_count", "Number of #{description} requests currently in progress")
82
+ def initialize(prefix, labels: [], duration_labels: nil, outgoing: true, description: prefix, registry: Prometheus::Client.registry)
83
+ @requests = registry.counter(:"#{prefix}_requests_total", docstring: "Number of #{description} requests #{outgoing ? 'sent' : 'received'}", labels: labels)
84
+ @durations = registry.histogram(:"#{prefix}_request_duration_seconds", docstring: "Time taken to #{outgoing ? 'receive' : 'send'} a #{description} response", labels: duration_labels || labels)
85
+ @exceptions = registry.counter(:"#{prefix}_exceptions_total", docstring: "Number of exceptions raised by the #{description} code", labels: labels + [:class])
86
+ @current = registry.gauge(:"#{prefix}_in_progress_count", docstring: "Number of #{description} requests currently in progress", labels: labels)
79
87
 
80
88
  # Prometheus::Client::Gauge doesn't (yet) have a built-in way to
81
89
  # atomically "adjust" a gauge, only get the current value and set a
@@ -149,7 +157,7 @@ module Frankenstein
149
157
  # have the same set of labels. If you fail to do this, an exception
150
158
  # will be raised by Prometheus after the block is executed.
151
159
  #
152
- # @raise [Prometheus::Request::NoBlockError] if you didn't pass a block to
160
+ # @raise [Frankenstein::Request::NoBlockError] if you didn't pass a block to
153
161
  # call. There's nothing to instrument!
154
162
  #
155
163
  # @raise [Prometheus::Client::LabelSetValidator::LabelSetError] if you
@@ -170,21 +178,21 @@ module Frankenstein
170
178
  "No block passed to #{self.class}#measure"
171
179
  end
172
180
 
173
- @requests.increment(labels, 1)
174
- @mutex.synchronize { @current.set(labels, (@current.get(labels) || 0) + 1) }
181
+ @requests.increment(labels: labels)
182
+ @mutex.synchronize { @current.set((@current.get(labels: labels) || 0) + 1, labels: labels) }
175
183
 
176
184
  res_labels = labels.dup
177
185
 
178
186
  begin
179
187
  yield(res_labels).tap do
180
188
  elapsed_time = Time.now - start_time
181
- @durations.observe(res_labels, elapsed_time)
189
+ @durations.observe(elapsed_time, labels: res_labels)
182
190
  end
183
191
  rescue Exception => ex
184
- @exceptions.increment(labels.merge(class: ex.class.to_s), 1)
192
+ @exceptions.increment(labels: labels.merge(class: ex.class.to_s))
185
193
  raise
186
194
  ensure
187
- @mutex.synchronize { @current.set(labels, @current.get(labels) - 1) }
195
+ @mutex.synchronize { @current.set(@current.get(labels: labels) - 1, labels: labels) }
188
196
  end
189
197
  end
190
198
  end
@@ -15,7 +15,7 @@ module Frankenstein
15
15
  #
16
16
  def self.register(registry = Prometheus::Client.registry)
17
17
  GC.stat.each do |k, v|
18
- Frankenstein::CollectedMetric.new(:"ruby_gc_#{k}", "Ruby GC parameter #{k}", registry: registry) do
18
+ Frankenstein::CollectedMetric.new(:"ruby_gc_#{k}", docstring: "Ruby GC parameter #{k}", registry: registry) do
19
19
  { {} => GC.stat[k] }
20
20
  end
21
21
  end
@@ -15,7 +15,7 @@ module Frankenstein
15
15
  #
16
16
  def self.register(registry = Prometheus::Client.registry)
17
17
  RubyVM.stat.each do |k, v|
18
- Frankenstein::CollectedMetric.new(:"ruby_vm_#{k}", "Ruby VM parameter #{k}", registry: registry) do
18
+ Frankenstein::CollectedMetric.new(:"ruby_vm_#{k}", docstring: "Ruby VM parameter #{k}", registry: registry) do
19
19
  { {} => RubyVM.stat[k] }
20
20
  end
21
21
  end
@@ -66,41 +66,35 @@ module Frankenstein
66
66
  @op_cv = ConditionVariable.new
67
67
  end
68
68
 
69
- # Start the server instance running in a separate thread.
69
+ # Start the server instance running.
70
70
  #
71
- # This method returns once the server is just about ready to start serving
72
- # requests.
71
+ # This method will return only after `#shutdown` is called (presumably from
72
+ # another thread).
73
73
  #
74
74
  def run
75
75
  @op_mutex.synchronize do
76
76
  return AlreadyRunningError if @server
77
77
 
78
- @server_thread = Thread.new do
79
- @op_mutex.synchronize do
80
- begin
81
- wrapped_logger = Frankenstein::Server::WEBrickLogger.new(logger: @logger, progname: "Frankenstein::Server")
82
- @server = WEBrick::HTTPServer.new(Logger: wrapped_logger, BindAddress: nil, Port: @port, AccessLog: [[wrapped_logger, WEBrick::AccessLog::COMMON_LOG_FORMAT]])
83
- @server.mount "/", Rack::Handler::WEBrick, app
84
- rescue => ex
85
- #:nocov:
86
- @logger.fatal("Frankenstein::Server#run") { (["Exception while trying to create WEBrick::HTTPServer: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
87
- #:nocov:
88
- ensure
89
- @op_cv.signal
90
- end
91
- end
92
-
93
- begin
94
- @server.start if @server
95
- rescue => ex
96
- #:nocov:
97
- @logger.fatal("Frankenstein::Server#run") { (["Exception while running WEBrick::HTTPServer: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
98
- #:nocov:
99
- end
78
+ begin
79
+ wrapped_logger = Frankenstein::Server::WEBrickLogger.new(logger: @logger, progname: "Frankenstein::Server")
80
+ @server = WEBrick::HTTPServer.new(Logger: wrapped_logger, BindAddress: nil, Port: @port, AccessLog: [[wrapped_logger, WEBrick::AccessLog::COMMON_LOG_FORMAT]])
81
+ @server.mount "/", Rack::Handler::WEBrick, app
82
+ rescue => ex
83
+ #:nocov:
84
+ @logger.fatal("Frankenstein::Server#run") { (["Exception while trying to create WEBrick::HTTPServer: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
85
+ #:nocov:
86
+ ensure
87
+ @op_cv.signal
100
88
  end
101
89
  end
102
90
 
103
- @op_mutex.synchronize { @op_cv.wait(@op_mutex) until @server }
91
+ begin
92
+ @server.start if @server
93
+ rescue => ex
94
+ #:nocov:
95
+ @logger.fatal("Frankenstein::Server#run") { (["Exception while running WEBrick::HTTPServer: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
96
+ #:nocov:
97
+ end
104
98
  end
105
99
 
106
100
  # Terminate a running server instance.
@@ -112,8 +106,6 @@ module Frankenstein
112
106
  return nil if @server.nil?
113
107
  @server.shutdown
114
108
  @server = nil
115
- @server_thread.join
116
- @server_thread = nil
117
109
  end
118
110
  end
119
111
 
@@ -125,9 +117,7 @@ module Frankenstein
125
117
  builder.use Rack::Deflater, if: ->(_, _, _, body) { body.any? && body[0].length > 512 }
126
118
  builder.use Prometheus::Middleware::Collector,
127
119
  registry: @registry,
128
- metrics_prefix: @metrics_prefix,
129
- counter_label_builder: ->(_, _) { {} },
130
- duration_label_builder: ->(_, _) { {} }
120
+ metrics_prefix: @metrics_prefix
131
121
  builder.use Prometheus::Middleware::Exporter, registry: @registry
132
122
  builder.run ->(_) { [301, { 'Location' => "/metrics", 'Content-Type' => 'text/plain' }, ["Try /metrics"]] }
133
123
  builder.to_app
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frankenstein
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-13 00:00:00.000000000 Z
11
+ date: 2020-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prometheus-client
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.8.0
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.8.0
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,20 +94,6 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: guard-rubocop
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rack-test
113
99
  requirement: !ruby/object:Gem::Requirement
@@ -164,20 +150,6 @@ dependencies:
164
150
  - - ">="
165
151
  - !ruby/object:Gem::Version
166
152
  version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: rubocop
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- version: '0'
181
153
  - !ruby/object:Gem::Dependency
182
154
  name: simplecov
183
155
  requirement: !ruby/object:Gem::Requirement
@@ -217,7 +189,6 @@ extensions: []
217
189
  extra_rdoc_files: []
218
190
  files:
219
191
  - ".gitignore"
220
- - ".rubocop.yml"
221
192
  - ".travis.yml"
222
193
  - ".yardopts"
223
194
  - CODE_OF_CONDUCT.md
@@ -229,6 +200,7 @@ files:
229
200
  - lib/frankenstein/collected_metric.rb
230
201
  - lib/frankenstein/error.rb
231
202
  - lib/frankenstein/process_metrics.rb
203
+ - lib/frankenstein/remove_time_series.rb
232
204
  - lib/frankenstein/request.rb
233
205
  - lib/frankenstein/ruby_gc_metrics.rb
234
206
  - lib/frankenstein/ruby_vm_metrics.rb
@@ -252,8 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
252
224
  - !ruby/object:Gem::Version
253
225
  version: '0'
254
226
  requirements: []
255
- rubyforge_project:
256
- rubygems_version: 2.5.2.1
227
+ rubygems_version: 3.0.3
257
228
  signing_key:
258
229
  specification_version: 4
259
230
  summary: or, the Modern Prometheus
@@ -1,104 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 2.4
3
- DisabledByDefault: true
4
-
5
- # Prefer &&/|| over and/or.
6
- Style/AndOr:
7
- Enabled: true
8
-
9
- # Do not use braces for hash literals when they are the last argument of a
10
- # method call.
11
- Style/BracesAroundHashParameters:
12
- Enabled: true
13
-
14
- # Align `when` with `case`.
15
- Layout/CaseIndentation:
16
- Enabled: true
17
-
18
- # Align comments with method definitions.
19
- Layout/CommentIndentation:
20
- Enabled: true
21
-
22
- # No extra empty lines.
23
- Layout/EmptyLines:
24
- Enabled: true
25
-
26
- # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
27
- Style/HashSyntax:
28
- Enabled: true
29
-
30
- # Two spaces, no tabs (for indentation).
31
- Layout/IndentationWidth:
32
- Enabled: true
33
-
34
- Layout/SpaceAfterColon:
35
- Enabled: true
36
-
37
- Layout/SpaceAfterComma:
38
- Enabled: true
39
-
40
- Layout/SpaceAroundEqualsInParameterDefault:
41
- Enabled: true
42
-
43
- Layout/SpaceAroundKeyword:
44
- Enabled: true
45
-
46
- Layout/SpaceAroundOperators:
47
- Enabled: true
48
-
49
- Layout/SpaceBeforeFirstArg:
50
- Enabled: true
51
-
52
- # Defining a method with parameters needs parentheses.
53
- Style/MethodDefParentheses:
54
- Enabled: true
55
-
56
- # Use `foo {}` not `foo{}`.
57
- Layout/SpaceBeforeBlockBraces:
58
- Enabled: true
59
-
60
- # Use `foo { bar }` not `foo {bar}`.
61
- Layout/SpaceInsideBlockBraces:
62
- Enabled: true
63
-
64
- # Use `{ a: 1 }` not `{a:1}`.
65
- Layout/SpaceInsideHashLiteralBraces:
66
- Enabled: true
67
-
68
- Layout/SpaceInsideParens:
69
- Enabled: true
70
-
71
- # Detect hard tabs, no hard tabs.
72
- Layout/Tab:
73
- Enabled: true
74
-
75
- # Blank lines should not have any spaces.
76
- Layout/TrailingBlankLines:
77
- Enabled: true
78
-
79
- # No trailing whitespace.
80
- Layout/TrailingWhitespace:
81
- Enabled: true
82
-
83
- Lint/BlockAlignment:
84
- Enabled: true
85
-
86
- # Align `end` with the matching keyword or starting expression except for
87
- # assignments, where it should be aligned with the LHS.
88
- Lint/EndAlignment:
89
- Enabled: true
90
- EnforcedStyleAlignWith: variable
91
-
92
- # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
93
- Lint/RequireParentheses:
94
- Enabled: true
95
-
96
- Layout/MultilineMethodCallIndentation:
97
- Enabled: true
98
- EnforcedStyle: indented
99
-
100
- Layout/AlignHash:
101
- Enabled: true
102
-
103
- Bundler/OrderedGems:
104
- Enabled: false