md-logstasher 1.0.5 → 1.4.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
- SHA1:
3
- metadata.gz: 4563d96cf88d8a5e5fa8c1a263ed5e79c2fa2acc
4
- data.tar.gz: edbcb27c41a3068d29fb1d896131a81035391c3d
2
+ SHA256:
3
+ metadata.gz: 5f6a2e729c225c8fb2cf06174d9fc5282ae0b2ee660fd89d675a30e7fcd19eb3
4
+ data.tar.gz: 9a8dea2258d1ed2c0fb1c01227bf7ea6b78421ca342ba122a32cc8f1351b7440
5
5
  SHA512:
6
- metadata.gz: f2bcdf71a918cbed00947a631abbd3a444dee9918afd8eb3d1947e4f092fc8569327ee088bb5aa890d5900fc959879dc3e9da3fcac96d675d36a6ea2db66e08f
7
- data.tar.gz: 77f0394fb5e701c380176ae702412d07c8b24faa31d6f67ec60969ad3e5f42499c763bcd4e6d78efbb19ba1750750619d074e9e4e011e65d306b1d50a231c3cc
6
+ metadata.gz: d23d146376ea21233a2b1189366586cbecc46f4a5694ffb1b7cae480881098828f7e9e79f171cf7f1c52372b793f53aff40d86dd444a4aee4e8a12e9334e2e7a
7
+ data.tar.gz: f6a8c91e937935dac803868c098e8b6826cb0b27f72fe5718bf8fcebad2685acdeb899e8055d6ee6cc2a4420bcf3465a7e3557e99875b8b2fbf8fbccd5c90618
@@ -59,7 +59,7 @@ module LogStasher
59
59
 
60
60
  def validate_options
61
61
  unless ['list', 'channel'].include?(options['data_type'])
62
- fail 'Expected data_type to be either "list" or "channel"'
62
+ fail RuntimeError, 'Expected data_type to be either "list" or "channel"'
63
63
  end
64
64
  end
65
65
  end
@@ -2,34 +2,27 @@
2
2
 
3
3
  require 'logstasher/device'
4
4
  require 'syslog'
5
- require 'thread'
6
5
 
7
6
  module LogStasher
8
7
  module Device
9
8
  class Syslog
10
9
  include ::LogStasher::Device
11
10
 
12
- SEMAPHORE = Mutex.new
13
-
14
11
  attr_reader :options
15
12
 
16
13
  def initialize(options = {})
17
14
  raw_options = default_options.merge(stringify_keys(options))
18
15
 
19
16
  @options = parse_options(raw_options)
20
- @closed = false
17
+ open_syslog
21
18
  end
22
19
 
23
20
  def close
24
- SEMAPHORE.synchronize do
25
- ::Syslog.close if ::Syslog.opened?
26
- end
27
-
28
- @closed = true
21
+ ::Syslog.close rescue nil
29
22
  end
30
23
 
31
24
  def closed?
32
- @closed
25
+ !::Syslog.opened?
33
26
  end
34
27
 
35
28
  def facility
@@ -49,11 +42,10 @@ module LogStasher
49
42
  end
50
43
 
51
44
  def write(log)
52
- fail ::RuntimeError, 'Cannot write. The device has been closed.' if closed?
45
+ fail ::RuntimeError, 'Syslog has been closed.' if closed?
46
+ fail ::RuntimeError, 'Syslog re-configured unexpectedly.' if syslog_config_changed?
53
47
 
54
- with_syslog_open do
55
- ::Syslog.log(priority, '%s', log)
56
- end
48
+ ::Syslog.log(priority, '%s', log)
57
49
  end
58
50
 
59
51
  private
@@ -63,10 +55,18 @@ module LogStasher
63
55
  'identity' => 'logstasher',
64
56
  'facility' => ::Syslog::LOG_LOCAL0,
65
57
  'priority' => ::Syslog::LOG_INFO,
66
- 'flags' => ::Syslog::LOG_PID | ::Syslog::LOG_CONS
58
+ 'flags' => ::Syslog::LOG_PID | ::Syslog::LOG_CONS,
67
59
  }
68
60
  end
69
61
 
