fluent-plugin-sumologic_output 1.7.5 → 1.9.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
2
  SHA256:
3
- metadata.gz: 10221368588a63fe0f97cb60695466a78a12eae80c13f736b5ae54879e4a5b4e
4
- data.tar.gz: 2b99181908e9df7b2bcae1e6534a9311d72464cb74923a77f3a7489eeeb13f94
3
+ metadata.gz: cbb31ea7d5a93f777e1c509790dec08a6462bade567f4ff222a62c628e3790b4
4
+ data.tar.gz: ed18ad85714d06efaee5c68689dfc36e4e78794e3a326602f46fd5947c28ee6a
5
5
  SHA512:
6
- metadata.gz: 245aa88c7c415099db251eabf2c6b9e80a64d657cdf4df90e365115e962cbeec76279cab1d4d5dc87de1b6387475c0e6363a2be24c55d21953d4bc852727d869
7
- data.tar.gz: c9a870b1252ca73b2565a4627e29ee5501ce9da6caa88834932d0edee05e45f573a5f7aeae183968e303786615622487188287236b1d12d8234ac992f25e822a
6
+ metadata.gz: 20ee2dc1b70ea6845e8251711e997ce08c682c2c5bdbf923cbef8b26a907498174a8ea77dcac8f9e405bead5deaa2acff1cc560c9c2c9dfa41c18f1c549372b1
7
+ data.tar.gz: 9c6bbd8fb280eba89718191a68f6d79a1f244f34d863aa9aa621e47766ad20769e98a5ee6718a77b2934551562b9c8603b06879de30f51fd3f9d24a3e6252dca
@@ -0,0 +1,23 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - '[0-9]+.[0-9]+.[0-9]+'
7
+ - '[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+'
8
+ - '[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+'
9
+ - '[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+'
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-20.04
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Build
19
+ run: gem build fluent-plugin-sumologic_output.gemspec
20
+ - name: Publish
21
+ env:
22
+ GEM_HOST_API_KEY: ${{ secrets.RUGYGEMS_APIKEY }}
23
+ run: gem push fluent-plugin-sumologic_output-*.gem
@@ -0,0 +1,15 @@
1
+ name: PR check
2
+
3
+ on:
4
+ pull_request:
5
+
6
+ jobs:
7
+ test:
8
+ runs-on: ubuntu-20.04
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: '3.3'
14
+ - run: bundle install
15
+ - run: bundle exec rake
data/CHANGELOG.md CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. Tracking did not begin until version 1.10.
4
4
 
