fluent-plugin-scalyr 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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