logstash_writer 0.0.7 → 0.0.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9254bae4e4a6f114fd683a3509b576d272256e162ecc5722c8d1c7a78a3e25e3
4
- data.tar.gz: 9e61badc96a9bc3028a15311117eb95b6d3f37c7c59d950d66fe76d223160363
3
+ metadata.gz: b4f17ecaf181fbd3bf0160ecbd3a0a1fb156b5965be340e4bda05713edafa8fa
4
+ data.tar.gz: c279de10eb157ab271e88117b78d46fe345b8612648c9a5a945fe01c808752d3
5
5
  SHA512:
6
- metadata.gz: 97ebc1f452ecc063b81e534ffb87e62ac4f225101454494ad8058abc18cef6427986b93a8643bc87631fdbde9d629dbebb35a51936f403a20e2d84b5517086b5
7
- data.tar.gz: 01f8be94cee73a68b228e69f55f4f2d8e6448f8d37d885427a741cb8786f4c8fc37e1a99567ee92c8133f27e3faded0f6b3b1ca19cfe0bc382696682b281b6c7
6
+ metadata.gz: f3de8d9133af36ed73dcf965db8d8004d2cd92df054d23a59930a2ea444711d579f6877740924860d265fdb30eb2289ca6b5506331685cac8606d1e6ff13f170
7
+ data.tar.gz: 9d40ca34dd0622593b48ef73c613d278a3f6ab7241abb0f5596e19745094a9791a15e5b9a163167d48b7bb3cd8256d8b5f80616a9b695d7b178d9f3f65cd74e1
@@ -0,0 +1,7 @@
1
+ [*.rb]
2
+ indent_style = space
3
+ indent_size = 2
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ charset = utf-8
7
+ trim_trailing_whitespace = true
data/README.md CHANGED
@@ -186,7 +186,7 @@ conduct](CODE_OF_CONDUCT.md).
186
186
  Unless otherwise stated, everything in this repo is covered by the following
187
187
  copyright notice:
188
188
 
189
- Copyright (C) 2015 Civilized Discourse Construction Kit, Inc.
189
+ Copyright (C) 2016,2017,2018 Civilized Discourse Construction Kit, Inc.
190
190
 
191
191
  This program is free software: you can redistribute it and/or modify it
192
192
  under the terms of the GNU General Public License version 3, as
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'ipaddr'
2
4
  require 'json'
3
5
  require 'resolv'
@@ -8,8 +10,8 @@ require 'prometheus/client'
8
10
  #
9
11
  # Flings events, represented as JSON objects, to logstash using the
10
12
  # `json_lines` codec (over TCP). Doesn't do any munging or modification of
11
- # the event data given to it, other than adding `@timestamp` and
12
- # `[@metadata][_id]` fields if they do not already exist.
13
+ # the event data given to it, other than adding a `@timestamp` field if
14
+ # it doesn't already exist.
13
15
  #
14
16
  # We support highly-available logstash installations by means of multiple
15
17
  # address records, or via SRV records. See the docs for .new for details
@@ -74,27 +76,29 @@ class LogstashWriter
74
76
  @server_name, @logger, @backlog = server_name, logger, backlog
75
77
 
