logstash-logger-p 0.26.1

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.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +1156 -0
  5. data/.travis.yml +26 -0
  6. data/Appraisals +23 -0
  7. data/CHANGELOG.md +199 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +880 -0
  11. data/Rakefile +23 -0
  12. data/gemfiles/rails_3.2.gemfile +9 -0
  13. data/gemfiles/rails_4.0.gemfile +9 -0
  14. data/gemfiles/rails_4.1.gemfile +9 -0
  15. data/gemfiles/rails_4.2.gemfile +9 -0
  16. data/gemfiles/rails_5.0.gemfile +9 -0
  17. data/gemfiles/rails_5.1.gemfile +9 -0
  18. data/lib/logstash-logger/buffer.rb +336 -0
  19. data/lib/logstash-logger/configuration.rb +29 -0
  20. data/lib/logstash-logger/device/aws_stream.rb +94 -0
  21. data/lib/logstash-logger/device/balancer.rb +40 -0
  22. data/lib/logstash-logger/device/base.rb +73 -0
  23. data/lib/logstash-logger/device/connectable.rb +131 -0
  24. data/lib/logstash-logger/device/file.rb +23 -0
  25. data/lib/logstash-logger/device/firehose.rb +42 -0
  26. data/lib/logstash-logger/device/io.rb +11 -0
  27. data/lib/logstash-logger/device/kafka.rb +57 -0
  28. data/lib/logstash-logger/device/kinesis.rb +44 -0
  29. data/lib/logstash-logger/device/multi_delegator.rb +36 -0
  30. data/lib/logstash-logger/device/redis.rb +76 -0
  31. data/lib/logstash-logger/device/socket.rb +21 -0
  32. data/lib/logstash-logger/device/stderr.rb +13 -0
  33. data/lib/logstash-logger/device/stdout.rb +14 -0
  34. data/lib/logstash-logger/device/tcp.rb +86 -0
  35. data/lib/logstash-logger/device/udp.rb +12 -0
  36. data/lib/logstash-logger/device/unix.rb +18 -0
  37. data/lib/logstash-logger/device.rb +67 -0
  38. data/lib/logstash-logger/formatter/base.rb +73 -0
  39. data/lib/logstash-logger/formatter/cee.rb +11 -0
  40. data/lib/logstash-logger/formatter/cee_syslog.rb +22 -0
  41. data/lib/logstash-logger/formatter/json.rb +11 -0
  42. data/lib/logstash-logger/formatter/json_lines.rb +11 -0
  43. data/lib/logstash-logger/formatter/logstash_event.rb +6 -0
  44. data/lib/logstash-logger/formatter.rb +51 -0
  45. data/lib/logstash-logger/logger.rb +106 -0
  46. data/lib/logstash-logger/multi_logger.rb +153 -0
  47. data/lib/logstash-logger/railtie.rb +51 -0
  48. data/lib/logstash-logger/silenced_logging.rb +83 -0
  49. data/lib/logstash-logger/tagged_logging.rb +40 -0
  50. data/lib/logstash-logger/version.rb +3 -0
  51. data/lib/logstash-logger.rb +11 -0
  52. data/logstash-logger.gemspec +39 -0
  53. data/samples/example.crt +16 -0
  54. data/samples/example.key +15 -0
  55. data/samples/file.conf +11 -0
  56. data/samples/redis.conf +12 -0
  57. data/samples/ssl.conf +15 -0
  58. data/samples/syslog.conf +10 -0
  59. data/samples/tcp.conf +11 -0
  60. data/samples/udp.conf +11 -0
  61. data/samples/unix.conf +11 -0
  62. data/spec/configuration_spec.rb +27 -0
  63. data/spec/constructor_spec.rb +30 -0
  64. data/spec/device/balancer_spec.rb +31 -0
  65. data/spec/device/connectable_spec.rb +74 -0
  66. data/spec/device/file_spec.rb +15 -0
  67. data/spec/device/firehose_spec.rb +41 -0
  68. data/spec/device/io_spec.rb +13 -0
  69. data/spec/device/kafka_spec.rb +32 -0
  70. data/spec/device/kinesis_spec.rb +41 -0
  71. data/spec/device/multi_delegator_spec.rb +31 -0
  72. data/spec/device/redis_spec.rb +52 -0
  73. data/spec/device/socket_spec.rb +15 -0
  74. data/spec/device/stderr_spec.rb +16 -0
  75. data/spec/device/stdout_spec.rb +31 -0
  76. data/spec/device/tcp_spec.rb +120 -0
  77. data/spec/device/udp_spec.rb +9 -0
  78. data/spec/device/unix_spec.rb +23 -0
  79. data/spec/device_spec.rb +97 -0
  80. data/spec/formatter/base_spec.rb +125 -0
  81. data/spec/formatter/cee_spec.rb +15 -0
  82. data/spec/formatter/cee_syslog_spec.rb +43 -0
  83. data/spec/formatter/json_lines_spec.rb +14 -0
  84. data/spec/formatter/json_spec.rb +10 -0
  85. data/spec/formatter/logstash_event_spec.rb +10 -0
  86. data/spec/formatter_spec.rb +79 -0
  87. data/spec/logger_spec.rb +128 -0
  88. data/spec/multi_logger_spec.rb +59 -0
  89. data/spec/rails_spec.rb +91 -0
  90. data/spec/silenced_logging_spec.rb +31 -0
  91. data/spec/spec_helper.rb +111 -0
  92. data/spec/syslog_spec.rb +32 -0
  93. data/spec/tagged_logging_spec.rb +32 -0
  94. metadata +335 -0
