logstash-logger 0.7.0 → 0.8.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: 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