76
78
  @metrics = {
77
- received: metrics_registry.counter(:"#{metrics_prefix}_events_received_total", "The number of logstash events which have been submitted for delivery"),
78
- sent: metrics_registry.counter(:"#{metrics_prefix}_events_written_total", "The number of logstash events which have been delivered to the logstash server"),
79
- queue_size: metrics_registry.gauge(:"#{metrics_prefix}_queue_size", "The number of events currently in the queue to be sent"),
80
- dropped: metrics_registry.counter(:"#{metrics_prefix}_events_dropped_total", "The number of events which have been dropped from the queue"),
79
+ received: metrics_registry.counter(:"#{metrics_prefix}_events_received_total", docstring: "The number of logstash events which have been submitted for delivery"),
80
+ sent: metrics_registry.counter(:"#{metrics_prefix}_events_written_total", docstring: "The number of logstash events which have been delivered to the logstash server", labels: %i{server}),
81
+ queue_size: metrics_registry.gauge(:"#{metrics_prefix}_queue_size", docstring: "The number of events currently in the queue to be sent"),
82
+ dropped: metrics_registry.counter(:"#{metrics_prefix}_events_dropped_total", docstring: "The number of events which have been dropped from the queue"),
81
83
 
82
- lag: metrics_registry.gauge(:"#{metrics_prefix}_last_sent_event_time_seconds", "When the last event successfully sent to logstash was originally received"),
84
+ lag: metrics_registry.gauge(:"#{metrics_prefix}_last_sent_event_time_seconds", docstring: "When the last event successfully sent to logstash was originally received"),
83
85
 
84
- connected: metrics_registry.gauge(:"#{metrics_prefix}_connected_to_server", "Boolean flag indicating whether we are currently connected to a logstash server"),
85
- connect_exception: metrics_registry.counter(:"#{metrics_prefix}_connect_exceptions_total", "The number of exceptions that have occurred whilst attempting to connect to a logstash server"),
86
- write_exception: metrics_registry.counter(:"#{metrics_prefix}_write_exceptions_total", "The number of exceptions that have occurred whilst attempting to write an event to a logstash server"),
86
+ connected: metrics_registry.gauge(:"#{metrics_prefix}_connected_to_server", docstring: "Boolean flag indicating whether we are currently connected to a logstash server", labels: %i{server}),
87
+ connect_exception: metrics_registry.counter(:"#{metrics_prefix}_connect_exceptions_total", docstring: "The number of exceptions that have occurred whilst attempting to connect to a logstash server", labels: %i{server class}),
88
+ write_exception: metrics_registry.counter(:"#{metrics_prefix}_write_exceptions_total", docstring: "The number of exceptions that have occurred whilst attempting to write an event to a logstash server", labels: %i{server class}),
87
89
 
88
- write_loop_exception: metrics_registry.counter(:"#{metrics_prefix}_write_loop_exceptions_total", "The number of exceptions that have occurred in the writing loop"),
89
- write_loop_ok: metrics_registry.gauge(:"#{metrics_prefix}_write_loop_ok", "Boolean flag indicating whether the writing loop is currently operating correctly, or is in a post-apocalyptic hellscape of never-ending exceptions"),
90
+ write_loop_exception: metrics_registry.counter(:"#{metrics_prefix}_write_loop_exceptions_total", docstring: "The number of exceptions that have occurred in the writing loop", labels: %i{class}),
91
+ write_loop_ok: metrics_registry.gauge(:"#{metrics_prefix}_write_loop_ok", docstring: "Boolean flag indicating whether the writing loop is currently operating correctly, or is in a post-apocalyptic hellscape of never-ending exceptions"),
90
92
  }
91
93
 
92
- @metrics[:lag].set({}, 0)
93
- @metrics[:queue_size].set({}, 0)
94
+ @metrics[:lag].set(0)
95
+ @metrics[:queue_size].set(0)
94
96
 
95
- metrics_registry.gauge(:"#{metrics_prefix}_queue_max", "The maximum size of the event queue").set({}, backlog)
97
+ metrics_registry.gauge(:"#{metrics_prefix}_queue_max", docstring: "The maximum size of the event queue").set(backlog)
96
98
 
97
- @queue = []
99
+ # We can't use a stdlib Queue object because we need to re-push items
100
+ # onto the front of the queue in case of error
101
+ @queue = []
98
102
  @queue_mutex = Mutex.new
99
103
  @queue_cv = ConditionVariable.new
100
104
 
@@ -104,8 +108,8 @@ class LogstashWriter
104
108
 
105
109
  # Add an event to the queue, to be sent to logstash. Actual event
106
110
  # delivery will happen in a worker thread that is started with