@@ -0,0 +1,120 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Device::TCP do
4
+ include_context 'device'
5
+
6
+ let(:tcp_socket) { double('TCPSocket') }
7
+ let(:ssl_socket) { double('SSLSocket') }
8
+
9
+ before(:each) do
10
+ allow(TCPSocket).to receive(:new) { tcp_socket }
11
+ allow(tcp_socket).to receive(:sync=)
12
+
13
+ allow(OpenSSL::SSL::SSLSocket).to receive(:new) { ssl_socket }
14
+ allow(ssl_socket).to receive(:connect)
15
+ allow(ssl_socket).to receive(:post_connection_check)
16
+ allow(ssl_tcp_device).to receive(:warn)
17
+ end
18
+
19
+ context "when not using SSL" do
20
+ it "writes to a TCP socket" do
21
+ expect(tcp_socket).to receive(:write)
22
+ tcp_device.write('test')
23
+ end
24
+
25
+ it "returns false for #use_ssl?" do
26
+ expect(tcp_device.use_ssl?).to be_falsey
27
+ end
28
+
29
+ it "exposes the TCP socket via #io" do
30
+ expect(tcp_device.io).to eq tcp_socket
31
+ end
32
+ end
33
+
34
+ context "when using SSL" do
35
+ it "writes to an SSL TCP socket" do
36
+ expect(ssl_socket).to receive(:write)
37
+ ssl_tcp_device.write('test')
38
+ end
39
+
40
+ it "returns true for #use_ssl?" do
41
+ expect(ssl_tcp_device.use_ssl?).to be_truthy
42
+ end
43
+
44
+ it "exposes the SSL socket via #io" do
45
+ expect(ssl_tcp_device.io).to eq ssl_socket
46
+ end
47
+
48
+ context 'hostname validation' do
49
+ let(:ssl_context) { double('test_ssl_context', verify_mode: OpenSSL::SSL::VERIFY_PEER) }
50
+ let(:ssl_tcp_options) { { type: :tcp, port: port, sync: true, ssl_context: ssl_context } }
51
+
52
+ context 'is enabled by default' do
53
+ let(:ssl_tcp_device) { LogStashLogger::Device.new(ssl_tcp_options) }
54
+
55
+ it 'validates' do
56
+ expect(ssl_tcp_device.send(:verify_hostname?)).to be_truthy
57
+ expect(ssl_socket).to receive(:post_connection_check).with HOST
58
+ ssl_tcp_device.connect
59
+ end
60
+ end
61
+
62
+ context 'is disabled explicitly' do
63
+ let(:ssl_tcp_device) { LogStashLogger::Device.new(ssl_tcp_options.merge(verify_hostname: false)) }
64
+
65
+ it 'does not validate' do
66
+ expect(ssl_tcp_device.send(:verify_hostname?)).to be_falsey
67
+ expect(ssl_socket).not_to receive(:post_connection_check)
68
+ ssl_tcp_device.connect
69
+ end
70
+ end
71
+
72
+ context 'is implicitly enabled by providing a hostname' do
73
+ let(:hostname) { 'www.example.com' }
74
+ let(:ssl_tcp_device) { LogStashLogger::Device.new(ssl_tcp_options.merge(verify_hostname: hostname)) }
75
+
76
+ it 'validates with supplied hostname' do
77
+ expect(ssl_socket).to receive(:post_connection_check).with hostname
78
+ ssl_tcp_device.connect
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'with a provided SSL context' do
84
+ let(:ssl_context) { double('test_ssl_context', verify_mode: OpenSSL::SSL::VERIFY_PEER) }
85
+ let(:ssl_tcp_device) { LogStashLogger::Device.new(type: :tcp, port: port, sync: true, ssl_context: ssl_context) }
86
+
87
+ it 'creates the socket using that context' do
88
+ expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(tcp_socket, ssl_context)
89
+ ssl_tcp_device.connect
90
+ end
91
+
92
+ it 'implicitly sets @use_ssl to true' do
93
+ expect(ssl_tcp_device.use_ssl?).to be_truthy
94
+ end
95
+
96
+ context 'and :ssl_enable explicitly set to false' do
97
+ let(:ssl_tcp_device) { LogStashLogger::Device.new(type: :tcp, port: port, sync: true, ssl_enable: false, ssl_context: ssl_context) }
98
+
99
+ it 'explicitly sets @use_ssl to false' do
100
+ expect(ssl_tcp_device.use_ssl?).to be_falsey
101
+ end
102
+ end
103
+ end
104
+
105
+ context 'without a provided SSL context' do
106
+ it 'ssl_context returns nil' do
107
+ expect(ssl_tcp_device.ssl_context).to be_nil
108
+ end
109
+ end
110
+
111
+ context 'only providing a certificate file' do
112
+ let(:ssl_tcp_device) { LogStashLogger::Device.new(type: :tcp, port: port, ssl_enable: true, sync: true, ssl_certificate: '/path/to/cert.pem') }
113
+
114
+ it 'implicitly uses a context with the configured certificate' do
115
+ expect(ssl_tcp_device.ssl_context.cert).to eq('/path/to/cert.pem')
116
+ end
117
+ end
118
+ end
119
+
120
+ end
@@ -0,0 +1,9 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Device::UDP do
4
+ include_context 'device'
5
+
6
+ it "writes to a UDP socket" do
7
+ expect(udp_device.to_io).to be_a UDPSocket
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Device::Unix do
4
+ include_context 'device'
5
+
6
+ let(:unix_socket) { double("UNIXSocket") }
7
+
8
+ before(:each) do
9
+ allow(::UNIXSocket).to receive(:new) { unix_socket }
10
+ allow(unix_socket).to receive(:sync=)
11
+ end
12
+
13
+ it "writes to a local unix socket" do
14
+ expect(unix_socket).to receive(:write)
15
+ unix_device.write('foo')
16
+ end
17
+
18
+ context "when path is not specified" do
19
+ it "raises an exception" do
20
+ expect { described_class.new }.to raise_error(ArgumentError)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,97 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Device do
4
+ include_context 'device'
5
+
6
+ context "when port is specified" do
7
+ it "defaults type to UDP" do
8
+ expect(device_with_port).to be_a LogStashLogger::Device::UDP
9
+ end
10
+ end
11
+
12
+ context "when passing in configuration" do
13
+ let(:configuration) { {type: :udp, port: port} }
14
+
15
+ subject(:new_device) { described_class.new(configuration) }
16
+
17
+ it "does not mutate the passed configuration" do
18
+ expect{ new_device }.to_not change { configuration }
19
+ expect( new_device ).to be_a LogStashLogger::Device::UDP
20
+ end
21
+ end
22
+
23
+ context "when configuration type is a String" do
24
+ let(:configuration) { {type: "udp", port: port} }
25
+
26
+ subject(:new_device) { described_class.new(configuration) }
27
+
28
+ it "it correctly recognizes the device type" do
29
+ expect(new_device).to be_a LogStashLogger::Device::UDP
30
+ end
31
+ end
32
+
33
+ describe ".parse_uri_config" do
34
+ subject(:parse_uri_config) { described_class.parse_uri_config(uri_config) }
35
+
36
+ context "when uri_config is valid" do
37
+ let(:uri_config) { udp_uri_config }
38
+ it { is_expected.to eq({type: 'udp', host: 'localhost', port: 5228, path: ''}) }
39
+ end
40
+
41
+ context "when uri is invalid" do
42
+ let(:uri_config) { invalid_uri_config }
43
+ specify { expect { parse_uri_config }.to raise_error(URI::InvalidURIError) }
44
+ end
45
+ end
46
+
47
+ describe "Parsing URI configurations" do
48
+ subject(:new_device) { described_class.new(uri_config) }
49
+
50
+ context "when URI config is udp" do
51
+ let(:uri_config) { udp_uri_config }
52
+ it { is_expected.to be_a LogStashLogger::Device::UDP }
53
+ end
54
+
55
+ context "when URI config is tcp" do
56
+ let(:uri_config) { tcp_uri_config }
57
+ it { is_expected.to be_a LogStashLogger::Device::TCP }
58
+ end
59
+
60
+ context "when URI config is unix" do
61
+ let(:uri_config) { unix_uri_config }
62
+ it { is_expected.to be_a LogStashLogger::Device::Unix }
63
+ end
64
+
65
+ context "when URI config is file" do
66
+ let(:uri_config) { file_uri_config }
67
+ it { is_expected.to be_a LogStashLogger::Device::File }
68
+ end
69
+
70
+ context "when URI config is redis" do
71
+ let(:uri_config) { redis_uri_config }
72
+ it { is_expected.to be_a LogStashLogger::Device::Redis }
73
+ context "list specified" do
74
+ let(:uri_config) { redis_uri_config.merge({list: 'mylist'}) }
75
+ it 'is expected to have the list option set' do
76
+ expect(new_device.list).to eq('mylist')
77
+ end
78
+ end
79
+ end
80
+
81
+ context "when URI config is kafka" do
82
+ let(:uri_config) { kafka_uri_config }
83
+ it { is_expected.to be_a LogStashLogger::Device::Kafka }
84
+ end
85
+
86
+ context "when URI config is stdout" do
87
+ let(:uri_config) { stdout_uri_config }
88
+ it { is_expected.to be_a LogStashLogger::Device::Stdout }
89
+ end
90
+
91
+ context 'when URI config is stderr' do
92
+ let(:uri_config) { stderr_uri_config }
93
+ it { is_expected.to be_a LogStashLogger::Device::Stderr }
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,125 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter::Base do
4
+ include_context "formatter"
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
+
28
+ describe "#build_event" do
29
+ let(:event) { formatted_message }
30
+
31
+ describe "message type" do
32
+ context "string" do
33
+ it "puts the message into the message field" do
34
+ expect(event['message']).to eq(message)
35
+ end
36
+ end
37
+
38
+ context "JSON string" do
39
+ let(:message) do
40
+ { message: 'test', foo: 'bar' }.to_json
41
+ end
42
+
43
+ it "parses the JSON and merges into the event" do
44
+ expect(event['message']).to eq('test')
45
+ expect(event['foo']).to eq('bar')
46
+ end
47
+ end
48
+
49
+ context "hash" do
50
+ let(:message) do
51
+ { 'message' => 'test', 'foo' => 'bar' }
52
+ end
53
+
54
+ it "merges into the event" do
55
+ expect(event['message']).to eq('test')
56
+ expect(event['foo']).to eq('bar')
57
+ end
58
+ end
59
+
60
+ context "LogStash::Event" do
61
+ let(:message) { LogStash::Event.new("message" => "foo") }
62
+
63
+ it "returns a clone of the original event" do
64
+ expect(event['message']).to eq("foo")
65
+ expect(event).to_not equal(message)
66
+ end
67
+ end
68
+
69
+ context "fallback" do
70
+ let(:message) { [1, 2, 3] }
71
+
72
+ it "calls inspect" do
73
+ expect(event['message']).to eq(message.inspect)
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "extra fields on the event" do
79
+ it "adds severity" do
80
+ expect(event['severity']).to eq(severity)
81
+ end
82
+
83
+ it "adds host" do
84
+ expect(event['host']).to eq(hostname)
85
+ end
86
+ end
87
+
88
+ describe "timestamp" do
89
+ it "ensures time is in ISO8601 format" do
90
+ expect(event.timestamp).to eq(time.iso8601(3))
91
+ end
92
+ end
93
+
94
+ describe "long messages" do
95
+
96
+ context "message field is present" do
97
+ let(:message) { long_message }
98
+
99
+ it "truncates long messages when max_message_size is set" do
100
+ LogStashLogger.configure do |config|
101
+ config.max_message_size = 2000
102
+ end
103
+
104
+ expect(event['message'].size).to eq(2000)
105
+ end
106
+ end
107
+
108
+ context "event without message field" do
109
+ let(:message) do
110
+ { 'test_field' => 'test', 'foo' => 'bar' }
111
+ end
112
+
113
+ it "still works" do
114
+ LogStashLogger.configure do |config|
115
+ config.max_message_size = 2000
116
+ end
117
+
118
+ expect(event['message']).to eq(nil)
119
+ expect(event['test_field']).to eq('test')
120
+ expect(event['foo']).to eq('bar')
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,15 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter::Cee do
4
+ include_context "formatter"
5
+
6
+ it "outputs in CEE format" do
7
+ expect(formatted_message).to match(/\A@cee:/)
8
+ end
9
+
10
+ it "serializes the LogStash::Event data as JSON" do
11
+ json_data = formatted_message[/\A@cee:\s?(.*)\z/, 1]
12
+ json_message = JSON.parse(json_data)
13
+ expect(json_message["message"]).to eq(message)
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter::CeeSyslog do
4
+ include_context "formatter"
5
+
6
+ describe "#call" do
7
+ let(:facility) { "facility" }
8
+
9
+ before do
10
+ allow(subject).to receive(:build_facility).and_return(facility)
11
+ end
12
+
13
+ it "outputs a facility before the @cee" do
14
+ expect(formatted_message).to match(/\A#{facility}:@cee:/)
15
+ end
16
+
17
+ it "serializes the LogStash::Event data as JSON" do
18
+ json_data = formatted_message[/\A#{facility}:@cee:\s?(.*)\Z/, 1]
19
+ json_message = JSON.parse(json_data)
20
+ expect(json_message["message"]).to eq(message)
21
+ end
22
+ end
23
+
24
+ describe "#build_facility" do
25
+ let(:host) { Socket.gethostname }
26
+
27
+ before do
28
+ formatted_message
29
+ end
30
+
31
+ it "includes hostname and progname" do
32
+ expect(subject.send(:build_facility, host)).to match(/\A#{host}\s#{progname}\z/)
33
+ end
34
+
35
+ context "without progname" do
36
+ let(:progname) { nil }
37
+
38
+ it "only includes hostname" do
39
+ expect(subject.send(:build_facility, host)).to match(/\A#{host}\z/)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter::JsonLines do
4
+ include_context "formatter"
5
+
6
+ it "outputs in JSON format" do
7
+ json_message = JSON.parse(formatted_message)
8
+ expect(json_message["message"]).to eq(message)
9
+ end
10
+
11
+ it "terminates with a line break" do
12
+ expect(formatted_message[-1]).to eq("\n")
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter::Json do
4
+ include_context "formatter"
5
+
6
+ it "outputs in JSON format" do
7
+ json_message = JSON.parse(formatted_message)
8
+ expect(json_message["message"]).to eq(message)
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter::LogStashEvent do
4
+ include_context "formatter"
5
+
6
+ it "outputs a LogStash::Event" do
7
+ expect(formatted_message).to be_a LogStash::Event
8
+ expect(formatted_message["message"]).to eq(message)
9
+ end
10
+ end
@@ -0,0 +1,79 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger::Formatter do
4
+ describe "#new" do
5
+ context "built in formatters" do
6
+ it "returns a new JsonLines formatter" do
7
+ expect(described_class.new(:json_lines)).to be_a LogStashLogger::Formatter::JsonLines
8
+ end
9
+
10
+ it "returns a new Json formatter" do
11
+ expect(described_class.new(:json)).to be_a LogStashLogger::Formatter::Json
12
+ end
13
+
14
+ it "returns a new Cee formatter" do
15
+ expect(described_class.new(:cee)).to be_a LogStashLogger::Formatter::Cee
16
+ end
17
+
18
+ it "returns a new CeeSyslog formatter" do
19
+ expect(described_class.new(:cee_syslog)).to be_a LogStashLogger::Formatter::CeeSyslog
20
+ end
21
+
22
+ it "returns a new LogStashEvent formatter" do
23
+ expect(described_class.new(:logstash_event)).to be_a LogStashLogger::Formatter::LogStashEvent
24
+ end
25
+ end
26
+
27
+ context "custom formatter" do
28
+ subject { described_class.new(formatter) }
29
+
30
+ context "formatter class" do
31
+ let(:formatter) { ::Logger::Formatter }
32
+
33
+ it "returns a new instance of the class" do
34
+ expect(subject).to be_a formatter
35
+ end
36
+ end
37
+
38
+ context "formatter instance" do
39
+ let(:formatter) { ::Logger::Formatter.new }
40
+
41
+ it "returns the same formatter instance" do
42
+ expect(subject).to eql(formatter)
43
+ end
44
+
45
+ it "supports tagged logging" do
46
+ expect(subject).to be_a ::LogStashLogger::TaggedLogging::Formatter
47
+ end
48
+ end
49
+
50
+ context "formatter proc" do
51
+ let(:formatter) do
52
+ proc { |severity, time, progname, msg| msg }
53
+ end
54
+
55
+ it "returns the same formatter proc" do
56
+ expect(subject).to eql(formatter)
57
+ end
58
+
59
+ it "supports tagged logging" do
60
+ expect(subject).to be_a ::LogStashLogger::TaggedLogging::Formatter
61
+ end
62
+ end
63
+
64
+ context "formatter lambda" do
65
+ let(:formatter) do
66
+ ->(severity, time, progname, msg) { msg }
67
+ end
68
+
69
+ it "returns the same formatter lambda" do
70
+ expect(subject).to eql(formatter)
71
+ end
72
+
73
+ it "supports tagged logging" do
74
+ expect(subject).to be_a ::LogStashLogger::TaggedLogging::Formatter
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,128 @@
1
+ require 'logstash-logger'
2
+
3
+ describe LogStashLogger do
4
+ include_context 'logger'
5
+
6
+ let! :listener do
7
+ case connection_type
8
+ when :tcp
9
+ TCPServer.new(port)
10
+ when :udp
11
+ UDPSocket.new.tap {|socket| socket.bind(host, port)}
12
+ end
13
+ end
14
+
15
+ # The TCP socket written to by the TCP logstash listener server
16
+ let(:tcp_client) { listener.accept }
17
+
18
+ # The logstash event to log
19
+ let(:logstash_event) do
20
+ LogStash::Event.new.tap do |event|
21
+ event['message'] = 'test'
22
+ event['severity'] = 'INFO'
23
+ end
24
+ end
25
+
26
+ # The raw input received by the logstash listener
27
+ let :listener_input do
28
+ case connection_type
29
+ when :tcp then tcp_client.readline
30
+ when :udp then listener.recvfrom(8192)[0]
31
+ end
32
+ end
33
+
34
+ # The logstash event received by the listener
35
+ let(:listener_event) { LogStash::Event.new(JSON.parse listener_input) }
36
+
37
+ #before(:each) do
38
+ # Sync socket writes so we can receive them in the listener immediately
39
+ #@socket = logdev.instance_variable_get(:@dev).send(:connect)
40
+ #@socket.sync = true
41
+ #end
42
+
43
+ after(:each) do
44
+ listener.close
45
+ end
46
+
47
+ # The socket that the logger is writing to
48
+ #let(:socket) { @socket }
49
+
50
+ it 'uses a LogStashLogger::Device as the log device' do
51
+ expect(logdev).to be_a Logger::LogDevice
52
+ expect(logdev.instance_variable_get(:@dev)).to be_a LogStashLogger::Device::Base
53
+ end
54
+
55
+ it 'takes a string message as input and writes a logstash event' do
56
+ message = 'test'
57
+ logger.info(message)
58
+
59
+ expect(listener_event['severity']).to eql('INFO')
60
+ expect(listener_event['message']).to eq(message)
61
+ expect(listener_event['host']).to eq(hostname)
62
+ end
63
+
64
+ it 'takes a logstash-formatted json string as input and writes out a logstash event' do
65
+ logger.info(logstash_event.to_json)
66
+
67
+ expect(listener_event['message']).to eq(logstash_event['message'])
68
+ expect(listener_event['host']).to eq(hostname)
69
+ end
70
+
71
+ it 'takes a LogStash::Event as input and writes it out intact' do
72
+ logger.warn(logstash_event)
73
+
74
+ expect(listener_event['message']).to eq(logstash_event['message'])
75
+ expect(listener_event['severity']).to eq(logstash_event['severity'])
76
+ expect(listener_event['@timestamp'].iso8601).to eq(logstash_event.timestamp.iso8601)
77
+ expect(listener_event['host']).to eq(hostname)
78
+ end
79
+
80
+ it 'takes a data hash as input and writes out a logstash event' do
81
+ data = {
82
+ 'message' => 'test',
83
+ 'severity' => 'INFO',
84
+ 'foo' => 'bar'
85
+ }
86
+
87
+ logger.info(data.dup)
88
+
89
+ expect(listener_event['message']).to eq(data["message"])
90
+ expect(listener_event['severity']).to eq(data['severity'])
91
+ expect(listener_event['foo']).to eq(data['foo'])
92
+ expect(listener_event['host']).to eq(hostname)
93
+ expect(listener_event['@timestamp']).to_not be_nil
94
+ end
95
+
96
+ it 'takes any object as input and writes a logstash event' do
97
+ message = Time.now
98
+
99
+ logger.info(message)
100
+
101
+ expect(listener_event['message']).to eq(message.inspect)
102
+ expect(listener_event['host']).to eq(hostname)
103
+ expect(listener_event['severity']).to eq('INFO')
104
+ end
105
+
106
+ it 'allows event to be customized via configuration' do
107
+ LogStashLogger.configure do |config|
108
+ config.customize_event do |event|
109
+ event["test1"] = "response1"
110
+ end
111
+ end
112
+
113
+ logger.info("test")
114
+
115
+ expect(listener_event["test1"]).to eq("response1")
116
+ end
117
+
118
+ describe 'customize_event on instance' do
119
+ let!(:customize_event) { ->(event){ event['custom'] = 'custom' } }
120
+ let!(:logger) { LogStashLogger.new(host: host, port: port, type: connection_type, sync: true, customize_event: customize_event)}
121
+
122
+ specify 'logger produce messages with custom field' do
123
+ logger.info('test')
124
+ expect(listener_event['custom']).to eq('custom')
125
+ end
126
+ end
127
+
128
+ end