62
+ def open_syslog
63
+ if ::Syslog.opened?
64
+ ::Syslog.reopen(identity, flags, facility)
65
+ else
66
+ ::Syslog.open(identity, flags, facility)
67
+ end
68
+ end
69
+
70
70
  def parse_option(value)
71
71
  case value
72
72
  when ::String
@@ -85,20 +85,8 @@ module LogStasher
85
85
  options
86
86
  end
87
87
 
88
- def syslog_configured?
89
- ::Syslog.ident == identity && ::Syslog.options == flags && ::Syslog.facility == facility
90
- end
91
-
92
- def with_syslog_open
93
- SEMAPHORE.synchronize do
94
- if ::Syslog.opened?
95
- ::Syslog.reopen(identity, flags, facility) unless syslog_configured?
96
- else
97
- ::Syslog.open(identity, flags, facility)
98
- end
99
-
100
- yield
101
- end
88
+ def syslog_config_changed?
89
+ ::Syslog.ident != identity || ::Syslog.options != flags || ::Syslog.facility != facility
102
90
  end
103
91
  end
104
92
  end
@@ -0,0 +1,40 @@
1
+ # simple UDP logger
2
+
3
+ require 'logstasher/device'
4
+ require 'socket'
5
+
6
+
7
+ module LogStasher
8
+ module Device
9
+ class UDP
10
+ include ::LogStasher::Device
11
+
12
+ attr_reader :options, :socket
13
+
14
+ def initialize(options = {})
15
+ @options = default_options.merge(stringify_keys(options))
16
+ @socket = UDPSocket.new
17
+ end
18
+
19
+ def close
20
+ @socket.close
21
+ end
22
+
23
+ def write(log)
24
+ @socket.send(log, 0, options['hostname'], options['port'])
25
+ end
26
+
27
+ private
28
+
29
+ def default_options
30
+ {
31
+ 'hostname' => '127.0.0.1',
32
+ 'port' => 31459,
33
+ }
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+
40
+
@@ -11,6 +11,9 @@ module LogStasher
11
11
  when "syslog", :syslog then
12
12
  require 'logstasher/device/syslog'
13
13
  ::LogStasher::Device::Syslog.new(config)
14
+ when "udp", :udp then
15
+ require 'logstasher/device/udp'
16
+ ::LogStasher::Device::UDP.new(config)
14
17
  else
15
18
  fail ArgumentError, "Unknown type: #{type}"
16
19
  end
@@ -21,7 +21,6 @@ module LogStasher
21
21
  payload = event.payload
22
22
  tags = extract_tags(payload)
23
23
  fields = extract_request(payload)
24
-
25
24
  fields.merge! extract_status(payload)
26
25
  fields.merge! runtimes(event)
27
26
  fields.merge! location
@@ -52,15 +51,19 @@ module LogStasher
52
51
  end
53
52
 
54
53
  def extract_request(payload)
55
- {
54
+ result = {
56
55
  :action => payload[:action],
57
56
  :controller => payload[:controller],
58
57
  :format => extract_format(payload),
59
58
  :ip => request.remote_ip,
59
+ :request_id => request.env["action_dispatch.request_id"],
60
60
  :method => payload[:method],
61
61
  :path => extract_path(payload),
62
62
  :route => "#{payload[:controller]}##{payload[:action]}"
63
63
  }
64
+ metadata = ::LogStasher.metadata
65
+ result.merge!(:metadata => metadata) unless metadata&.empty?
66
+ result
64
67
  end
65
68
 
66
69
  # Monkey patching to enable exception logging
@@ -86,7 +89,6 @@ module LogStasher
86
89
  def extract_parameters(payload)
87
90
  if LogStasher.include_parameters?
88
91
  external_params = payload[:params].except(*INTERNAL_PARAMS)
89
-
90
92
  if LogStasher.serialize_parameters?
91
93
  { :params => JSON.generate(external_params) }
92
94
  else
@@ -8,6 +8,7 @@ module LogStasher
8
8
  config.logstasher.logger = nil
9
9
  config.logstasher.log_level = ::Logger::INFO
10
10
 
11
+ config.logstasher.metadata = {}
11
12
  config.before_initialize do
12
13
  options = config.logstasher
13
14
 
@@ -17,6 +18,7 @@ module LogStasher
17
18
  ::LogStasher.silence_standard_logging = options.silence_standard_logging
18
19
  ::LogStasher.logger = options.logger || default_logger
19
20
  ::LogStasher.logger.level = options.log_level
21
+ ::LogStasher.metadata = options.metadata
20
22
  end
21
23
 
22
24
  initializer 'logstasher.load' do
@@ -1,3 +1,3 @@
1
1
  module LogStasher
2
- VERSION = "1.0.5"
2
+ VERSION = "1.4.0"
3
3
  end
data/lib/logstasher.rb CHANGED
@@ -8,6 +8,7 @@ module LogStasher
8
8
  attr_writer :include_parameters
9
9
  attr_writer :serialize_parameters
10
10
  attr_writer :silence_standard_logging
11
+ attr_accessor :metadata
11
12
 
12
13
  def append_fields(&block)
13
14
  @append_fields_callback = block
@@ -40,7 +40,7 @@ describe LogStasher::Device::Redis do
40
40
  it 'does not allow unsupported data types' do
41
41
  expect {
42
42
  device = LogStasher::Device::Redis.new(data_type: 'blargh')
43
- }.to raise_error()
43
+ }.to raise_error(::RuntimeError)
44
44
  end