107
- # #run. If the event does not have a `@timestamp` or `[@metadata][_id]`
108
- # element, they will be added with appropriate values.
111
+ # #run. If the event does not have a `@timestamp` field, it will
112
+ # be added set to the current time.
109
113
  #
110
114
  # @param e [Hash] the event data to be sent.
111
115
  #
@@ -120,22 +124,6 @@ class LogstashWriter
120
124
  e[:@timestamp] = Time.now.utc.strftime("%FT%T.%NZ")
121
125
  end
122
126
 
123
- if e.has_key?("@metadata")
124
- e[:@metadata] = (e[:@metadata] || {}).merge(e.delete("@metadata"))
125
- end
126
-
127
- unless e.has_key?(:@metadata)
128
- e[:@metadata] = {}
129
- end
130
-
131
- unless e[:@metadata].has_key?(:_id) || e.has_key?("_id")
132
- # This is the quickest way I've found to get a long, random string.
133
- # We don't need any sort of cryptographic or unpredictability
134
- # guarantees for what we're doing here, so SecureRandom is unnecessary
135
- # overhead.
136
- e[:@metadata][:_id] = rand(0x1000_0000_0000_0000_0000_0000_0000_0000).to_s(36)
137
- end
138
-
139
127
  @queue_mutex.synchronize do
140
128
  @queue << { content: e, arrival_timestamp: Time.now }
141
129
  while @queue.length > @backlog
@@ -150,6 +138,33 @@ class LogstashWriter
150
138
  nil
151
139
  end
152
140
 
141
+ # Send events.
142
+ #
143
+ # Does not return until `#shutdown` is called (in another thread).
144
+ #
145
+ def run
146
+ @queue_mutex.synchronize do
147
+ @terminate = false
148
+ end
149
+
150
+ write_loop
151
+ end
152
+
153
+ # Tell the LogstashWriter to flush its queue and terminate operation.
154
+ #
155
+ # Returns immediately.
156
+ #
157
+ def shutdown
158
+ #:nocov:
159
+ @worker_mutex.synchronize do
160
+ @queue_mutex.synchronize do
161
+ @terminate = true
162
+ @queue_cv.signal
163
+ end
164
+ end
165
+ #:nocov:
166
+ end
167
+
153
168
  # Start sending events.
154
169
  #
155
170
  # This method will return almost immediately, and actual event
@@ -157,15 +172,16 @@ class LogstashWriter
157
172
  #
158
173
  # @return [NilClass]
159
174
  #
160
- def run
175
+ def start!
161
176
  @worker_mutex.synchronize do
162
177
  if @worker_thread.nil?
163
- m, cv = Mutex.new, ConditionVariable.new
164
-
165
- @worker_thread = Thread.new { cv.signal; write_loop }
178
+ @queue_mutex.synchronize do
179
+ @terminate = false
180
+ end
166
181
 
167
- # Don't return until the thread has *actually* started
168
- m.synchronize { cv.wait(m) }
182
+ @worker_thread = Thread.new do
183
+ write_loop
184
+ end
169
185
  end
170
186
  end
171
187
 
@@ -180,18 +196,19 @@ class LogstashWriter
180
196
  #
181
197
  # @return [NilClass]
182
198
  #
183
- def stop
199
+ def stop!
184
200
  @worker_mutex.synchronize do
185
201
  if @worker_thread
186
- @terminate = true
187
- @queue_cv.signal
202
+ @queue_mutex.synchronize do
203
+ @terminate = true
204
+ @queue_cv.signal
205
+ end
188
206
  begin
189
- @worker_thread.join
207
+ @worker_thread.join unless @worker_thread == Thread.current
190
208
  rescue Exception => ex
