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 +4 -4
- data/.editorconfig +7 -0
- data/README.md +1 -1
- data/lib/logstash_writer.rb +100 -84
- data/logstash_writer.gemspec +3 -6
- metadata +8 -37
- data/.rubocop.yml +0 -116
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4f17ecaf181fbd3bf0160ecbd3a0a1fb156b5965be340e4bda05713edafa8fa
|
4
|
+
data.tar.gz: c279de10eb157ab271e88117b78d46fe345b8612648c9a5a945fe01c808752d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3de8d9133af36ed73dcf965db8d8004d2cd92df054d23a59930a2ea444711d579f6877740924860d265fdb30eb2289ca6b5506331685cac8606d1e6ff13f170
|
7
|
+
data.tar.gz: 9d40ca34dd0622593b48ef73c613d278a3f6ab7241abb0f5596e19745094a9791a15e5b9a163167d48b7bb3cd8256d8b5f80616a9b695d7b178d9f3f65cd74e1
|
data/.editorconfig
ADDED
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)
|
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
|
data/lib/logstash_writer.rb
CHANGED
@@ -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`
|
12
|
-
#
|
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:
|
78
|
-
sent:
|
79
|
-
queue_size:
|
80
|
-
dropped:
|
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:
|
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:
|
85
|
-
connect_exception:
|
86
|
-
write_exception:
|
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:
|
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(
|
93
|
-
@metrics[:queue_size].set(
|
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(
|
97
|
+
metrics_registry.gauge(:"#{metrics_prefix}_queue_max", docstring: "The maximum size of the event queue").set(backlog)
|
96
98
|
|
97
|
-
|
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`
|
108
|
-
#
|
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
|
175
|
+
def start!
|
161
176
|
@worker_mutex.synchronize do
|
162
177
|
if @worker_thread.nil?
|
163
|
-
|
164
|
-
|
165
|
-
|
178
|
+
@queue_mutex.synchronize do
|
179
|
+
@terminate = false
|
180
|
+
end
|
166
181
|
|
167
|
-
|
168
|
-
|
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
|
-
@
|
187
|
-
|
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
|
-
|
231
|
-
|
232
|
-
event = nil
|
248
|
+
until @terminate do
|
249
|
+
event = nil
|
233
250
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
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(
|
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 }
|
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 }
|
306
|
-
@logger.
|
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(
|
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
|
data/logstash_writer.gemspec
CHANGED
@@ -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
|
-
|
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.
|
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:
|
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:
|
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:
|
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
|
-
|
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
|
data/.rubocop.yml
DELETED
@@ -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
|