45
45
 
46
46
  it 'quits the redis connection on #close' do
@@ -14,9 +14,9 @@ describe LogStasher::Device::Syslog do
14
14
  before { allow(::Syslog).to receive(:log) }
15
15
 
16
16
  around do |example|
17
- ::Syslog.close if ::Syslog.opened?
17
+ ::Syslog.close rescue nil
18
18
  example.run
19
- ::Syslog.close if ::Syslog.opened?
19
+ ::Syslog.close rescue nil
20
20
  end
21
21
 
22
22
  it 'has default options' do
@@ -64,25 +64,37 @@ describe LogStasher::Device::Syslog do
64
64
  expect(device.flags).to eq(::Syslog::LOG_NOWAIT | ::Syslog::LOG_ODELAY)
65
65
  end
66
66
 
67
- describe '#write' do
68
- subject { LogStasher::Device::Syslog.new }
67
+ it 'opens syslog when it is closed' do
68
+ expect(::Syslog).to receive(:open).with(
69
+ default_options['identity'],
70
+ default_options['flags'],
71
+ default_options['facility'],
72
+ )
69
73
 
70
- it 'opens syslog when syslog is closed' do
71
- expect(::Syslog).to receive(:open).with(subject.identity, subject.flags, subject.facility)
72
- subject.write('a log')
73
- end
74
+ LogStasher::Device::Syslog.new
75
+ end
74
76
 
75
- it 'does not re-open syslog when its config is in sync' do
76
- ::Syslog.open(subject.identity, subject.flags, subject.facility)
77
- expect(::Syslog).not_to receive(:open)
78
- expect(::Syslog).not_to receive(:reopen)
79
- subject.write('a log')
80
- end
77
+ it 're-opens syslog when it is already opened' do
78
+ ::Syslog.open('temp', ::Syslog::LOG_NDELAY, ::Syslog::LOG_AUTH)
81
79
 
82
- it 're-opens syslog when its config is out of sync' do
83
- ::Syslog.open('temp', ::Syslog::LOG_NDELAY, ::Syslog::LOG_AUTH)
84
- expect(::Syslog).to receive(:reopen).with(subject.identity, subject.flags, subject.facility)
85
- subject.write('a log')
80
+ expect(::Syslog).to receive(:reopen).with(
81
+ default_options['identity'],
82
+ default_options['flags'],
83
+ default_options['facility'],
84
+ )
85
+
86
+ LogStasher::Device::Syslog.new
87
+ end
88
+
89
+ describe '#write' do
90
+ subject { LogStasher::Device::Syslog.new }
91
+
92
+ it 'fails when the syslog config is out of sync' do
93
+ subject
94
+ ::Syslog.reopen('temp', ::Syslog::LOG_NDELAY, ::Syslog::LOG_AUTH)
95
+ expect {
96
+ subject.write('a log')
97
+ }.to raise_error(::RuntimeError, 'Syslog re-configured unexpectedly.')
86
98
  end
