logstash_writer 0.0.7 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|