5
+ ## [1.9.0]
6
+
7
+ Released 2024-02-14
8
+
9
+ - feat: enable compression by default [#87](https://github.com/SumoLogic/fluentd-output-sumologic/pull/87)
10
+ - feat: log warning if `log_key` does not exist in log [#86](https://github.com/SumoLogic/fluentd-output-sumologic/pull/86)
11
+ - fix: fix how `compress` configuration flag works [#90](https://github.com/SumoLogic/fluentd-output-sumologic/pull/90)
12
+
13
+ In `v1.8.0`, setting `compress` flag to either `true` or `false` caused compression to be enabled.
14
+ This is now fixed.
15
+
16
+ [1.9.0]: https://github.com/SumoLogic/fluentd-output-sumologic/releases/1.9.0
17
+
18
+ <a name="1.8.0"></a>
19
+ # [1.8.0] (2022-04-22)
20
+
21
+ - feat: add exponential backoff for sending data [#76](https://github.com/SumoLogic/fluentd-output-sumologic/pull/76)
22
+ - feat(max_request_size): add max_request_size to limit size of requests [#78](https://github.com/SumoLogic/fluentd-output-sumologic/pull/78)
23
+
24
+ <a name="1.7.5"></a>
25
+ # [1.7.5] (2022-04-11)
26
+
27
+ - refactor: add a debug log on sending [#75](https://github.com/SumoLogic/fluentd-output-sumologic/pull/75)
28
+
29
+ <a name="1.7.4"></a>
30
+ # [1.7.4] (2021-04-08)
31
+
32
+ - fix: handle receiver warning messages [#73](https://github.com/SumoLogic/fluentd-output-sumologic/pull/73)
33
+
5
34
  <a name="1.7.3"></a>
6
35
  # [1.7.3] (2021-10-19)
7
36
  - Expose httpclient send_timeout [#66](https://github.com/SumoLogic/fluentd-output-sumologic/pull/68)
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,23 @@
1
+ # Contributing
2
+
3
+ ## How to release
4
+
5
+ 1. Create a pull request named `chore: release x.y.z` with the following changes:
6
+
7
+ - Set `gem.version` to `"x.y.z"` in [fluent-plugin-sumologic_output.gemspec](fluent-plugin-sumologic_output.gemspec).
8
+ - Add new version to [CHANGELOG.md](./CHANGELOG.md).
9
+
10
+ 2. Create and push the release tag:
11
+
12
+ ```bash
13
+ git checkout main
14
+ git pull
15
+ export VERSION=x.y.z
16
+ git tag -a "v${VERSION}" -m "Release v${VERSION}"
17
+ git push origin "v${VERSION}"
18
+ ```
19
+
20
+ This will trigger the GitHub Actions [publish](./.github/workflows/publish.yaml) action to pubilsh the gem in Ruby Gems.
21
+
22
+ 3. Go to https://github.com/SumoLogic/fluentd-output-sumologic/releases and create a new release for the tag.
23
+ Copy the changes from Changelog and publish the release.
data/README.md CHANGED
@@ -34,10 +34,17 @@ Configuration options for fluent.conf are:
34
34
  * `proxy_uri` - Add the `uri` of the `proxy` environment if present.
35
35
  * `metric_data_format` - The format of metrics you will be sending, either `graphite` or `carbon2` or `prometheus` (Default is `graphite `)
36
36
  * `disable_cookies` - Option to disable cookies on the HTTP Client. (Default is `false `)
37
- * `compress` - Option to enable compression (default `false`)
37
+ * `compress` - Option to enable compression (default `true`)
38
38
  * `compress_encoding` - Compression encoding format, either `gzip` or `deflate` (default `gzip`)
39
39
  * `custom_fields` - Comma-separated key=value list of fields to apply to every log. [more information](https://help.sumologic.com/Manage/Fields#http-source-fields)
40
40
  * `custom_dimensions` - Comma-separated key=value list of dimensions to apply to every metric. [more information](https://help.sumologic.com/03Send-Data/Sources/02Sources-for-Hosted-Collectors/HTTP-Source/Upload-Metrics-to-an-HTTP-Source#supported-http-headers)
41
+ * `use_internal_retry` - Enable custom retry mechanism. As this is `false` by default due to backward compatibility,
42
+ we recommend to enable it and configure the following parameters (`retry_min_interval`, `retry_max_interval`, `retry_timeout`, `retry_max_times`)
43
+ * `retry_min_interval` - Minimum interval to wait between sending tries (default is `1s`)
44
+ * `retry_max_interval` - Maximum interval to wait between sending tries (default is `5m`)
45
+ * `retry_timeout` - Time after which the data is going to be dropped (default is `72h`) (`0s` means that there is no timeout)
46
+ * `retry_max_times` - Maximum number of retries (default is `0`) (`0` means that there is no max retry times, retries will happen forever)
47
+ * `max_request_size` - Maximum request size (before applying compression). Default is `0k` which means no limit
41
48
 
42
49
  __NOTE:__ <sup>*</sup> [Placeholders](https://docs.fluentd.org/v1.0/articles/buffer-section#placeholders) are supported
43
50
 
@@ -137,6 +144,14 @@ Example
137
144
  }
138
145
  ```
139
146
 
147
+ ## Retry Mechanism
148
+
149
+ `retry_min_interval`, `retry_max_interval`, `retry_timeout`, `retry_max_times` are not the [buffer retries parameters][buffer_retries].
150
+ Due to technical reason, this plugin implements it's own retrying back-off exponential mechanism.
151
+ It is disabled by default, but we recommend to enable it by setting `use_internal_retry` to `true`.
152
+
153
+ [buffer_retries]: https://docs.fluentd.org/configuration/buffer-section#retries-parameters
154
+
140
155
  ### TLS 1.2 Requirement
141
156
 
142
157
  Sumo Logic only accepts connections from clients using TLS version 1.2 or greater. To utilize the content of this repo, ensure that it's running in an execution environment that is configured to use TLS 1.2 or greater.
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "fluent-plugin-sumologic_output"
7
- gem.version = "1.7.5"
7
+ gem.version = "1.9.0"
8
8
  gem.authors = ["Steven Adams", "Frank Reno"]
9
9
  gem.email = ["stevezau@gmail.com", "frank.reno@me.com"]
10
10
  gem.description = %q{Output plugin to SumoLogic HTTP Endpoint}
@@ -17,12 +17,10 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
- gem.required_ruby_version = '>= 2.0.0'
21
-
22
- gem.add_development_dependency "bundler", "~> 2"
20
+ gem.add_development_dependency "bundler"
23
21
  gem.add_development_dependency "rake"
24
- gem.add_development_dependency 'test-unit', '~> 3.1.0'
25
- gem.add_development_dependency "codecov", ">= 0.1.10"
26
- gem.add_runtime_dependency "fluentd", ">= 0.14.12"
27
- gem.add_runtime_dependency 'httpclient', '~> 2.8.0'
22
+ gem.add_development_dependency 'test-unit'
23
+ gem.add_development_dependency "codecov"
24
+ gem.add_runtime_dependency "fluentd"
25
+ gem.add_runtime_dependency 'httpclient'
28
26
  end
@@ -157,13 +157,22 @@ class Fluent::Plugin::Sumologic < Fluent::Plugin::Output
157
157
  config_param :timestamp_key, :string, :default => 'timestamp'
158
158
  config_param :proxy_uri, :string, :default => nil
159
159
  config_param :disable_cookies, :bool, :default => false
160
+
161
+ config_param :use_internal_retry, :bool, :default => false
162
+ config_param :retry_timeout, :time, :default => 72 * 3600 # 72h
163
+ config_param :retry_max_times, :integer, :default => 0
164
+ config_param :retry_min_interval, :time, :default => 1 # 1s
165
+ config_param :retry_max_interval, :time, :default => 5*60 # 5m
166
+
167
+ config_param :max_request_size, :size, :default => 0
168
+
160
169
  # https://help.sumologic.com/Manage/Fields
161
170
  desc 'Fields string (eg "cluster=payment, service=credit_card") which is going to be added to every log record.'
162
171
  config_param :custom_fields, :string, :default => nil
163
172
  desc 'Name of sumo client which is send as X-Sumo-Client header'
164
173
  config_param :sumo_client, :string, :default => 'fluentd-output'
165
174
  desc 'Compress payload'
166
- config_param :compress, :bool, :default => false
175
+ config_param :compress, :bool, :default => true
167
176
  desc 'Encoding method of compresssion (either gzip or deflate)'
168
177
  config_param :compress_encoding, :string, :default => SumologicConnection::COMPRESS_GZIP
169
178
  # https://help.sumologic.com/03Send-Data/Sources/02Sources-for-Hosted-Collectors/HTTP-Source/Upload-Metrics-to-an-HTTP-Source#supported-http-headers
@@ -187,65 +196,50 @@ class Fluent::Plugin::Sumologic < Fluent::Plugin::Output
187
196
  def configure(conf)
188
197
 
189
198
  compat_parameters_convert(conf, :buffer)
199
+ super
190
200
 
191
- unless conf['endpoint'] =~ URI::regexp
192
- raise Fluent::ConfigError, "Invalid SumoLogic endpoint url: #{conf['endpoint']}"
201
+ unless @endpoint =~ URI::regexp
202
+ raise Fluent::ConfigError, "Invalid SumoLogic endpoint url: #{@endpoint}"
193
203
  end
194
204
 
195
- unless conf['data_type'].nil?
196
- unless conf['data_type'] =~ /\A(?:logs|metrics)\z/
197
- raise Fluent::ConfigError, "Invalid data_type #{conf['data_type']} must be logs or metrics"
198
- end
205
+ unless @data_type =~ /\A(?:logs|metrics)\z/
206
+ raise Fluent::ConfigError, "Invalid data_type #{@data_type} must be logs or metrics"
199
207
  end
200
208
 
201
- if conf['data_type'].nil? || conf['data_type'] == LOGS_DATA_TYPE
202
- unless conf['log_format'].nil?
203
- unless conf['log_format'] =~ /\A(?:json|text|json_merge|fields)\z/
204
- raise Fluent::ConfigError, "Invalid log_format #{conf['log_format']} must be text, json, json_merge or fields"
205
- end
209
+ if @data_type == LOGS_DATA_TYPE
210
+ unless @log_format =~ /\A(?:json|text|json_merge|fields)\z/
211
+ raise Fluent::ConfigError, "Invalid log_format #{@log_format} must be text, json, json_merge or fields"
206
212
  end
207
213
  end
208
214
 
209
- if conf['data_type'] == METRICS_DATA_TYPE && ! conf['metrics_data_type'].nil?
210
- unless conf['metrics_data_type'] =~ /\A(?:graphite|carbon2|pronetheus)\z/
211
- raise Fluent::ConfigError, "Invalid metrics_data_type #{conf['metrics_data_type']} must be graphite or carbon2 or prometheus"
215
+ if @data_type == METRICS_DATA_TYPE
216
+ unless @metric_data_format =~ /\A(?:graphite|carbon2|prometheus)\z/
217
+ raise Fluent::ConfigError, "Invalid metric_data_format #{@metric_data_format} must be graphite or carbon2 or prometheus"
212
218
  end
213
219
  end
214
220
 
215
- conf['custom_fields'] = validate_key_value_pairs(conf['custom_fields'])
216
- if conf['custom_fields'].nil?
217
- conf.delete 'custom_fields'
218
- end
219
- unless conf['custom_fields']
220
- @log.debug "Custom fields: #{conf['custom_fields']}"
221
+ @custom_fields = validate_key_value_pairs(@custom_fields)
222
+ if @custom_fields
223
+ @log.debug "Custom fields: #{@custom_fields}"
221
224
  end
222
225
 
223
- conf['custom_dimensions'] = validate_key_value_pairs(conf['custom_dimensions'])
224
- if conf['custom_dimensions'].nil?
225
- conf.delete 'custom_dimensions'
226
- end
227
- unless conf['custom_dimensions']
228
- @log.debug "Custom dimensions: #{conf['custom_dimensions']}"
229
- end
230
-
231
- # For some reason default is set incorrectly in unit-tests
232
- if conf['sumo_client'].nil? || conf['sumo_client'].strip.length == 0
233
- conf['sumo_client'] = 'fluentd-output'
226
+ @custom_dimensions = validate_key_value_pairs(@custom_dimensions)
227
+ if @custom_dimensions
228
+ @log.debug "Custom dimensions: #{@custom_dimensions}"
234
229
  end
235
230
 
236
231
  @sumo_conn = SumologicConnection.new(
237
- conf['endpoint'],
238
- conf['verify_ssl'],
239
- conf['open_timeout'].to_i,
240
- conf['send_timeout'].to_i,
241
- conf['proxy_uri'],
242
- conf['disable_cookies'],
243
- conf['sumo_client'],
244
- conf['compress'],
245
- conf['compress_encoding'],
246
- log,
232
+ @endpoint,
233
+ @verify_ssl,
234
+ @open_timeout,
235
+ @send_timeout,
236
+ @proxy_uri,
237
+ @disable_cookies,
238
+ @sumo_client,
239
+ @compress,
240
+ @compress_encoding,
241
+ @log,
247
242
  )
248
- super
249
243
  end
250
244
 
251
245
  # This method is called when starting.
@@ -354,6 +348,9 @@ class Fluent::Plugin::Sumologic < Fluent::Plugin::Output
354
348
  when 'logs'
355
349
  case log_format
356
350
  when 'text'
351
+ if !record.has_key?(@log_key)
352
+ log.warn "log key `#{@log_key}` has not been found in the log"
353
+ end
357
354
  log = log_to_str(record[@log_key])
358
355
  when 'json_merge'
359
356
  if @add_timestamp
@@ -385,6 +382,7 @@ class Fluent::Plugin::Sumologic < Fluent::Plugin::Output
385
382
 
386
383
  end
387
384
 
385
+ chunk_id = "##{chunk.dump_unique_id_hex(chunk.unique_id)}"
388
386
  # Push logs to sumo
389
387
  messages_list.each do |key, messages|
390
388
  source_name, source_category, source_host, fields = key[:source_name], key[:source_category],
@@ -397,18 +395,78 @@ class Fluent::Plugin::Sumologic < Fluent::Plugin::Output
397
395
  fields = [fields,@custom_fields].compact.join(",")
398
396
  end
399
397
 
400
- @log.debug { "Sending #{messages.count} #{@data_type} records with source category '#{source_category}', source host '#{source_host}', source name '#{source_name}'." }
401
-
402
- @sumo_conn.publish(
403
- messages.join("\n"),
404
- source_host =source_host,
405
- source_category =source_category,
406
- source_name =source_name,
407
- data_type =@data_type,
408
- metric_data_format =@metric_data_format,
409
- collected_fields =fields,
410
- dimensions =@custom_dimensions
411
- )
398
+ if @max_request_size <= 0
399
+ messages_to_send = [messages]
400
+ else
401
+ messages_to_send = []
402
+ current_message = []
403
+ current_length = 0
404
+ messages.each do |message|
405
+ current_message.push message
406
+ current_length += message.length
407
+
408
+ if current_length > @max_request_size
409
+ messages_to_send.push(current_message)
410
+ current_message = []
411
+ current_length = 0
412
+ end
413
+ current_length += 1 # this is for newline
414
+ end
415
+ if current_message.length > 0
416
+ messages_to_send.push(current_message)
417
+ end
418
+ end
419
+
420
+ messages_to_send.each_with_index do |message, i|
421
+ retries = 0
422
+ start_time = Time.now
423
+ sleep_time = @retry_min_interval
424
+
425
+ while true
426
+ common_log_part = "#{@data_type} records with source category '#{source_category}', source host '#{source_host}', source name '#{source_name}', chunk #{chunk_id}, try #{retries}, batch #{i}"
427
+
428
+ begin
429
+ @log.debug { "Sending #{message.count}; #{common_log_part}" }
430
+
431
+ @sumo_conn.publish(
432
+ message.join("\n"),
433
+ source_host =source_host,
434
+ source_category =source_category,
435
+ source_name =source_name,
436
+ data_type =@data_type,
437
+ metric_data_format =@metric_data_format,
438
+ collected_fields =fields,
439
+ dimensions =@custom_dimensions
440
+ )
441
+ break
442
+ rescue => e
443
+ if !@use_internal_retry
444
+ raise e
445
+ end
446
+ # increment retries
447
+ retries += 1
448
+
449
+ log.warn "error while sending request to sumo: #{e}; #{common_log_part}"
450
+ log.warn_backtrace e.backtrace
451
+
452
+ # drop data if
453
+ # - we reached out the @retry_max_times retries
454
+ # - or we exceeded @retry_timeout
455
+ if (retries >= @retry_max_times && @retry_max_times > 0) || (Time.now > start_time + @retry_timeout && @retry_timeout > 0)
456
+ log.warn "dropping records; #{common_log_part}"
457
+ break
458
+ end
459
+
460
+ log.info "going to retry to send data at #{Time.now + sleep_time}; #{common_log_part}"
461
+ sleep sleep_time
462
+
463
+ sleep_time *= 2
464
+ if sleep_time > @retry_max_interval
465
+ sleep_time = @retry_max_interval
466
+ end
467
+ end
468
+ end
469
+ end
412
470
  end
413
471
 
414
472
  end
@@ -19,7 +19,15 @@ class SumologicOutput < Test::Unit::TestCase
19
19
  def test_no_endpoint_configure
20
20
  config = %{}
21
21
  exception = assert_raise(Fluent::ConfigError) {create_driver(config)}
22
- assert_equal("Invalid SumoLogic endpoint url: ", exception.message)
22
+ assert_equal("'endpoint' parameter is required", exception.message)
23
+ end
24
+
25
+ def test_invalid_endpoint
26
+ config = %{
27
+ endpoint Not-a-URL
28
+ }
29
+ exception = assert_raise(Fluent::ConfigError) {create_driver(config)}
30
+ assert_equal("Invalid SumoLogic endpoint url: Not-a-URL", exception.message)
23
31
  end
24
32
 
25
33
  def test_invalid_data_type_configure
@@ -40,14 +48,14 @@ class SumologicOutput < Test::Unit::TestCase
40
48
  assert_equal("Invalid log_format foo must be text, json, json_merge or fields", exception.message)
41
49
  end
42
50
 
43
- def test_invalid_metrics_data_type
51
+ def test_invalid_metric_data_format
44
52
  config = %{
45
53
  endpoint https://SUMOLOGIC_URL
46
54
  data_type metrics
47
- metrics_data_type foo
55
+ metric_data_format foo
48
56
  }
49
57
  exception = assert_raise(Fluent::ConfigError) {create_driver(config)}
50
- assert_equal("Invalid metrics_data_type foo must be graphite or carbon2 or prometheus", exception.message)
58
+ assert_equal("Invalid metric_data_format foo must be graphite or carbon2 or prometheus", exception.message)
51
59
  end
52
60
 
53
61
  def test_default_configure
@@ -73,11 +81,13 @@ class SumologicOutput < Test::Unit::TestCase
73
81
  assert_equal instance.proxy_uri, nil
74
82
  assert_equal instance.disable_cookies, false
75
83
  assert_equal instance.sumo_client, 'fluentd-output'
84
+ assert_equal instance.compress, true
76
85
  assert_equal instance.compress_encoding, 'gzip'
77
86
  end
78
87
 
79
88
  def test_emit_text
80
89
  config = %{
90
+ compress false
81
91
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
82
92
  log_format text
83
93
  source_category test
@@ -99,6 +109,7 @@ class SumologicOutput < Test::Unit::TestCase
99
109
 
100
110
  def test_emit_text_custom_sumo_client
101
111
  config = %{
112
+ compress false
102
113
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
103
114
  log_format text
104
115
  source_category test
@@ -121,6 +132,7 @@ class SumologicOutput < Test::Unit::TestCase
121
132
 
122
133
  def test_emit_json
123
134
  config = %{
135
+ compress false
124
136
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
125
137
  log_format json
126
138
  source_category test
@@ -142,6 +154,7 @@ class SumologicOutput < Test::Unit::TestCase
142
154
 
143
155
  def test_emit_empty_fields
144
156
  config = %{
157
+ compress false
145
158
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
146
159
  log_format fields
147
160
  source_category test
@@ -163,6 +176,7 @@ class SumologicOutput < Test::Unit::TestCase
163
176
 
164
177
  def test_emit_json_double_encoded
165
178
  config = %{
179
+ compress false
166
180
  endpoint https://endpoint3.collection.us2.sumologic.com/receiver/v1/http/1234
167
181
  log_format json
168
182
  source_category test
@@ -184,6 +198,7 @@ class SumologicOutput < Test::Unit::TestCase
184
198
 
185
199
  def test_emit_text_format_as_json
186
200
  config = %{
201
+ compress false
187
202
  endpoint https://endpoint3.collection.us2.sumologic.com/receiver/v1/http/1234
188
203
  log_format json
189
204
  source_category test
@@ -205,6 +220,7 @@ class SumologicOutput < Test::Unit::TestCase
205
220
 
206
221
  def test_emit_json_merge
207
222
  config = %{
223
+ compress false
208
224
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
209
225
  log_format json_merge
210
226
  source_category test
@@ -226,6 +242,7 @@ class SumologicOutput < Test::Unit::TestCase
226
242
 
227
243
  def test_emit_json_merge_timestamp
228
244
  config = %{
245
+ compress false
229
246
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
230
247
  log_format json_merge
231
248
  source_category test
@@ -247,6 +264,7 @@ class SumologicOutput < Test::Unit::TestCase
247
264
 
248
265
  def test_emit_with_sumo_metadata_with_fields_json_format
249
266
  config = %{
267
+ compress false
250
268
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
251
269
  log_format json
252
270
  }
@@ -270,6 +288,7 @@ class SumologicOutput < Test::Unit::TestCase
270
288
 
271
289
  def test_emit_with_sumo_metadata_with_fields_fields_format
272
290
  config = %{
291
+ compress false
273
292
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
274
293
  log_format fields
275
294
  }
@@ -293,6 +312,7 @@ class SumologicOutput < Test::Unit::TestCase
293
312
 
294
313
  def test_emit_with_sumo_metadata_with_fields_and_custom_fields_fields_format
295
314
  config = %{
315
+ compress false
296
316
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
297
317
  log_format fields
298
318
  custom_fields "lorem=ipsum,dolor=amet"
@@ -317,6 +337,7 @@ class SumologicOutput < Test::Unit::TestCase
317
337
 
318
338
  def test_emit_with_sumo_metadata_with_fields_and_empty_custom_fields_fields_format
319
339
  config = %{
340
+ compress false
320
341
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
321
342
  log_format fields
322
343
  custom_fields ""
@@ -341,6 +362,7 @@ class SumologicOutput < Test::Unit::TestCase
341
362
 
342
363
  def test_emit_with_sumo_metadata_with_empty_fields_and_custom_fields_fields_format
343
364
  config = %{
365
+ compress false
344
366
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
345
367
  log_format fields
346
368
  custom_fields "lorem=ipsum,invalid"
@@ -365,6 +387,7 @@ class SumologicOutput < Test::Unit::TestCase
365
387
 
366
388
  def test_emit_with_sumo_metadata
367
389
  config = %{
390
+ compress false
368
391
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
369
392
  log_format json
370
393
  }
@@ -387,6 +410,7 @@ class SumologicOutput < Test::Unit::TestCase
387
410
 
388
411
  def test_emit_json_no_timestamp
389
412
  config = %{
413
+ compress false
390
414
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
391
415
  log_format json
392
416
  source_category test
@@ -408,6 +432,7 @@ class SumologicOutput < Test::Unit::TestCase
408
432
 
409
433
  def test_emit_json_timestamp_key
410
434
  config = %{
435
+ compress false
411
436
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
412
437
  log_format json
413
438
  source_category test
@@ -429,6 +454,7 @@ class SumologicOutput < Test::Unit::TestCase
429
454
 
430
455
  def test_emit_graphite
431
456
  config = %{
457
+ compress false
432
458
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
433
459
  data_type metrics
434
460
  metric_data_format graphite
@@ -450,6 +476,7 @@ class SumologicOutput < Test::Unit::TestCase
450
476
 
451
477
  def test_emit_carbon
452
478
  config = %{
479
+ compress false
453
480
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
454
481
  data_type metrics
455
482
  metric_data_format carbon2
@@ -471,6 +498,7 @@ class SumologicOutput < Test::Unit::TestCase
471
498
 
472
499
  def test_emit_prometheus
473
500
  config = %{
501
+ compress false
474
502
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
475
503
  data_type metrics
476
504
  metric_data_format prometheus
@@ -492,6 +520,7 @@ class SumologicOutput < Test::Unit::TestCase
492
520
 
493
521
  def test_emit_prometheus_with_custom_dimensions
494
522
  config = %{
523
+ compress false
495
524
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
496
525
  data_type metrics
497
526
  metric_data_format prometheus
@@ -520,6 +549,7 @@ class SumologicOutput < Test::Unit::TestCase
520
549
 
521
550
  def test_emit_prometheus_with_empty_custom_metadata
522
551
  config = %{
552
+ compress false
523
553
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
524
554
  data_type metrics
525
555
  metric_data_format prometheus
@@ -547,6 +577,7 @@ class SumologicOutput < Test::Unit::TestCase
547
577
 
548
578
  def test_batching_same_headers
549
579
  config = %{
580
+ compress false
550
581
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
551
582
  log_format json
552
583
  source_category test
@@ -568,6 +599,7 @@ class SumologicOutput < Test::Unit::TestCase
568
599
 
569
600
  def test_batching_different_headers
570
601
  config = %{
602
+ compress false
571
603
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
572
604
  log_format json
573
605
  source_category test
@@ -593,6 +625,7 @@ class SumologicOutput < Test::Unit::TestCase
593
625
 
594
626
  def test_batching_different_fields
595
627
  config = %{
628
+ compress false
596
629
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
597
630
  log_format fields
598
631
  source_category test
@@ -635,7 +668,6 @@ class SumologicOutput < Test::Unit::TestCase
635
668
  source_name test
636
669
  compress true
637
670
  compress_encoding deflate
638
-
639
671
  }
640
672
  driver = create_driver(config)
641
673
  time = event_time
@@ -657,7 +689,6 @@ class SumologicOutput < Test::Unit::TestCase
657
689
  source_host test
658
690
  source_name test
659
691
  compress true
660
-
661
692
  }
662
693
  driver = create_driver(config)
663
694
  time = event_time
@@ -673,6 +704,7 @@ class SumologicOutput < Test::Unit::TestCase
673
704
 
674
705
  def test_emit_text_from_array
675
706
  config = %{
707
+ compress false
676
708
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
677
709
  log_format text
678
710
  source_category test
@@ -694,6 +726,7 @@ class SumologicOutput < Test::Unit::TestCase
694
726
 
695
727
  def test_emit_text_from_dict
696
728
  config = %{
729
+ compress false
697
730
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
698
731
  log_format text
699
732
  source_category test
@@ -715,6 +748,7 @@ class SumologicOutput < Test::Unit::TestCase
715
748
 
716
749
  def test_emit_fields_string_based
717
750
  config = %{
751
+ compress false
718
752
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
719
753
  log_format fields
720
754
  source_category test
@@ -736,6 +770,7 @@ class SumologicOutput < Test::Unit::TestCase
736
770
 
737
771
  def test_emit_fields_invalid_json_string_based_1
738
772
  config = %{
773
+ compress false
739
774
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
740
775
  log_format fields
741
776
  source_category test
@@ -757,6 +792,7 @@ class SumologicOutput < Test::Unit::TestCase
757
792
 
758
793
  def test_emit_fields_invalid_json_string_based_2
759
794
  config = %{
795
+ compress false
760
796
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
761
797
  log_format fields
762
798
  source_category test
@@ -778,6 +814,7 @@ class SumologicOutput < Test::Unit::TestCase
778
814
 
779
815
  def test_emit_fields_invalid_json_string_based_3
780
816
  config = %{
817
+ compress false
781
818
  endpoint https://collectors.sumologic.com/v1/receivers/http/1234
782
819
  log_format fields
783
820
  source_category test
@@ -800,6 +837,7 @@ class SumologicOutput < Test::Unit::TestCase
800
837
  def test_warning_response_from_receiver
801
838
  endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
802
839
  config = %{
840
+ compress false
803
841
  endpoint #{endpoint}
804
842
  }
805
843
  testdata = [
@@ -825,4 +863,164 @@ class SumologicOutput < Test::Unit::TestCase
825
863
  end
826
864
  end
827
865
 
866
+ def test_resend
867
+ endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
868
+ config = %{
869
+ compress false
870
+ endpoint #{endpoint}
871
+ retry_min_interval 0s
872
+ retry_max_times 3
873
+ use_internal_retry true
874
+ }
875
+ time = event_time
876
+
877
+ driver = create_driver(config)
878
+ stub_request(:post, endpoint).to_return(
879
+ {status: 500, headers: {content_type: 'application/json'}},
880
+ {status: 200, headers: {content_type: 'application/json'}}
881
+ )
882
+ driver.run do
883
+ driver.feed("test", time, {"message": "test"})
884
+ end
885
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
886
+ body: /\A{"timestamp":\d+.,"message":"test"}\z/,
887
+ times:2
888
+ end
889
+
890
+ def test_resend_failed
891
+ endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
892
+ config = %{
893
+ compress false
894
+ endpoint #{endpoint}
895
+ retry_min_interval 0s
896
+ retry_max_times 15
897
+ use_internal_retry true
898
+ }
899
+ time = event_time
900
+
901
+ driver = create_driver(config)
902
+ stub_request(:post, endpoint).to_return(
903
+ status: 500, headers: {content_type: 'application/json'}
904
+ )
905
+ driver.run do
906
+ driver.feed("test", time, {"message": "test"})
907
+ end
908
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
909
+ body: /\A{"timestamp":\d+.,"message":"test"}\z/,
910
+ times:15
911
+ end
912
+
913
+ def test_resend_forever
914
+ endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
915
+ config = %{
916
+ compress false
917
+ endpoint #{endpoint}
918
+ retry_min_interval 0s
919
+ retry_max_times 0
920
+ retry_timeout 0s
921
+ use_internal_retry true
922
+ }
923
+ time = event_time
924
+
925
+ driver = create_driver(config)
926
+ stub_request(:post, endpoint).to_return(
927
+ *[{status: 500, headers: {content_type: 'application/json'}}]*123,
928
+ {status: 200, headers: {content_type: 'application/json'}}
929
+ )
930
+ driver.run do
931
+ driver.feed("test", time, {"message": "test"})
932
+ end
933
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
934
+ body: /\A{"timestamp":\d+.,"message":"test"}\z/,
935
+ times:124
936
+ end
937
+
938
+ def test_skip_retry
939
+ endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
940
+ config = %{
941
+ compress false
942
+ endpoint #{endpoint}
943
+ }
944
+ time = event_time
945
+
946
+ driver = create_driver(config)
947
+ stub_request(:post, endpoint).to_return(status: 500, headers: {content_type: 'application/json'})
948
+
949
+ exception = assert_raise(RuntimeError) {
950
+ driver.run do
951
+ driver.feed("test", time, {"message": "test"})
952
+ end
953
+ }
954
+ assert_equal("Failed to send data to HTTP Source. 500 - ", exception.message)
955
+ end
956
+
957
+ def test_split_negative_or_zero
958
+ endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
959
+
960
+ configs = [
961
+ %{
962
+ compress false
963
+ endpoint #{endpoint}
964
+ max_request_size -5
965
+ },
966
+ %{
967
+ compress false
968
+ endpoint #{endpoint}
969
+ max_request_size 0
970
+ }
971
+ ]
972
+
973
+ time = event_time
974
+
975
+ configs.each do |config|
976
+ WebMock.reset_executed_requests!
977
+ driver = create_driver(config)
978
+ stub_request(:post, endpoint).to_return(status: 200, headers: {content_type: 'application/json'})
979
+
980
+ driver.run do
981
+ driver.feed("test", time, {"message": "test"})
982
+ driver.feed("test", time, {"message": "test"})
983
+ driver.feed("test", time, {"message": "test"})
984
+ end
985
+
986
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
987
+ body: /\A{"timestamp":\d+.,"message":"test"}\n{"timestamp":\d+.,"message":"test"}\n{"timestamp":\d+.,"message":"test"}\z/,
988
+ times:1
989
+ end
990
+ end
991
+
992
+ def test_split
993
+ endpoint = "https://collectors.sumologic.com/v1/receivers/http/1234"
994
+
995
+ config = %{
996
+ compress false
997
+ endpoint #{endpoint}
998
+ max_request_size 80
999
+ }
1000
+
1001
+ time = event_time
1002
+
1003
+ WebMock.reset_executed_requests!
1004
+ driver = create_driver(config)
1005
+ stub_request(:post, endpoint).to_return(status: 200, headers: {content_type: 'application/json'})
1006
+
1007
+ driver.run do
1008
+ driver.feed("test", time, {"message": "test1"})
1009
+ driver.feed("test", time, {"message": "test2"})
1010
+ driver.feed("test", time, {"message": "test3"})
1011
+ driver.feed("test", time, {"message": "test4"})
1012
+ driver.feed("test", time, {"message": "test5"})
1013
+ end
1014
+
1015
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
1016
+ body: /\A{"timestamp":\d+.,"message":"test1"}\n{"timestamp":\d+.,"message":"test2"}\z/,
1017
+ times:1
1018
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
1019
+ body: /\A{"timestamp":\d+.,"message":"test3"}\n{"timestamp":\d+.,"message":"test4"}\z/,
1020
+ times:1
1021
+ assert_requested :post, "https://collectors.sumologic.com/v1/receivers/http/1234",
1022
+ body: /\A{"timestamp":\d+.,"message":"test5"}\z/,
1023
+ times:1
1024
+ end
1025
+
828
1026
  end
data/vagrant/provision.sh CHANGED
@@ -22,6 +22,5 @@ usermod -aG docker vagrant
22
22
  apt-get install -y make
23
23
 
24
24
  # install requirements for ruby
25
- snap install ruby --channel=2.6/stable --classic
26
- su vagrant -c 'gem install bundler:2.1.4'
25
+ snap install ruby --channel=3.3/stable --classic
27
26
  apt install -y gcc g++ libsnappy-dev libicu-dev zlib1g-dev cmake pkg-config libssl-dev
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-sumologic_output
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.5
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Adams
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-04-11 00:00:00.000000000 Z
12
+ date: 2024-02-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: '2'
20
+ version: '0'
21
21
  type: :development
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: '2'
27
+ version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -43,58 +43,58 @@ dependencies:
43
43
  name: test-unit
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 3.1.0
48
+ version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - "~>"
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
- version: 3.1.0
55
+ version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: codecov
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - ">="
61
61
  - !ruby/object:Gem::Version
62
- version: 0.1.10
62
+ version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - ">="
68
68
  - !ruby/object:Gem::Version
69
- version: 0.1.10
69
+ version: '0'
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: fluentd
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: 0.14.12
76
+ version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: 0.14.12
83
+ version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: httpclient
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
- version: 2.8.0
90
+ version: '0'
91
91
  type: :runtime
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - "~>"
95
+ - - ">="
96
96
  - !ruby/object:Gem::Version
97
- version: 2.8.0
97
+ version: '0'
98
98
  description: Output plugin to SumoLogic HTTP Endpoint
99
99
  email:
100
100
  - stevezau@gmail.com
@@ -104,9 +104,12 @@ extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
106
  - ".github/CODEOWNERS"
107
+ - ".github/workflows/publish.yaml"
108
+ - ".github/workflows/pull_request.yaml"
107
109
  - ".gitignore"
108
110
  - ".travis.yml"
109
111
  - CHANGELOG.md
112
+ - CONTRIBUTING.md
110
113
  - Gemfile
111
114
  - LICENSE
112
115
  - README.md
@@ -131,14 +134,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
134
  requirements:
132
135
  - - ">="
133
136
  - !ruby/object:Gem::Version
134
- version: 2.0.0
137
+ version: '0'
135
138
  required_rubygems_version: !ruby/object:Gem::Requirement
136
139
  requirements:
137
140
  - - ">="
138
141
  - !ruby/object:Gem::Version
139
142
  version: '0'
140
143
  requirements: []
141
- rubygems_version: 3.0.8
144
+ rubygems_version: 3.1.2
142
145
  signing_key:
143
146
  specification_version: 4
144
147
  summary: Output plugin to SumoLogic HTTP Endpoint