87
99
 
88
100
  it 'writes the log to syslog' do
@@ -94,7 +106,7 @@ describe LogStasher::Device::Syslog do
94
106
  subject.close
95
107
  expect {
96
108
  subject.write('a log')
97
- }.to raise_error(::RuntimeError, 'Cannot write. The device has been closed.')
109
+ }.to raise_error(::RuntimeError, 'Syslog has been closed.')
98
110
  end
99
111
  end
100
112
 
@@ -106,15 +118,9 @@ describe LogStasher::Device::Syslog do
106
118
  expect(subject).to be_closed
107
119
  end
108
120
 
109
- it 'closes syslog when syslog is open' do
110
- ::Syslog.open(subject.identity, subject.flags, subject.facility)
121
+ it 'closes syslog' do
111
122
  expect(::Syslog).to receive(:close)
112
123
  subject.close
113
124
  end
114
-
115
- it 'does not close syslog if it is already closed' do
116
- expect(::Syslog).not_to receive(:close)
117
- subject.close
118
- end
119
125
  end
120
126
  end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ require 'logstasher/device/udp'
4
+
5
+ describe LogStasher::Device::UDP do
6
+
7
+ let(:default_options) {{
8
+ 'hostname' => '127.0.0.1',
9
+ 'port' => 31459
10
+ }}
11
+
12
+ it 'has default options' do
13
+ device = LogStasher::Device::UDP.new
14
+ expect(device.options).to eq(default_options)
15
+ end
16
+
17
+ it 'closes the udp socket on #close' do
18
+ device = LogStasher::Device::UDP.new
19
+ expect(device.socket).to receive(:close)
20
+ device.close
21
+ end
22
+
23
+ it 'works as a logger device' do
24
+ device = LogStasher::Device::UDP.new
25
+ expect(device).to receive(:write).with('foo')
26
+ logger = Logger.new(device)
27
+ logger << 'foo'
28
+ end
29
+
30
+ describe '#write' do
31
+ subject { LogStasher::Device::UDP.new }
32
+ it 'writes the log to the the socket' do
33
+ expect(subject.socket).to receive(:send).with('a log', 0, default_options['hostname'], default_options['port'])
34
+ subject.write('a log')
35
+ end
36
+ end
37
+ end
@@ -3,6 +3,7 @@ require "spec_helper"
3
3
  require "logstasher/device"
4
4
  require "logstasher/device/redis"
5
5
  require "logstasher/device/syslog"
6
+ require "logstasher/device/udp"
6
7
 
7
8
  describe LogStasher::Device do
8
9
  describe ".factory" do
@@ -47,7 +48,17 @@ describe LogStasher::Device do
47
48
  device = ::LogStasher::Device.factory(:type => "syslog")
48
49
  expect(device).to be_a_kind_of(::LogStasher::Device::Syslog)
49
50
  end
51
+
52
+ it "can create udp devices" do
53
+ expect(
54
+ ::LogStasher::Device
55
+ ).to receive(:require).with("logstasher/device/udp")
56
+
57
+ device = ::LogStasher::Device.factory(:type => "udp")
58
+ expect(device).to be_a_kind_of(::LogStasher::Device::UDP)
59
+ end
50
60
 
61
+
51
62
  it "fails to create unknown devices" do
52
63
  expect {
53
64
  ::LogStasher::Device.factory(:type => "unknown")
@@ -10,6 +10,12 @@ class MockController
10
10
  end
11
11
 
12
12
  class MockRequest
13
+ attr_accessor :env
14
+
15
+ def initialize
16
+ @env = { 'action_dispatch.request_id' => 1 }
17
+ end
18
+
13
19
  def remote_ip
14
20
  '127.0.0.1'
15
21
  end
@@ -19,6 +25,7 @@ describe LogStasher::LogSubscriber do
19
25
  subject { described_class.new }
20
26
 
21
27
  let(:logger) { ::Logger.new('/dev/null') }
28
+
22
29
  let(:mock_controller) { MockController.new }
23
30
  let(:mock_request) { MockRequest.new }
24
31
  let(:context) {{ :controller => mock_controller, :request => mock_request }}
@@ -46,10 +53,12 @@ describe LogStasher::LogSubscriber do
46
53
  :path => '/users/1',
47
54
  :status => 200
48
55
  }}
