logstash-logger 0.25.1 → 0.26.0

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
  SHA1:
3
- metadata.gz: '02946cc68ecd472a33ee4e20c8b0f9676a35c31e'
4
- data.tar.gz: 22ebacf159993cebd61ec2f2069c5d35ccb5949e
3
+ metadata.gz: 2f81edad89b077de5fa36b1b1291f6b0d1c66761
4
+ data.tar.gz: 9834bb9837f9b9d6672f6a24b0325e3d2d9098ef
5
5
  SHA512:
6
- metadata.gz: d19465ebd83bb4a0710eac75face6c11287c5737fc8683e79e5b725cd81933082d123d0bcf220ab49b267c693b98f6bffc5300c7c6ceae7a0ad7b350654c3fe6
7
- data.tar.gz: f1be1a3735cd768d7c53b5d9cdddb34a3fde4e76d0cc6b770f731a70cd5129d1278bd21017634c9af25c99593d7f006d3d9ed2646a4faf7c84e8e454b85a00d8
6
+ metadata.gz: 49afad48b880a4c98156de108ad9f3105ed3ecf72e38d24987d08027d56ecdc2147c4b46fe0fb9d59799fdfbf44af7218e70e9185470f0f046e89921976afed1
7
+ data.tar.gz: 7274f69bc942ee4c2597682cde7f818c6da371bc58108ef56b2e3002b854e7142f241529003f5ed4f7c2001b35364e23f62572b70430ef9971131088c44a7b71
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.26.0
2
+
3
+ - Allow user configuration of the logger class. [#129](https://github.com/dwbutler/logstash-logger/pull/129)
4
+ - Fix: Allow type to be a string for multi_logger and syslog. [#131](https://github.com/dwbutler/logstash-logger/pull/131)
5
+ - Fix: Cancelled events are being logged. [#133](https://github.com/dwbutler/logstash-logger/issues/133)
6
+ - Fix: Expose method to reset logger state. [#138](https://github.com/dwbutler/logstash-logger/pull/138)
7
+ - Use specific AWS SDK gems. [#136](https://github.com/dwbutler/logstash-logger/pull/136)
8
+ - Adds support for using the default AWS credential provider chain. [#141](https://github.com/dwbutler/logstash-logger/pull/141)
9
+
1
10
  ## 0.25.1
2
11
 
3
12
  - Skip message truncating when there is no message field. [#130](https://github.com/dwbutler/logstash-logger/pull/130)
data/README.md CHANGED
@@ -399,6 +399,15 @@ logger.silence(temporary_level) do
399
399
  end
400
400
  ```
401
401
 
402
+ ## Custom Logger Class
403
+
404
+ By default, LogStashLogger creates a logger that extends Ruby's built in `Logger` class.
405
+ If you require a different logger implementation, you can use a different class
406
+ by passing in the class with the `logger_class` option.
407
+
408
+ Note that for syslog, the `Syslog::Logger` class is required and cannot be
409
+ changed.
410
+
402
411
  ## Rails Integration
403
412
 
404
413
  Supports Rails 4 and 5.
@@ -559,6 +568,10 @@ config.logstash.backoff = 1
559
568
 
560
569
  Add the aws-sdk gem to your Gemfile:
561
570
 
571
+ # aws-sdk >= 3.0
572
+ gem 'aws-sdk-kinesis'
573
+
574
+ # aws-sdk < 3.0
562
575
  gem 'aws-sdk'
563
576
 
564
577
  ```ruby
@@ -583,6 +596,10 @@ config.logstash.aws_secret_access_key = 'ASKASKHLD1234123412341234'
583
596
 
584
597
  Add the aws-sdk gem to your Gemfile:
585
598
 
599
+ # aws-sdk >= 3.0
600
+ gem 'aws-sdk-firehose'
601
+
602
+ # aws-sdk < 3.0
586
603
  gem 'aws-sdk'
587
604
 
588
605
  ```ruby
@@ -592,13 +609,13 @@ config.logstash.type = :firehose
592
609
  # Optional, will default to the 'logstash' delivery stream
593
610
  config.logstash.stream = 'my-stream-name'
594
611
 
595
- # Optional, will default to 'us-east-1'
612
+ # Optional, will default to AWS default region config chain
596
613
  config.logstash.aws_region = 'us-west-2'
597
614
 
598
- # Optional, will default to the AWS_ACCESS_KEY_ID environment variable
615
+ # Optional, will default to AWS default credential provider chain
599
616
  config.logstash.aws_access_key_id = 'ASKASKHLD12341'
600
617
 
601
- # Optional, will default to the AWS_SECRET_ACCESS_KEY environment variable
618
+ # Optional, will default to AWS default credential provider chain
602
619
  config.logstash.aws_secret_access_key = 'ASKASKHLD1234123412341234'
603
620
 
604
621
  ```
@@ -693,6 +710,36 @@ def track_load_balancer_session_id
693
710
  end
694
711
  ```
695
712
 
713
+ ## Cleaning up resources when forking
714
+
715
+ If your application forks (as is common with many web servers) you will need to
716
+ manage cleaning up resources on your LogStashLogger instances. The instance method
717
+ `#reset` is available for this purpose. Here is sample configuration for
718
+ several common web servers used with Rails:
719
+
720
+ Passenger:
721
+ ```ruby
722
+ ::PhusionPassenger.on_event(:starting_worker_process) do |forked|
723
+ Rails.logger.reset
724
+ end
725
+ ```
726
+
727
+ Puma:
728
+ ```ruby
729
+ # In config/puma.rb
730
+ on_worker_boot do
731
+ Rails.logger.reset
732
+ end
733
+ ```
734
+
735
+ Unicorn
736
+ ```ruby
737
+ # In config/unicorn.rb
738
+ after_fork do |server, worker|
739
+ Rails.logger.reset
740
+ end
741
+ ```
742
+
696
743
  ## Ruby Compatibility
697
744
 
698
745
  Verified to work with:
@@ -818,6 +865,11 @@ logger = LogStashLogger.new('localhost', 5228, :tcp)
818
865
  * [Joao Fernandes](https://github.com/jcmfernandes)
819
866
  * [CoolElvis](https://github.com/coolelvis)
820
867
  * [Sergey Pyankov](https://github.com/esergion)
868
+ * [Alec Hoey](https://github.com/alechoey)
869
+ * [Alexey Krasnoperov](https://github.com/AlexeyKrasnoperov)
870
+ * [Gabriel de Oliveira](https://github.com/gdeoliveira)
871
+ * [Vladislav Syabruk](https://github.com/SeTeM)
872
+ * [Matus Vacula](https://github.com/matus-vacula)
821
873
 
822
874
  ## Contributing
823
875
 
@@ -107,6 +107,8 @@ module LogStashLogger
107
107
  end
108
108
 
109
109
  def reset_buffer
110
+ reset_flush_timer_thread
111
+
110
112
  @buffer_state = {
111
113
  # items accepted from including class
112
114
  :pending_items => {},
@@ -127,7 +129,6 @@ module LogStashLogger
127
129
  :timer => flush_timer_thread
128
130
  }
129
131
 
130
-
131
132
  # events we've accumulated
132
133
  buffer_clear_pending
133
134
  end
@@ -305,6 +306,13 @@ module LogStashLogger
305
306
  end
306
307
  end
307
308
 
309
+ def reset_flush_timer_thread
310
+ unless @flush_timer_thread.nil?
311
+ @flush_timer_thread.kill
312
+ @flush_timer_thread = nil
313
+ end
314
+ end
315
+
308
316
  def buffer_clear_pending
309
317
  @buffer_state[:pending_items] = Hash.new { |h, k| h[k] = [] }
310
318
  @buffer_state[:pending_count] = 0
@@ -1,10 +1,13 @@
1
- require 'aws-sdk'
1
+ begin
2
+ require 'aws-sdk-core'
3
+ rescue LoadError
4
+ require 'aws-sdk'
5
+ end
2
6
 
3
7
  module LogStashLogger
4
8
  module Device
5
9
  class AwsStream < Connectable
6
10
 
7
- DEFAULT_REGION = 'us-east-1'
8
11
  DEFAULT_STREAM = 'logstash'
9
12
 
10
13
  @stream_class = nil
@@ -18,9 +21,9 @@ module LogStashLogger
18
21
 
19
22
  def initialize(opts)
20
23
  super
21
- @access_key_id = opts[:aws_access_key_id] || ENV['AWS_ACCESS_KEY_ID']
22
- @secret_access_key = opts[:aws_secret_access_key] || ENV['AWS_SECRET_ACCESS_KEY']
23
- @aws_region = opts[:aws_region] || DEFAULT_REGION
24
+ @access_key_id = opts[:aws_access_key_id]
25
+ @secret_access_key = opts[:aws_secret_access_key]
26
+ @aws_region = opts[:aws_region]
24
27
  @stream = opts[:stream] || DEFAULT_STREAM
25
28
  end
26
29
 
@@ -41,10 +44,10 @@ module LogStashLogger
41
44
  end
42
45
 
43
46
  def connect
44
- @io = self.class.stream_class.new(
45
- region: @aws_region,
46
- credentials: ::Aws::Credentials.new(@access_key_id, @secret_access_key)
47
- )
47
+ client_opts = {}
48
+ client_opts[:credentials] = Aws::Credentials.new(@access_key_id, @secret_access_key) unless @access_key_id == nil || @secret_access_key == nil
49
+ client_opts[:region] = @aws_region unless @aws_region == nil
50
+ @io = self.class.stream_class.new(client_opts)
48
51
  end
49
52
 
50
53
  def with_connection
@@ -15,7 +15,7 @@ module LogStashLogger
15
15
  end
16
16
 
17
17
  def write(message)
18
- write_one(message)
18
+ write_one(message) unless message.nil?
19
19
  end
20
20
 
21
21
  def write_one(message)
@@ -39,6 +39,10 @@ module LogStashLogger
39
39
  @io && @io.flush
40
40
  end
41
41
 
42
+ def reset
43
+ close
44
+ end
45
+
42
46
  def close(opts = {})
43
47
  close!
44
48
  rescue => e
@@ -56,7 +56,7 @@ module LogStashLogger
56
56
  end
57
57
 
58
58
  def write(message)
59
- buffer_receive message, @buffer_group
59
+ buffer_receive(message, @buffer_group) unless message.nil?
60
60
  end
61
61
 
62
62
  def flush(*args)
@@ -107,6 +107,11 @@ module LogStashLogger
107
107
  fail NotImplementedError
108
108
  end
109
109
 
110
+ def reset
111
+ reset_buffer
112
+ close(flush: false)
113
+ end
114
+
110
115
  def reconnect
111
116
  close(flush: false)
112
117
  connect
@@ -1,4 +1,9 @@
1
- require 'aws-sdk'
1
+ begin
2
+ require 'aws-sdk-firehose'
3
+ rescue LoadError
4
+ require 'aws-sdk'
5
+ end
6
+
2
7
  require 'logstash-logger/device/aws_stream'
3
8
 
4
9
  module LogStashLogger
@@ -1,4 +1,9 @@
1
- require 'aws-sdk'
1
+ begin
2
+ require 'aws-sdk-kinesis'
3
+ rescue LoadError
4
+ require 'aws-sdk'
5
+ end
6
+
2
7
  require 'logstash-logger/device/aws_stream'
3
8
 
4
9
  module LogStashLogger
@@ -14,11 +14,12 @@ module LogStashLogger
14
14
  super()
15
15
  end
16
16
 
17
- def call(severity, time, progname, message)
18
- @event = build_event(message, severity, time)
17
+ def call(severity, time, _progname, message)
18
+ event = build_event(message, severity, time)
19
+ format_event(event) unless event.cancelled?
19
20
  end
20
21
 
21
- protected
22
+ private
22
23
 
23
24
  def build_event(message, severity, time)
24
25
  data = message
@@ -63,6 +64,10 @@ module LogStashLogger
63
64
 
64
65
  event
65
66
  end
67
+
68
+ def format_event(event)
69
+ event
70
+ end
66
71
  end
67
72
  end
68
73
  end
@@ -1,9 +1,10 @@
1
1
  module LogStashLogger
2
2
  module Formatter
3
3
  class Cee < Base
4
- def call(severity, time, progname, message)
5
- super
6
- "@cee:#{@event.to_json}"
4
+ private
5
+
6
+ def format_event(event)
7
+ "@cee:#{event.to_json}"
7
8
  end
8
9
  end
9
10
  end
@@ -2,18 +2,20 @@ module LogStashLogger
2
2
  module Formatter
3
3
  class CeeSyslog < Cee
4
4
  def call(severity, time, progname, message)
5
- @cee = super
6
5
  @progname = progname
7
-
8
- "#{facility}:#{@cee}\n"
6
+ super
9
7
  end
10
8
 
11
- protected
9
+ private
10
+
11
+ def build_facility(host)
12
+ facility = host.dup
13
+ facility << " #{@progname}" if @progname
14
+ facility
15
+ end
12
16
 
13
- def facility
14
- @facility = "#{@event['host']}"
15
- @facility << " #{@progname}" if @progname
16
- @facility
17
+ def format_event(event)
18
+ "#{build_facility(event["host".freeze])}:#{super}\n"
17
19
  end
18
20
  end
19
21
  end
@@ -1,9 +1,10 @@
1
1
  module LogStashLogger
2
2
  module Formatter
3
3
  class Json < Base
4
- def call(severity, time, progname, message)
5
- super
6
- @event.to_json
4
+ private
5
+
6
+ def format_event(event)
7
+ event.to_json
7
8
  end
8
9
  end
9
10
  end
@@ -1,9 +1,10 @@
1
1
  module LogStashLogger
2
2
  module Formatter
3
3
  class JsonLines < Base
4
- def call(severity, time, progname, message)
5
- super
6
- "#{@event.to_json}\n"
4
+ private
5
+
6
+ def format_event(event)
7
+ "#{event.to_json}\n"
7
8
  end
8
9
  end
9
10
  end
@@ -1,9 +1,6 @@
1
1
  module LogStashLogger
2
2
  module Formatter
3
3
  class LogStashEvent < Base
4
- def call(severity, time, progname, message)
5
- super
6
- end
7
4
  end
8
5
  end
9
6
  end
@@ -19,6 +19,10 @@ module LogStashLogger
19
19
  def flush
20
20
  !!(@device.flush if @device.respond_to?(:flush))
21
21
  end
22
+
23
+ def reset
24
+ @device.reset if @device.respond_to?(:reset)
25
+ end
22
26
  end
23
27
  end
24
28
 
@@ -48,7 +52,8 @@ module LogStashLogger
48
52
  def self.build_logger(opts)
49
53
  formatter = Formatter.new(opts.delete(:formatter), customize_event: opts.delete(:customize_event))
50
54
 
51
- logger = case opts[:type]
55
+ logger_type = opts[:type].to_s.to_sym
56
+ logger = case logger_type
52
57
  when :multi_logger
53
58
  build_multi_logger(opts)
54
59
  when :syslog
@@ -64,8 +69,9 @@ module LogStashLogger
64
69
  private
65
70
 
66
71
  def self.build_default_logger(opts)
72
+ logger_class = opts.delete(:logger_class) || ::Logger
67
73
  device = Device.new(opts)
68
- ::Logger.new(device).tap do |logger|
74
+ logger_class.new(device).tap do |logger|
69
75
  logger.instance_variable_set(:@device, device)
70
76
  extend_logger(logger)
71
77
  end
@@ -1,3 +1,3 @@
1
1
  module LogStashLogger
2
- VERSION = "0.25.1"
2
+ VERSION = "0.26.0"
3
3
  end
@@ -34,4 +34,5 @@ Gem::Specification.new do |gem|
34
34
  gem.add_development_dependency 'pry'
35
35
  gem.add_development_dependency 'wwtd'
36
36
  gem.add_development_dependency 'appraisal'
37
+ gem.add_development_dependency 'rubocop'
37
38
  end
@@ -1,22 +1,30 @@
1
1
  require 'logstash-logger'
2
2
 
3
3
  describe LogStashLogger do
4
- describe ".new" do
5
- it "returns a Logger instance" do
4
+ describe '.new' do
5
+ it 'returns a Logger instance' do
6
6
  expect(LogStashLogger.new(type: :stdout)).to be_a ::Logger
7
7
  end
8
8
 
9
- context "type: :multi_logger" do
9
+ context 'type: :multi_logger' do
10
10
  it "returns an instance of LogStashLogger::MultiLogger" do
11
11
  expect(LogStashLogger.new(type: :multi_logger)).to be_a LogStashLogger::MultiLogger
12
12
  end
13
13
 
14
- it "merges top level configuration into each logger" do
14
+ it 'merges top level configuration into each logger' do
15
15
  logger = LogStashLogger.new(type: :multi_logger, port: 1234, outputs: [ { type: :tcp }, { type: :udp } ])
16
16
  logger.loggers.each do |logger|
17
17
  expect(logger.device.port).to eq(1234)
18
18
  end
19
19
  end
20
20
  end
21
+
22
+ context 'logger_class: CustomLogger' do
23
+ class CustomLogger < Logger; end
24
+
25
+ it 'should create a logger of the specified class' do
26
+ expect(LogStashLogger.new(type: :stdout, :logger_class => CustomLogger)).to be_a CustomLogger
27
+ end
28
+ end
21
29
  end
22
30
  end
@@ -1,6 +1,6 @@
1
1
  require 'logstash-logger'
2
2
 
3
- describe LogStashLogger::Device::Kinesis do
3
+ describe LogStashLogger::Device::Firehose do
4
4
  include_context 'device'
5
5
 
6
6
  let(:client) { double("Aws::Firehose::Client") }
@@ -35,10 +35,6 @@ describe LogStashLogger::Device::Kinesis do
35
35
  firehose_device.write_one "foo"
36
36
  end
37
37
 
38
- it "defaults the AWS region to us-east-1" do
39
- expect(firehose_device.aws_region).to eq('us-east-1')
40
- end
41
-
42
38
  it "defaults the Firehose stream to logstash" do
43
39
  expect(firehose_device.stream).to eq('logstash')
44
40
  end
@@ -35,10 +35,6 @@ describe LogStashLogger::Device::Kinesis do
35
35
  kinesis_device.write_one "foo"
36
36
  end
37
37
 
38
- it "defaults the AWS region to us-east-1" do
39
- expect(kinesis_device.aws_region).to eq('us-east-1')
40
- end
41
-
42
38
  it "defaults the kinesis stream to logstash" do
43
39
  expect(kinesis_device.stream).to eq('logstash')
44
40
  end
@@ -3,6 +3,28 @@ require 'logstash-logger'
3
3
  describe LogStashLogger::Formatter::Base do
4
4
  include_context "formatter"
5
5
 
6
+ describe "#call" do
7
+ context "when event is not cancelled" do
8
+ it "returns a formatted message" do
9
+ expect(subject).to receive(:format_event).once.with(instance_of(LogStash::Event)).and_call_original
10
+ expect(subject.call(severity, time, progname, message)).to be_a(LogStash::Event)
11
+ end
12
+ end
13
+
14
+ context "when event is cancelled" do
15
+ before(:each) do
16
+ LogStashLogger.configure do |config|
17
+ config.customize_event(&:cancel)
18
+ end
19
+ end
20
+
21
+ it "returns `nil`" do
22
+ expect(subject).not_to receive(:format_event)
23
+ expect(subject.call(severity, time, progname, message)).to be_nil
24
+ end
25
+ end
26
+ end
27
+
6
28
  describe "#build_event" do
7
29
  let(:event) { formatted_message }
8
30
 
@@ -7,7 +7,7 @@ describe LogStashLogger::Formatter::CeeSyslog do
7
7
  let(:facility) { "facility" }
8
8
 
9
9
  before do
10
- allow(subject).to receive(:facility).and_return(facility)
10
+ allow(subject).to receive(:build_facility).and_return(facility)
11
11
  end
12
12
 
13
13
  it "outputs a facility before the @cee" do
@@ -21,7 +21,7 @@ describe LogStashLogger::Formatter::CeeSyslog do
21
21
  end
22
22
  end
23
23
 
24
- describe "#facility" do
24
+ describe "#build_facility" do
25
25
  let(:host) { Socket.gethostname }
26
26
 
27
27
  before do
@@ -29,14 +29,14 @@ describe LogStashLogger::Formatter::CeeSyslog do
29
29
  end
30
30
 
31
31
  it "includes hostname and progname" do
32
- expect(subject.send(:facility)).to match(/\A#{host}\s#{progname}\z/)
32
+ expect(subject.send(:build_facility, host)).to match(/\A#{host}\s#{progname}\z/)
33
33
  end
34
34
 
35
35
  context "without progname" do
36
36
  let(:progname) { nil }
37
37
 
38
38
  it "only includes hostname" do
39
- expect(subject.send(:facility)).to match(/\A#{host}\z/)
39
+ expect(subject.send(:build_facility, host)).to match(/\A#{host}\z/)
40
40
  end
41
41
  end
42
42
  end
data/spec/syslog_spec.rb CHANGED
@@ -1,25 +1,32 @@
1
1
  require 'logstash-logger'
2
2
 
3
3
  describe LogStashLogger do
4
- context "Syslog" do
5
- let(:program_name) { "MyApp" }
6
- let(:facility) { 128 } #Syslog::LOG_LOCAL0 }
4
+ let(:program_name) { 'MyApp' }
5
+ let(:facility) { 128 } #Syslog::LOG_LOCAL0 }
6
+
7
+ context 'Syslog' do
7
8
  subject { LogStashLogger.new(type: :syslog, program_name: program_name, facility: facility) }
8
9
  let(:syslog) { subject.class.class_variable_get(:@@syslog) }
9
10
 
10
11
  it { is_expected.to be_a Syslog::Logger }
11
12
 
12
- it "writes formatted messages to syslog" do
13
+ it 'writes formatted messages to syslog' do
13
14
  expect(syslog).to receive(:log)
14
- subject.info("test")
15
+ subject.info('test')
15
16
  end
16
17
 
17
- it "sets the syslog identity" do
18
+ it 'sets the syslog identity' do
18
19
  expect(syslog.ident).to eq(program_name)
19
20
  end
20
21
 
21
- it "sets the default facility if supported" do
22
+ it 'sets the default facility if supported' do
22
23
  expect(subject.facility).to eq(facility) if subject.respond_to?(:facility)
23
24
  end
24
25
  end
26
+
27
+ context 'when logger type is a string' do
28
+ subject { LogStashLogger.new(type: 'syslog', program_name: program_name, facility: facility) }
29
+
30
+ it { is_expected.to be_a Syslog::Logger }
31
+ end
25
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.1
4
+ version: 0.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Butler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-08 00:00:00.000000000 Z
11
+ date: 2018-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-event
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  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'
153
167
  description: Ruby logger that writes directly to LogStash
154
168
  email:
155
169
  - dwbutler@ucla.edu
@@ -157,7 +171,6 @@ executables: []
157
171
  extensions: []
158
172
  extra_rdoc_files: []
159
173
  files:
160
- - ".codeclimate.yml"
161
174
  - ".gitignore"
162
175
  - ".rspec"
163
176
  - ".rubocop.yml"
data/.codeclimate.yml DELETED
@@ -1,16 +0,0 @@
1
- ---
2
- engines:
3
- duplication:
4
- enabled: true
5
- config:
6
- languages:
7
- - ruby
8
- fixme:
9
- enabled: true
10
- rubocop:
11
- enabled: true
12
- ratings:
13
- paths:
14
- - "**.rb"
15
- exclude_paths:
16
- - spec/