fluent-plugin-scalyr 0.7.4

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.
@@ -0,0 +1,248 @@
1
+ #
2
+ # Scalyr Output Plugin for Fluentd
3
+ #
4
+ # Copyright (C) 2015 Scalyr, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ require 'helper'
20
+ require 'fluent/event'
21
+
22
+ class EventsTest < Scalyr::ScalyrOutTest
23
+
24
+ def test_format
25
+ d = create_driver
26
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
27
+ mock = flexmock( d.instance )
28
+ mock.should_receive( :post_request ).with_any_args.and_return( response )
29
+
30
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
31
+ d.emit( { "a" => 1 }, time )
32
+ d.expect_format [ "test", time, { "a" => 1 } ].to_msgpack
33
+ d.run
34
+ end
35
+
36
+ def test_build_add_events_body_basic_values
37
+ d = create_driver
38
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
39
+ mock = flexmock( d.instance )
40
+
41
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
42
+ attrs = { "a" => 1 }
43
+ d.emit( attrs, time )
44
+
45
+ attrs["logfile"] = "/fluentd/test";
46
+
47
+ mock.should_receive( :post_request ).with(
48
+ URI,
49
+ on { |request_body|
50
+ body = JSON.parse( request_body )
51
+ assert( body.key?( "token" ), "Missing token field" )
52
+ assert( body.key?( "client_timestamp" ), "Missing client_timestamp field" )
53
+ assert( body.key?( "session" ), "Missing session field" )
54
+ assert( !body.key?( "sessionInfo"), "sessionInfo field set, but no sessionInfo" )
55
+ assert( body.key?( "events" ), "missing events field" )
56
+ assert( body.key?( "threads" ), "missing threads field" )
57
+ assert_equal( 1, body['events'].length, "Only expecting 1 event" )
58
+ assert_equal( d.instance.to_nanos( time ), body['events'][0]['ts'].to_i, "Event timestamp differs" )
59
+ assert_equal( attrs, body['events'][0]['attrs'], "Value of attrs differs from log" )
60
+ true
61
+ }
62
+ ).and_return( response )
63
+
64
+ d.run
65
+ end
66
+
67
+ def test_build_add_events_body_dont_override_logfile_field
68
+ d = create_driver
69
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
70
+ mock = flexmock( d.instance )
71
+
72
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
73
+ attrs = { "a" => 1 }
74
+ attrs["logfile"] = "/some/log/file";
75
+ d.emit( attrs, time )
76
+
77
+ mock.should_receive( :post_request ).with(
78
+ URI,
79
+ on { |request_body|
80
+ body = JSON.parse( request_body )
81
+ assert_equal( attrs, body['events'][0]['attrs'], "Value of attrs differs from log" )
82
+ true
83
+ }
84
+ ).and_return( response )
85
+
86
+ d.run
87
+ end
88
+
89
+ def test_build_add_events_body_with_server_attributes
90
+ d = create_driver CONFIG + 'server_attributes { "test":"value" }'
91
+
92
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
93
+ mock = flexmock( d.instance )
94
+
95
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
96
+ attrs = { "a" => 1 }
97
+ d.emit( attrs, time )
98
+
99
+ mock.should_receive( :post_request ).with(
100
+ URI,
101
+ on { |request_body|
102
+ body = JSON.parse( request_body )
103
+ assert( body.key?( "sessionInfo"), "sessionInfo field set, but no sessionInfo" )
104
+ assert_equal( "value", body["sessionInfo"]["test"] )
105
+ true
106
+ }
107
+ ).and_return( response )
108
+
109
+ d.run
110
+ end
111
+
112
+ def test_build_add_events_body_incrementing_timestamps
113
+ d = create_driver
114
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
115
+ mock = flexmock( d.instance )
116
+
117
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
118
+ d.emit( { "a" => 1 }, time )
119
+ d.emit( { "a" => 2 }, time )
120
+
121
+ time = Time.parse("2015-04-01 09:59:00 UTC").to_i
122
+ d.emit( { "a" => 3 }, time )
123
+
124
+ mock.should_receive( :post_request ).with(
125
+ URI,
126
+ on { |request_body|
127
+ body = JSON.parse( request_body )
128
+ events = body['events']
129
+ assert_equal( 3, events.length, "Expecting 3 events" )
130
+ #test equal timestamps are increased
131
+ assert events[1]['ts'].to_i > events[0]['ts'].to_i, "Event timestamps must increase"
132
+
133
+ #test earlier timestamps are increased
134
+ assert events[2]['ts'].to_i > events[1]['ts'].to_i, "Event timestamps must increase"
135
+
136
+ true
137
+ }
138
+ ).and_return( response )
139
+
140
+ d.run
141
+ end
142
+
143
+ def test_build_add_events_body_thread_ids
144
+ d = create_driver
145
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
146
+ mock = flexmock( d.instance )
147
+
148
+ entries = []
149
+
150
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
151
+ entries << [time, { "a" => 1 }]
152
+
153
+ es = Fluent::ArrayEventStream.new(entries)
154
+ buffer = d.instance.format_stream("test1", es)
155
+
156
+ chunk = d.instance.buffer.new_chunk('')
157
+ chunk << buffer
158
+
159
+ buffer = d.instance.format_stream("test2", es)
160
+ chunk << buffer
161
+
162
+ mock.should_receive( :post_request ).with(
163
+ URI,
164
+ on { |request_body|
165
+ body = JSON.parse( request_body )
166
+ events = body['events']
167
+ threads = body['threads']
168
+
169
+ assert_equal( 2, threads.length, "Expecting 2 threads, #{threads.length} found" )
170
+ assert_equal( 2, events.length, "Expecting 2 events, #{events.length} found" )
171
+ assert_equal( events[0]['thread'], threads[0]['id'].to_s, "thread id should match event thread id" )
172
+ assert_equal( events[1]['thread'], threads[1]['id'].to_s, "thread id should match event thread id" )
173
+ true
174
+ }
175
+ ).at_least.once.and_return( response )
176
+
177
+ d.instance.start
178
+ d.instance.write( chunk )
179
+ d.instance.shutdown
180
+ end
181
+
182
+ def test_default_message_field
183
+ d = create_driver CONFIG
184
+
185
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
186
+ mock = flexmock( d.instance )
187
+
188
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
189
+ attrs = { "log" => "this is a test", "logfile" => "/fluentd/test" }
190
+ d.emit( attrs, time )
191
+
192
+ mock.should_receive( :post_request ).with(
193
+ URI,
194
+ on { |request_body|
195
+ body = JSON.parse( request_body )
196
+ events = body['events']
197
+ assert_equal( attrs, body['events'][0]['attrs'], "Value of attrs differs from log" )
198
+ true
199
+ }
200
+ ).and_return( response )
201
+
202
+ d.run
203
+ end
204
+
205
+ def test_different_message_field
206
+ d = create_driver CONFIG + 'message_field log'
207
+
208
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
209
+ mock = flexmock( d.instance )
210
+
211
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
212
+ attrs = { "log" => "this is a test" }
213
+ d.emit( attrs, time )
214
+
215
+ mock.should_receive( :post_request ).with(
216
+ URI,
217
+ on { |request_body|
218
+ body = JSON.parse( request_body )
219
+ events = body['events']
220
+ assert( events[0]['attrs'].key?( 'message'), "'message' field not found in event" )
221
+ assert_equal( "this is a test", events[0]['attrs']['message'], "'message' field incorrect" )
222
+ assert( !events[0]['attrs'].key?( 'log' ), "'log' field should no longer exist in event" )
223
+ true
224
+ }
225
+ ).and_return( response )
226
+
227
+ d.run
228
+ end
229
+
230
+ def test_different_message_field_message_already_exists
231
+ d = create_driver CONFIG + 'message_field log'
232
+
233
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
234
+ mock = flexmock( d.instance )
235
+ mock.should_receive( :post_request ).and_return( response )
236
+
237
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
238
+ attrs = { "log" => "this is a test", "message" => "uh oh" }
239
+ d.emit( attrs, time )
240
+
241
+ logger = flexmock( $log )
242
+ logger.should_receive( :warn ).with( /overwriting log record field 'message'/i ).at_least().once()
243
+
244
+ d.run
245
+ end
246
+
247
+ end
248
+
@@ -0,0 +1,90 @@
1
+ #
2
+ # Scalyr Output Plugin for Fluentd
3
+ #
4
+ # Copyright (C) 2015 Scalyr, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ require 'helper'
20
+ require 'flexmock/test_unit'
21
+
22
+ class HandleResponseTest < Scalyr::ScalyrOutTest
23
+
24
+ def test_handle_response_missing_status
25
+ d = create_driver
26
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "message":"An invalid message" }' )
27
+ exception = assert_raise( Scalyr::ServerError, "Server error not raised for missing status" ) {
28
+ d.instance.handle_response( response )
29
+ }
30
+
31
+ assert_equal( "JSON response does not contain status message", exception.message )
32
+ end
33
+
34
+ def test_handle_response_discard_buffer
35
+ d = create_driver
36
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "message":"An invalid message", "status":"error/server/discardBuffer" }' )
37
+ logger = flexmock( $log )
38
+ logger.should_receive( :warn ).with( /buffer dropped/i )
39
+ assert_nothing_raised( Scalyr::ServerError, Scalyr::ClientError, "Nothing should be raised when discarding the buffer" ) {
40
+ d.instance.handle_response( response )
41
+ }
42
+
43
+ end
44
+
45
+ def test_handle_response_unknown_error
46
+ d = create_driver
47
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "message":"An invalid message", "status":"error/other" }' )
48
+ exception = assert_raise( Scalyr::ServerError, "Server error not raised for error status" ) {
49
+ d.instance.handle_response( response )
50
+ }
51
+ assert_equal( "error/other", exception.message )
52
+ end
53
+
54
+ def test_handle_response_client_error
55
+ d = create_driver
56
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "message":"An invalid message", "status":"error/client/test" }' )
57
+ exception = assert_raise( Scalyr::ClientError, "Client error not raised for error status" ) {
58
+ d.instance.handle_response( response )
59
+ }
60
+ assert_equal( "error/client/test", exception.message )
61
+ end
62
+
63
+ def test_handle_response_server_error
64
+ d = create_driver
65
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "message":"An invalid message", "status":"error/server/test" }' )
66
+ exception = assert_raise( Scalyr::ServerError, "Server error not raised for error status" ) {
67
+ d.instance.handle_response( response )
68
+ }
69
+ assert_equal( "error/server/test", exception.message )
70
+ end
71
+
72
+ def test_handle_response_code_4xx
73
+ d = create_driver
74
+ response = flexmock( Net::HTTPResponse, :code => '404', :body =>'{ "status":"error/server/fileNotFound" }' )
75
+ exception = assert_raise( Scalyr::Client4xxError, "No 4xx exception raised" ) {
76
+ d.instance.handle_response( response )
77
+ }
78
+ assert_equal( "error/server/fileNotFound", exception.message )
79
+ end
80
+
81
+ def test_handle_response_code_200
82
+ d = create_driver
83
+ response = flexmock( Net::HTTPResponse, :code => '200', :body =>'{ "status":"success" }' )
84
+ exception = assert_nothing_raised( Scalyr::ServerError, Scalyr::ClientError, "Error raised on success" ) {
85
+ d.instance.handle_response( response )
86
+ }
87
+ end
88
+
89
+ end
90
+
@@ -0,0 +1,35 @@
1
+ #
2
+ # Scalyr Output Plugin for Fluentd
3
+ #
4
+ # Copyright (C) 2015 Scalyr, Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ require 'helper'
20
+
21
+ class SSLVerifyTest < Scalyr::ScalyrOutTest
22
+ def test_bad_ssl_certificates
23
+ d = create_driver CONFIG + 'ssl_ca_bundle_path /home/invalid'
24
+
25
+ time = Time.parse("2015-04-01 10:00:00 UTC").to_i
26
+ d.emit( { "a" => 1 }, time )
27
+
28
+ logger = flexmock( $log )
29
+ logger.should_receive( :warn ).with( /certificate verification failed/i )
30
+ logger.should_receive( :warn ).with( /certificate verify failed/i )
31
+ logger.should_receive( :warn ).with( /discarding buffer/i )
32
+
33
+ d.run
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-scalyr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.4
5
+ platform: ruby
6
+ authors:
7
+ - Imron Alston
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.49
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '0.14'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.10.49
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.14'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.9'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.9'
47
+ - !ruby/object:Gem::Dependency
48
+ name: test-unit
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: flexmock
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.2'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.2'
75
+ - !ruby/object:Gem::Dependency
76
+ name: bundler
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.9'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.9'
89
+ description: Sends log data collected by fluentd to Scalyr (http://www.scalyr.com)
90
+ email: imron@imralsoftware.com
91
+ executables: []
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - AUTHORS
96
+ - Gemfile
97
+ - LICENSE
98
+ - README.md
99
+ - Rakefile
100
+ - VERSION
101
+ - fluent-plugin-scalyr.gemspec
102
+ - fluent.conf.sample
103
+ - lib/fluent/plugin/out_scalyr.rb
104
+ - lib/fluent/plugin/scalyr-exceptions.rb
105
+ - test/helper.rb
106
+ - test/test_config.rb
107
+ - test/test_events.rb
108
+ - test/test_handle_response.rb
109
+ - test/test_ssl_verify.rb
110
+ homepage: https://github.com/scalyr/scalyr-fluentd
111
+ licenses:
112
+ - Apache-2.0
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.6.13
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Scalyr plugin for fluentd
134
+ test_files:
135
+ - test/helper.rb
136
+ - test/test_config.rb
137
+ - test/test_events.rb
138
+ - test/test_handle_response.rb
139
+ - test/test_ssl_verify.rb