logstash-logger 0.7.0 → 0.8.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
2
  SHA1:
3
- metadata.gz: 028f82a7160982a2b3d5d7fea16a87b408f28f19
4
- data.tar.gz: 31e13e392d3315844dfeb73e7f8b61a764575d60
3
+ metadata.gz: 226fca630b4975188d705c7a09a96f48d8fe7f3b
4
+ data.tar.gz: f898f4f314c038719ce689f1e9a63c4f4679bbd9
5
5
  SHA512:
6
- metadata.gz: 5c97296f106d4c66323026861e587dc98b2dd00bb53a09fa2de273cbd4bcb2dd8270ffee84e2003fbb0309343a42485d08b104108da512a45f59ba39a312b711
7
- data.tar.gz: dec18c3ff5a7d76da22ab9cdb8e62bca254742013b2f12b09298a1753bd8c3f288d35ebd18eb51b7b5eee8afd4545abedcd40a694d48b7d6d621092be3d9a884
6
+ metadata.gz: ef10037612a82b594afbd20b6349daf16d2803dc519a199be08dc499d264e5106f162e8668b0d689d11bc9b8e5a8d4256fc7ace7a9a176975c8459d508bb5317
7
+ data.tar.gz: b55942ec2be01e35b92c557472b772ca08504ad11460ff204c49c26491567a1b29b8acf50bc1c52cd2cadd30775024a01db88b90325480913c59560aacad5a14
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
19
  .idea/
20
+ log/
@@ -6,9 +6,11 @@ rvm:
6
6
  - 2.1.1
7
7
  - 2.1.2
8
8
  - 2.1.3
9
+ - 2.2.0
9
10
  - jruby-19mode
10
11
  - rbx-2
11
12
  gemfile:
12
13
  - gemfiles/rails_3.2.gemfile
13
14
  - gemfiles/rails_4.0.gemfile
14
15
  - gemfiles/rails_4.1.gemfile
16
+ - gemfiles/rails_4.2.gemfile
data/Appraisals CHANGED
@@ -8,4 +8,8 @@ end
8
8
 
9
9
  appraise "rails-4.1" do
10
10
  gem "rails", "~> 4.1.1"