56
+ let(:data) { { "namespace" => "test", "appversion" => "v1" } }
49
57
 
50
58
  let(:event) { double(:payload => payload, :duration => duration) }
51
59
 
52
60
  it 'logs the event in logstash format' do
61
+ ::LogStasher.metadata = data
53
62
  expect(logger).to receive(:<<) do |json|
54
63
  expect(JSON.parse(json)).to eq({
55
64
  '@timestamp' => timestamp,
@@ -64,7 +73,9 @@ describe LogStasher::LogSubscriber do
64
73
  'path' => payload[:path],
65
74
  'route' => "#{payload[:controller]}##{payload[:action]}",
66
75
  'status' => payload[:status],
67
- 'runtime' => { 'total' => duration }
76
+ 'runtime' => { 'total' => duration },
77
+ 'request_id' => 1,
78
+ 'metadata' => data
68
79
  })
69
80
  end
70
81
 
@@ -19,12 +19,6 @@ describe ::LogStasher::Railtie do
19
19
  let(:config) { described_class.config.logstasher }
20
20
 
21
21
  describe 'logstasher.configure' do
22
- subject do
23
- described_class.instance.initializers.find do |initializer|
24
- initializer.name == 'logstasher.configure'
25
- end
26
- end
27
-
28
22
  it 'should configure LogStasher' do
29
23
  config.logger = ::Logger.new('/dev/null')
30
24
  config.log_level = "log_level"
@@ -40,7 +34,7 @@ describe ::LogStasher::Railtie do
40
34
  expect(::LogStasher).to receive(:logger=).with(config.logger).and_call_original
41
35
  expect(config.logger).to receive(:level=).with("log_level")
42
36
 
43
- subject.run
37
+ ActiveSupport.run_load_hooks(:before_initialize)
44
38
  end
45
39
  end
46
40
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: md-logstasher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devin Christensen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-12 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash-event
@@ -85,6 +85,7 @@ files:
85
85
  - lib/logstasher/device.rb
86
86
  - lib/logstasher/device/redis.rb
87
87
  - lib/logstasher/device/syslog.rb
88
+ - lib/logstasher/device/udp.rb
88
89
  - lib/logstasher/log_subscriber.rb
89
90
  - lib/logstasher/railtie.rb
90
91
  - lib/logstasher/silent_logger.rb
@@ -96,6 +97,7 @@ files:
96
97
  - logstasher.gemspec
97
98
  - spec/lib/logstasher/device/redis_spec.rb
98
99
  - spec/lib/logstasher/device/syslog_spec.rb
100
+ - spec/lib/logstasher/device/udp_spec.rb
99
101
  - spec/lib/logstasher/device_spec.rb
100
102
  - spec/lib/logstasher/log_subscriber_spec.rb
101
103
  - spec/lib/logstasher/railtie_spec.rb
@@ -105,7 +107,7 @@ homepage: https://github.com/moneydesktop/logstasher
105
107
  licenses:
106
108
  - MIT
107
109
  metadata: {}
108
- post_install_message:
110
+ post_install_message:
109
111
  rdoc_options: []
110
112
  require_paths:
111
113
  - lib
@@ -120,14 +122,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
122
  - !ruby/object:Gem::Version
121
123
  version: '0'
122
124
  requirements: []
123
- rubyforge_project:
124
- rubygems_version: 2.2.2
125
- signing_key:
125
+ rubygems_version: 3.2.28
126
+ signing_key:
126
127
  specification_version: 4
127
128
  summary: Awesome rails logs
128
129
  test_files:
129
130
  - spec/lib/logstasher/device/redis_spec.rb
130
131
  - spec/lib/logstasher/device/syslog_spec.rb
132
+ - spec/lib/logstasher/device/udp_spec.rb
131
133
  - spec/lib/logstasher/device_spec.rb
132
134
  - spec/lib/logstasher/log_subscriber_spec.rb
133
135
  - spec/lib/logstasher/railtie_spec.rb