191
209
  @logger.error("LogstashWriter") { (["Worker thread terminated with exception: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
192
210
  end
193
211
  @worker_thread = nil
194
- @socket_mutex.synchronize { (@current_target.close; @current_target = nil) if @current_target }
195
212
  end
196
213
  end
197
214
 
@@ -226,45 +243,43 @@ class LogstashWriter
226
243
  #
227
244
  def write_loop
228
245
  error_wait = INITIAL_RETRY_WAIT
246
+ Thread.current.name = "LogstashWriter"
229
247
 
230
- catch :terminate do
231
- loop do
232
- event = nil
248
+ until @terminate do
249
+ event = nil
233
250
 
234
- begin
235
- @queue_mutex.synchronize do
236
- while @queue.empty? && !@terminate
237
- @queue_cv.wait(@queue_mutex)
238
- end
239
-
240
- if @queue.empty? && @terminate
241
- @terminate = false
242
- throw :terminate
243
- end
244
-
245
- event = @queue.shift
251
+ begin
252
+ @queue_mutex.synchronize do
253
+ while @queue.empty? && !@terminate
254
+ @queue_cv.wait(@queue_mutex)
246
255
  end
247
256
 
257
+ event = @queue.shift
258
+ end
259
+
260
+ if event
248
261
  current_target do |t|
249
262
  t.socket.puts event[:content].to_json
250
263
  stat_sent(t.to_s, event[:arrival_timestamp])
251
- @metrics[:write_loop_ok].set({}, 1)
264
+ @metrics[:write_loop_ok].set(1)
252
265
  error_wait = INITIAL_RETRY_WAIT
253
266
  end
254
- rescue StandardError => ex
255
- @logger.error("LogstashWriter") { (["Exception in write_loop: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
256
- @queue_mutex.synchronize { @queue.unshift(event) if event }
257
- @metrics[:write_loop_exception].increment(class: ex.class.to_s)
258
- @metrics[:write_loop_ok].set({}, 0)
259
- sleep error_wait
260
- # Increase the error wait timeout for next time, up to a maximum
261
- # interval of about 60 seconds
262
- error_wait *= 1.1
263
- error_wait = 60 if error_wait > 60
264
- error_wait += rand / 0.5
265
267
  end
268
+ rescue StandardError => ex
269
+ @logger.error("LogstashWriter") { (["Exception in write_loop: #{ex.message} (#{ex.class})"] + ex.backtrace).join("\n ") }
270
+ @queue_mutex.synchronize { @queue.unshift(event) if event }
271
+ @metrics[:write_loop_exception].increment(labels: { class: ex.class.to_s })
272
+ @metrics[:write_loop_ok].set(0)
273
+ sleep error_wait
274
+ # Increase the error wait timeout for next time, up to a maximum
275
+ # interval of about 60 seconds
276
+ error_wait *= 1.1
277
+ error_wait = 60 if error_wait > 60
278
+ error_wait += rand / 0.5
266
279
  end
267
280
  end
281
+
282
+ force_disconnect!
268
283
  end
269
284
 
270
285
  # Yield a Target connected to the server we currently believe to be
@@ -296,14 +311,14 @@ class LogstashWriter
296
311
  raise Errno::ENOTCONN unless IO.select([@current_target.socket], [], [], 0).nil?
297
312
 
298
313
  yield @current_target
299
- @metrics[:connected].set({ server: @current_target.describe_peer }, 1)
314
+ @metrics[:connected].set(1, labels: { server: @current_target.describe_peer })
300
315
  done = true
301
316
  rescue SystemCallError => ex
302
317
  # Something went wrong during the send; disconnect from this
303
318
  # server and recycle
304
- @metrics[:write_exception].increment(server: @current_target.describe_peer, class: ex.class.to_s)
305
- @metrics[:connected].set({ server: @current_target.describe_peer }, 0)
306
- @logger.info("LogstashWriter") { "Error while writing to current server #{@current_target.describe_peer}: #{ex.message} (#{ex.class})" }
319
+ @metrics[:write_exception].increment(labels: { server: @current_target.describe_peer, class: ex.class.to_s })
320
+ @metrics[:connected].set(0, labels: { server: @current_target.describe_peer })
321
+ @logger.error("LogstashWriter") { "Error while writing to current server #{@current_target.describe_peer}: #{ex.message} (#{ex.class})" }
307
322
  @current_target.close
308
323
  @current_target = nil
309
324
 
@@ -328,6 +343,7 @@ class LogstashWriter
328
343
  @current_target = next_server
329
344
  # Trigger a connection attempt
330
345
  @current_target.socket
346
+ @logger.info("LogstashWriter") { "Connected to #{@current_target.describe_peer}" }
331
347
  else
332
348
  @logger.debug("LogstashWriter") { "Could not connect to any server; pausing before trying again" }
333
349
  @current_target = nil
@@ -344,7 +360,7 @@ class LogstashWriter
344
360
  end
345
361
  rescue SystemCallError => ex
346
362
  # Connection failed for any number of reasons; try the next one in the list
347
- @metrics[:connect_exception].increment(server: next_server.to_s, class: ex.class.to_s)
363
+ @metrics[:connect_exception].increment(labels: { server: next_server.to_s, class: ex.class.to_s })
348
364
  @logger.error("LogstashWriter") { "Failed to connect to #{next_server.to_s}: #{ex.message} (#{ex.class})" }
349
365
  sleep INITIAL_RETRY_WAIT
350
366
  retry
@@ -436,19 +452,19 @@ class LogstashWriter
436
452
  end
437
453
 
438
454
  def stat_received
439
- @metrics[:received].increment({})
440
- @metrics[:queue_size].increment({})
455
+ @metrics[:received].increment
456
+ @metrics[:queue_size].increment
441
457
  end
442
458
 
443
459
  def stat_sent(peer, arrived_time)
444
- @metrics[:sent].increment(server: peer)
445
- @metrics[:queue_size].decrement({})
446
- @metrics[:lag].set({}, arrived_time.to_f)
460
+ @metrics[:sent].increment(labels: { server: peer })
461
+ @metrics[:queue_size].decrement
462
+ @metrics[:lag].set(arrived_time.to_f)
447
463
  end
448
464
 
449
465
  def stat_dropped
450
- @metrics[:queue_size].decrement({})
451
- @metrics[:dropped].increment({})
466
+ @metrics[:queue_size].decrement
467
+ @metrics[:dropped].increment
452
468
  end
453
469
 
454
470
  # An individual target for logstash messages
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'git-version-bump'
3
5
  rescue LoadError
@@ -27,21 +29,16 @@ Gem::Specification.new do |s|
27
29
 
28
30
  s.required_ruby_version = ">= 2.3.0"
29
31
 
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"
32
+ s.add_runtime_dependency "prometheus-client", "~> 2.0"
34
33
 
35
34
  s.add_development_dependency 'bundler'
36
35
  s.add_development_dependency 'github-release'
37
36
  s.add_development_dependency 'git-version-bump'
38
37
  s.add_development_dependency 'guard-rspec'
39
- s.add_development_dependency 'guard-rubocop'
40
38
  s.add_development_dependency 'rack-test'
41
39
  s.add_development_dependency 'rake', "~> 12.0"
42
40
  s.add_development_dependency 'redcarpet'
43
41
  s.add_development_dependency 'rspec'
44
- s.add_development_dependency 'rubocop'
45
42
  s.add_development_dependency 'simplecov'
46
43
  s.add_development_dependency 'yard'
47
44
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash_writer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.12
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-10-04 00:00:00.000000000 Z
11
+ date: 2020-05-31 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: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,6 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: guard-rubocop
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rack-test
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -150,20 +136,6 @@ dependencies:
150
136
  - - ">="
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: rubocop
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
139
  - !ruby/object:Gem::Dependency
168
140
  name: simplecov
169
141
  requirement: !ruby/object:Gem::Requirement
@@ -202,8 +174,8 @@ executables: []
202
174
  extensions: []
203
175
  extra_rdoc_files: []
204
176
  files:
177
+ - ".editorconfig"
205
178
  - ".gitignore"
206
- - ".rubocop.yml"
207
179
  - ".travis.yml"
208
180
  - ".yardopts"
209
181
  - CODE_OF_CONDUCT.md
@@ -230,8 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
202
  - !ruby/object:Gem::Version
231
203
  version: '0'
232
204
  requirements: []
233
- rubyforge_project:
234
- rubygems_version: 2.7.7
205
+ rubygems_version: 3.0.3
235
206
  signing_key:
236
207
  specification_version: 4
237
208
  summary: Opinionated logstash event pump
@@ -1,116 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 2.4
3
- DisabledByDefault: true
4
- Exclude:
5
- - 'db/schema.rb'
6
- - 'bundle/**/*'
7
- - 'vendor/**/*'
8
- - 'node_modules/**/*'
9
- - 'public/**/*'
10
-
11
- # Prefer &&/|| over and/or.
12
- Style/AndOr:
13
- Enabled: true
14
-
15
- # Do not use braces for hash literals when they are the last argument of a
16
- # method call.
17
- Style/BracesAroundHashParameters:
18
- Enabled: true
19
-
20
- # Align `when` with `case`.
21
- Layout/CaseIndentation:
22
- Enabled: true
23
-
24
- # Align comments with method definitions.
25
- Layout/CommentIndentation:
26
- Enabled: true
27
-
28
- # No extra empty lines.
29
- Layout/EmptyLines:
30
- Enabled: true
31
-
32
- # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
33
- Style/HashSyntax:
34
- Enabled: true
35
-
36
- # Two spaces, no tabs (for indentation).
37
- Layout/IndentationWidth:
38
- Enabled: true
39
-
40
- Layout/SpaceAfterColon:
41
- Enabled: true
42
-
43
- Layout/SpaceAfterComma:
44
- Enabled: true
45
-
46
- Layout/SpaceAroundEqualsInParameterDefault:
47
- Enabled: true
48
-
49
- Layout/SpaceAroundKeyword:
50
- Enabled: true
51
-
52
- Layout/SpaceAroundOperators:
53
- Enabled: true
54
-
55
- Layout/SpaceBeforeFirstArg:
56
- Enabled: true
57
-
58
- # Defining a method with parameters needs parentheses.
59
- Style/MethodDefParentheses:
60
- Enabled: true
61
-
62
- # Use `foo {}` not `foo{}`.
63
- Layout/SpaceBeforeBlockBraces:
64
- Enabled: true
65
-
66
- # Use `foo { bar }` not `foo {bar}`.
67
- Layout/SpaceInsideBlockBraces:
68
- Enabled: true
69
-
70
- # Use `{ a: 1 }` not `{a:1}`.
71
- Layout/SpaceInsideHashLiteralBraces:
72
- Enabled: true
73
-
74
- Layout/SpaceInsideParens:
75
- Enabled: true
76
-
77
- # Detect hard tabs, no hard tabs.
78
- Layout/Tab:
79
- Enabled: true
80
-
81
- # Blank lines should not have any spaces.
82
- Layout/TrailingBlankLines:
83
- Enabled: true
84
-
85
- # No trailing whitespace.
86
- Layout/TrailingWhitespace:
87
- Enabled: true
88
-
89
- Lint/Debugger:
90
- Enabled: true
91
-
92
- Layout/BlockAlignment:
93
- Enabled: true
94
-
95
- # Align `end` with the matching keyword or starting expression except for
96
- # assignments, where it should be aligned with the LHS.
97
- Layout/EndAlignment:
98
- Enabled: true
99
- EnforcedStyleAlignWith: variable
100
-
101
- # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
102
- Lint/RequireParentheses:
103
- Enabled: true
104
-
105
- Lint/ShadowingOuterLocalVariable:
106
- Enabled: true
107
-
108
- Layout/MultilineMethodCallIndentation:
109
- Enabled: true
110
- EnforcedStyle: indented
111
-
112
- Layout/AlignHash:
113
- Enabled: true
114
-
115
- Bundler/OrderedGems:
116
- Enabled: false