11
- end
11
+ end
12
+
13
+ appraise "rails-4.2" do
14
+ gem "rails", "~> 4.2.0"
15
+ end
@@ -1,3 +1,9 @@
1
+ ## 0.8.0
2
+ - Support for logging to stderr. Fixes [#24](https://github.com/dwbutler/logstash-logger/pull/25).
3
+ Thanks [Jan Schulte](https://github.com/schultyy)!
4
+ - Support multiple log outputs. Fixes [#28](https://github.com/dwbutler/logstash-logger/pull/28).
5
+ Thanks [Kurt Preston](https://github.com/KurtPreston)!
6
+
1
7
  ## 0.7.0
2
8
  - Support for logging to a generic IO object.
3
9
  - Support for overriding IO in stdout logger. Fixes [#20](https://github.com/dwbutler/logstash-logger/pull/20).
data/README.md CHANGED
@@ -8,7 +8,7 @@ writing to a file or syslog since logstash can receive the structured data direc
8
8
  ## Features
9
9
 
10
10
  * Can write directly to logstash over a UDP or TCP/SSL connection.
11
- * Can write to a file, Redis, a unix socket, or stdout.
11
+ * Can write to a file, Redis, a unix socket, stdout or stderr.
12
12
  * Always writes in logstash JSON format.
13
13
  * Logger can take a string message, a hash, a `LogStash::Event`, an object, or a JSON string as input.
14
14
  * Events are automatically populated with message, timestamp, host, and severity.
@@ -45,8 +45,12 @@ file_logger = LogStashLogger.new(type: :file, path: 'log/development.log', sync:
45
45
  unix_logger = LogStashLogger.new(type: :unix, path: '/tmp/sock')
46
46
  redis_logger = LogStashLogger.new(type: :redis)
47
47
  stdout_logger = LogStashLogger.new(type: :stdout)
48
+ stderr_logger = LogStashLogger.new(type: :stderr)
48
49
  io_logger = LogStashLogger.new(type: :io, io: io)
49
50
 
51
+ # Multiple Outputs
52
+ multi_logger = LogStashLogger.new([{type: :file, path: 'log/development.log'}, {type: :udp, host: 'localhost', port: 5228}])
53
+
50
54
  # The following messages are written to UDP port 5228:
51
55
 
52
56
  logger.info 'test'
@@ -78,6 +82,7 @@ unix:///tmp/socket
78
82
  file:///path/to/file
79
83
  redis://localhost:6379
80
84
  stdout:/
85
+ stderr:/
81
86
  ```
82
87
 
83
88
  Pass the URI into your logstash logger like so:
@@ -248,6 +253,22 @@ config.logstash.type = :io
248
253
  config.logstash.io = io
249
254
  ```
250
255
 
256
+ #### Multiple Outputs
257
+
258
+ ```ruby
259
+ config.logstash = [
260
+ {
261
+ type: :file,
262
+ path: 'log/production.log'
263
+ },
264
+ {
265
+ type: :udp,
266
+ port: 5228,
267
+ host: 'localhost'
268
+ }
269
+ ]
270
+ ```
271
+
251
272
  ## Ruby Compatibility
252
273
 
253
274
  Verified to work with:
@@ -299,6 +320,15 @@ logger = LogStashLogger.new('localhost', 5228)
299
320
  logger = LogStashLogger.new('localhost', 5228, :tcp)
300
321
  ```
301
322
 
323
+ ## Contributors
324
+ * [David Butler](https://github.com/dwbutler)
325
+ * [pctj101](https://github.com/pctj101)
326
+ * [Gary Rennie](https://github.com/Gazler)
327
+ * [Nick Ethier](https://github.com/nickethier)
328
+ * [Arron Mabrey](https://github.com/arronmabrey)
329
+ * [Jan Schulte](https://github.com/schultyy)
330
+ * [Kurt Preston](https://github.com/KurtPreston)
331
+
302
332
  ## Contributing
303
333
 
304
334
  1. Fork it
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "~> 4.2.0"
6
+
7
+ gemspec :path => "../"
@@ -14,10 +14,25 @@ module LogStashLogger
14
14
  autoload :File, 'logstash-logger/device/file'
15
15
  autoload :IO, 'logstash-logger/device/io'
16
16
  autoload :Stdout, 'logstash-logger/device/stdout'
17
+ autoload :Stderr, 'logstash-logger/device/stderr'
18
+ autoload :MultiDelegator, 'logstash-logger/device/multi_delegator'
17
19
 
18
20
  def self.new(opts)
19
21
  opts = opts.dup
20
22
 
23
+ if opts.is_a?(Array)
24
+ # Multiple device configs supplied... create a MultiDelegator
25
+ devices = opts.map{|opt| build_device(opt)}
26
+ Device::MultiDelegator.new(*devices)
27
+ elsif Hash
28
+ # Create a single device
29
+ build_device(opts)
30
+ else
31
+ raise ArgumentError, "Invalid device options: must be a Hash or an Array of Hashes"
32
+ end
33
+ end
34
+
35
+ def self.build_device(opts)
21
36
  if parsed_uri_opts = parse_uri_config(opts)
22
37
  opts = parsed_uri_opts
23
38
  end
@@ -43,6 +58,7 @@ module LogStashLogger
43
58
  when :redis then Redis
44
59
  when :io then IO
45
60
  when :stdout then Stdout
61
+ when :stderr then Stderr
46
62
  else fail ArgumentError, 'Invalid type'
47
63
  end
48
64
  end
@@ -0,0 +1,28 @@
1
+ # Container to allow writes to multiple devices
2
+
3
+ # Code originally from:
4
+ # http://stackoverflow.com/a/6410202
5
+
6
+ module LogStashLogger
7
+ module Device
8
+ class MultiDelegator < Base
9
+ attr_reader :devices
10
+
11
+ def initialize(*devices)
12
+ @io = self
13
+ @devices = devices
14
+ self.class.delegate(:write, :close, :flush)
15
+ end
16
+
17
+ private
18
+
19
+ def self.delegate(*methods)
20
+ methods.each do |m|
21
+ define_method(m) do |*args|
22
+ @devices.each { |device| device.send(m, *args) }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ module LogStashLogger
2
+ module Device
3
+ class Stderr < IO
4
+ def initialize(opts={})
5
+ super({io: $stderr}.merge(opts))
6
+ end
7
+
8
+ def close
9
+ # no-op
10
+ end
11
+ end
12
+ end
13
+ end
@@ -29,15 +29,22 @@ module LogStashLogger
29
29
  protected
30
30
 
31
31
  def self.extract_opts(*args)
32
+ args.flatten!
33
+
32
34
  if args.length > 1
33
- puts "[LogStashLogger] (host, port, type) constructor is deprecated. Please use an options hash instead."
34
- host, port, type = *args
35
- {host: host, port: port, type: type}
35
+ if args.all?{|arg| arg.is_a?(Hash)}
36
+ # Array of Hashes
37
+ args
38
+ else
39
+ # Deprecated host/port/type syntax
40
+ puts "[LogStashLogger] (host, port, type) constructor is deprecated. Please use an options hash instead."
41
+ host, port, type = *args
42
+ {host: host, port: port, type: type}
43
+ end
36
44
  elsif Hash === args[0]
37
45
  args[0]
38
46
  else
39
47
  fail ArgumentError, "Invalid LogStashLogger options"
40
48
  end
41
49
  end
42
-
43
50
  end
@@ -6,6 +6,25 @@ module LogStashLogger
6
6
 
7
7
  logger_options = app.config.logstash
8
8
 
9
+ sanitized_logger_options = if logger_options.is_a?(Array)
10
+ logger_options.map do |opts|
11
+ sanitize_logger_options(app, opts)
12
+ end
13
+ else
14
+ sanitize_logger_options(app, logger_options)
15
+ end
16
+
17
+ logger = LogStashLogger.new(sanitized_logger_options)
18
+
19
+ logger.level = ::Logger.const_get(app.config.log_level.to_s.upcase)
20
+
21
+ app.config.logger = logger
22
+ end
23
+
24
+ def self.sanitize_logger_options(app, logger_options)
25
+ # Convert logger options to OrderedOptions if regular Hash
26
+ logger_options = ActiveSupport::OrderedOptions.new.merge(logger_options)
27
+
9
28
  if parsed_uri_options = LogStashLogger::Device.parse_uri_config(logger_options)
10
29
  logger_options.delete(:uri)
11
30
  logger_options.merge!(parsed_uri_options)
@@ -19,11 +38,7 @@ module LogStashLogger
19
38
  logger_options.sync = app.config.autoflush_log
20
39
  end
21
40
 
22
- logger = LogStashLogger.new(logger_options)
23
-
24
- logger.level = ::Logger.const_get(app.config.log_level.to_s.upcase)
25
-
26
- app.config.logger = logger
41
+ logger_options
27
42
  end
28
43
 
29
44
  class Railtie < ::Rails::Railtie
@@ -1,3 +1,3 @@
1
1
  module LogStashLogger
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -0,0 +1,21 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Device::MultiDelegator do
4
+ include_context 'device'
5
+
6
+ # Create a MultiDelegator writing to both STDOUT and a StringIO
7
+ let(:subject) { multi_delegator_device }
8
+
9
+ let(:stdout) { $stdout }
10
+ let(:io) { StringIO.new }
11
+
12
+ it "writes to $stdout" do
13
+ # MultiDelegator writes to stdout
14
+ expect(stdout).to receive(:write).once
15
+
16
+ # MultiDelegator writes to IO
17
+ expect(io).to receive(:write).once
18
+
19
+ subject.write("test")
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Device::Stderr do
4
+ let(:stderr) { $stderr }
5
+
6
+ it 'writes to stderr' do
7
+ expect(subject.to_io).to eq stderr
8
+ expect(stderr).to receive(:write).once
9
+ subject.write("test")
10
+ end
11
+
12
+ it 'ignores #close' do
13
+ expect(stderr).not_to receive(:close)
14
+ subject.close
15
+ end
16
+ end
@@ -76,6 +76,11 @@ describe LogStashLogger::Device do
76
76
  let(:uri_config) { stdout_uri_config }
77
77
  it { is_expected.to be_a LogStashLogger::Device::Stdout }
78
78
  end
79
+
80
+ context 'when URI config is stderr' do
81
+ let(:uri_config) { stderr_uri_config }
82
+ it { is_expected.to be_a LogStashLogger::Device::Stderr }
83
+ end
79
84
  end
80
85
 
81
86
  end
@@ -11,10 +11,10 @@ describe LogStashLogger do
11
11
  UDPSocket.new.tap {|socket| socket.bind(host, port)}
12
12
  end
13
13
  end
14
-
14
+
15
15
  # The TCP socket written to by the TCP logstash listener server
16
16
  let(:tcp_client) { listener.accept }
17
-
17
+
18
18
  # The logstash event to log
19
19
  let(:logstash_event) do
20
20
  LogStash::Event.new.tap do |event|
@@ -22,7 +22,7 @@ describe LogStashLogger do
22
22
  event['severity'] = 'INFO'
23
23
  end
24
24
  end
25
-
25
+
26
26
  # The raw input received by the logstash listener
27
27
  let :listener_input do
28
28
  case connection_type
@@ -30,23 +30,23 @@ describe LogStashLogger do
30
30
  when :udp then listener.recvfrom(8192)[0]
31
31
  end
32
32
  end
33
-
33
+
34
34
  # The logstash event received by the listener
35
35
  let(:listener_event) { LogStash::Event.new(JSON.parse listener_input) }
36
-
36
+
37
37
  #before(:each) do
38
38
  # Sync socket writes so we can receive them in the listener immediately
39
39
  #@socket = logdev.instance_variable_get(:@dev).send(:connect)
40
40
  #@socket.sync = true
41
41
  #end
42
-
42
+
43
43
  after(:each) do
44
44
  listener.close
45
45
  end
46
-
46
+
47
47
  # The socket that the logger is writing to
48
48
  #let(:socket) { @socket }
49
-
49
+
50
50
  it 'uses a LogStashLogger::Device as the log device' do
51
51
  expect(logdev).to be_a Logger::LogDevice
52
52
  expect(logdev.instance_variable_get(:@dev)).to be_a LogStashLogger::Device::Base
@@ -63,11 +63,11 @@ describe LogStashLogger do
63
63
  end
64
64
 
65
65
  logger.info(message)
66
-
66
+
67
67
  expect(listener_event['message']).to eq(message)
68
68
  expect(listener_event['host']).to eq(hostname)
69
69
  end
70
-
70
+
71
71
  it 'takes a logstash-formatted json string as input and writes out a logstash event' do
72
72
  expect(logdev).to receive(:write).and_call_original do |event|
73
73
  expect(event).to be_a LogStash::Event
@@ -76,11 +76,11 @@ describe LogStashLogger do
76
76
  end
77
77
 
78
78
  logger.info(logstash_event.to_json)
79
-
79
+
80
80
  expect(listener_event['message']).to eq(logstash_event['message'])
81
81
  expect(listener_event['host']).to eq(hostname)
82
82
  end
83
-
83
+
84
84
  it 'takes a LogStash::Event as input and writes it out intact' do
85
85
  expect(logdev).to receive(:write).and_call_original do |event|
86
86
  expect(event).to be_a LogStash::Event
@@ -89,21 +89,21 @@ describe LogStashLogger do
89
89
  expect(event.timestamp).to eql(logstash_event.timestamp)
90
90
  expect(event.host).to eql(hostname)
91
91
  end
92
-
92
+
93
93
  logger.warn(logstash_event)
94
-
94
+
95
95
  expect(listener_event['message']).to eq(logstash_event['message'])
96
96
  expect(listener_event['severity']).to eq(logstash_event['severity'])
97
97
  expect(listener_event['host']).to eq(hostname)
98
98
  end
99
-
99
+
100
100
  it 'takes a data hash as input and writes out a logstash event' do
101
101
  data = {
102
102
  'message' => 'test',
103
103
  'severity' => 'INFO',
104
104
  'foo' => 'bar'
105
105
  }
106
-
106
+
107
107
  expect(logdev).to receive(:write).and_call_original do |event|
108
108
  expect(event).to be_a LogStash::Event
109
109
  expect(event['message']).to eql('test')
@@ -113,7 +113,7 @@ describe LogStashLogger do
113
113
  end
114
114
 
115
115
  logger.info(data.dup)
116
-
116
+
117
117
  expect(listener_event['message']).to eq(data["message"])
118
118
  expect(listener_event['severity']).to eq(data['severity'])
119
119
  expect(listener_event['foo']).to eq(data['foo'])
@@ -135,5 +135,5 @@ describe LogStashLogger do
135
135
 
136
136
  expect(listener_event['message']).to eq(message.inspect)
137
137
  end
138
-
138
+
139
139
  end
@@ -22,7 +22,7 @@ describe LogStashLogger do
22
22
  subject { app.config.logger }
23
23
 
24
24
  before(:each) do
25
- app.config.logstash.clear
25
+ app.config.logstash = ActiveSupport::OrderedOptions.new
26
26
  app.config.logger = nil
27
27
  end
28
28
 
@@ -52,6 +52,29 @@ describe LogStashLogger do
52
52
  end
53
53
  end
54
54
 
55
+ context "when configured with multiple devices" do
56
+ before(:each) do
57
+ app.config.logstash = [
58
+ {
59
+ type: :udp,
60
+ uri: udp_uri
61
+ },
62
+ {
63
+ type: :file
64
+ }
65
+ ]
66
+ LogStashLogger.setup(app)
67
+ end
68
+
69
+ it "uses a multi-delegator" do
70
+ expect(subject.device).to be_a LogStashLogger::Device::MultiDelegator
71
+ expect(subject.device.devices.map(&:class)).to eq([
72
+ LogStashLogger::Device::UDP,
73
+ LogStashLogger::Device::File
74
+ ])
75
+ end
76
+ end
77
+
55
78
  context "when logstash is not configured" do
56
79
  before(:each) do
57
80
  LogStashLogger.setup(app)
@@ -46,6 +46,7 @@ RSpec.shared_context 'device' do
46
46
  let(:io_device) { LogStashLogger::Device.new(type: :io, io: io)}
47
47
 
48
48
  let(:redis_device) { LogStashLogger::Device.new(type: :redis, sync: true) }
49
+ let(:multi_delegator_device) { LogStashLogger::Device.new([{type: :stdout}, {type: :io, io: io}]) }
49
50
 
50
51
  let(:udp_uri) { "udp://localhost:5228" }
51
52
  let(:tcp_uri) { "tcp://localhost:5229" }
@@ -53,6 +54,7 @@ RSpec.shared_context 'device' do
53
54
  let(:file_uri) { "file://#{file.path}" }
54
55
  let(:redis_uri) { "redis://localhost:6379" }
55
56
  let(:stdout_uri) { "stdout://localhost" }
57
+ let(:stderr_uri) { "stderr://localhost" }
56
58
 
57
59
  let(:invalid_uri_config) { {uri: "non parsable uri"} }
58
60
  let(:udp_uri_config) { {uri: udp_uri} }
@@ -61,4 +63,5 @@ RSpec.shared_context 'device' do
61
63
  let(:file_uri_config) { {uri: file_uri} }
62
64
  let(:redis_uri_config) { {uri: redis_uri} }
63
65
  let(:stdout_uri_config) { {uri: stdout_uri} }
66
+ let(:stderr_uri_config) { {uri: stderr_uri} }
64
67
  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.7.0
4
+ version: 0.8.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: 2014-10-05 00:00:00.000000000 Z
11
+ date: 2015-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-event
@@ -155,14 +155,17 @@ files:
155
155
  - gemfiles/rails_3.2.gemfile
156
156
  - gemfiles/rails_4.0.gemfile
157
157
  - gemfiles/rails_4.1.gemfile
158
+ - gemfiles/rails_4.2.gemfile
158
159
  - lib/logstash-logger.rb
159
160
  - lib/logstash-logger/device.rb
160
161
  - lib/logstash-logger/device/base.rb
161
162
  - lib/logstash-logger/device/connectable.rb
162
163
  - lib/logstash-logger/device/file.rb
163
164
  - lib/logstash-logger/device/io.rb
165
+ - lib/logstash-logger/device/multi_delegator.rb
164
166
  - lib/logstash-logger/device/redis.rb
165
167
  - lib/logstash-logger/device/socket.rb
168
+ - lib/logstash-logger/device/stderr.rb
166
169
  - lib/logstash-logger/device/stdout.rb
167
170
  - lib/logstash-logger/device/tcp.rb
168
171
  - lib/logstash-logger/device/udp.rb
@@ -183,8 +186,10 @@ files:
183
186
  - samples/unix.conf
184
187
  - spec/device/file_spec.rb
185
188
  - spec/device/io_spec.rb
189
+ - spec/device/multi_delegator_spec.rb
186
190
  - spec/device/redis_spec.rb
187
191
  - spec/device/socket_spec.rb
192
+ - spec/device/stderr_spec.rb
188
193
  - spec/device/stdout_spec.rb
189
194
  - spec/device/tcp_spec.rb
190
195
  - spec/device/udp_spec.rb
@@ -214,15 +219,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
214
219
  version: '0'
215
220
  requirements: []
216
221
  rubyforge_project:
217
- rubygems_version: 2.2.2
222
+ rubygems_version: 2.4.5
218
223
  signing_key:
219
224
  specification_version: 4
220
225
  summary: LogStash Logger for ruby
221
226
  test_files:
222
227
  - spec/device/file_spec.rb
223
228
  - spec/device/io_spec.rb
229
+ - spec/device/multi_delegator_spec.rb
224
230
  - spec/device/redis_spec.rb
225
231
  - spec/device/socket_spec.rb
232
+ - spec/device/stderr_spec.rb
226
233
  - spec/device/stdout_spec.rb
227
234
  - spec/device/tcp_spec.rb
228
235
  - spec/device/udp_spec.rb