fluent-plugin-splunk-hec 1.2.4 → 1.2.8

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: 057e56b761d497efa241a04003ffabe88f22c52f04eb7388538044c829548736
4
- data.tar.gz: 50a5bcbed257411be793337e52ce45b49c723782134b4ff9000e74af28c59965
3
+ metadata.gz: 3404443a78707ec84c807cc959de100eefec4c7144f76b4587fa4c02580d300d
4
+ data.tar.gz: '098eb708f6093e40c59aa597c7f185403f9fb195c03758a726ebd8bcc2fc4468'
5
5
  SHA512:
6
- metadata.gz: e036e50f81d0f607145b57111031fcee43072915c4619c98d33126df237e3c4afbfde859d7babfd94bdddc849c09d881d0383fc7863688f4db7f0f2e8c5e7cfd
7
- data.tar.gz: 78246497f0735f9b54d80cce7b19831d75c623c31a90adfd8a717dc4a9a347f9b2288202566532d89c5b0526c2b04e1e34041fdce5e0de9cc790ac8d67b27a02
6
+ metadata.gz: b7dc521fe94e36ae9e4df51f5a32c936615228a164f76ec9391bd72033aa06d35e8292d8cc95b6025cf880943e56f48c2bebbbc5a9e606e219972528a464c9a3
7
+ data.tar.gz: 4d6ae8221544453debf6e0dbf1ecbdb9a0774f36ae3d1e4715781ca078a2c0d3ebd2870455ffcd75bdb292d1634a8e71d6034f620c69638d51372f010cac4d46
data/Gemfile.lock CHANGED
@@ -1,62 +1,62 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-splunk-hec (1.2.4)
4
+ fluent-plugin-splunk-hec (1.2.8)
5
5
  fluentd (>= 1.4)
6
6
  multi_json (~> 1.13)
7
7
  net-http-persistent (~> 3.1)
8
8
  openid_connect (~> 1.1.8)
9
- prometheus-client (< 0.10.0)
9
+ prometheus-client (>= 2.1.0)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activemodel (5.2.4.3)
15
- activesupport (= 5.2.4.3)
16
- activesupport (5.2.4.3)
14
+ activemodel (6.1.4.1)
15
+ activesupport (= 6.1.4.1)
16
+ activesupport (6.1.4.1)
17
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
- i18n (>= 0.7, < 2)
19
- minitest (~> 5.1)
20
- tzinfo (~> 1.1)
21
- addressable (2.7.0)
18
+ i18n (>= 1.6, < 2)
19
+ minitest (>= 5.1)
20
+ tzinfo (~> 2.0)
21
+ zeitwerk (~> 2.3)
22
+ addressable (2.8.0)
22
23
  public_suffix (>= 2.0.2, < 5.0)
23
- aes_key_wrap (1.0.1)
24
- ast (2.4.0)
24
+ aes_key_wrap (1.1.0)
25
25
  attr_required (1.0.1)
26
- bindata (2.4.4)
27
- concurrent-ruby (1.1.6)
28
- connection_pool (2.2.2)
29
- cool.io (1.6.0)
30
- crack (0.4.3)
31
- safe_yaml (~> 1.0.0)
32
- docile (1.3.2)
33
- fluentd (1.9.2)
26
+ bindata (2.4.10)
27
+ concurrent-ruby (1.1.9)
28
+ connection_pool (2.2.5)
29
+ cool.io (1.7.1)
30
+ crack (0.4.5)
31
+ rexml
32
+ docile (1.4.0)
33
+ fluentd (1.14.2)
34
+ bundler
34
35
  cool.io (>= 1.4.5, < 2.0.0)
35
- http_parser.rb (>= 0.5.1, < 0.7.0)
36
+ http_parser.rb (>= 0.5.1, < 0.8.0)
36
37
  msgpack (>= 1.3.1, < 2.0.0)
37
- serverengine (>= 2.0.4, < 3.0.0)
38
+ serverengine (>= 2.2.2, < 3.0.0)
38
39
  sigdump (~> 0.2.2)
39
- strptime (>= 0.2.2, < 1.0.0)
40
+ strptime (>= 0.2.4, < 1.0.0)
40
41
  tzinfo (>= 1.0, < 3.0)
41
42
  tzinfo-data (~> 1.0)
43
+ webrick (>= 1.4.2, < 1.8.0)
42
44
  yajl-ruby (~> 1.0)
43
- hashdiff (1.0.0)
44
- http_parser.rb (0.5.3)
45
+ hashdiff (1.0.1)
46
+ http_parser.rb (0.7.0)
45
47
  httpclient (2.8.3)
46
- i18n (1.8.2)
48
+ i18n (1.8.11)
47
49
  concurrent-ruby (~> 1.0)
48
- jaro_winkler (1.5.4)
49
- json (2.3.0)
50
- json-jwt (1.11.0)
50
+ json-jwt (1.13.0)
51
51
  activesupport (>= 4.2)
52
52
  aes_key_wrap
53
53
  bindata
54
54
  mail (2.7.1)
55
55
  mini_mime (>= 0.1.1)
56
- mini_mime (1.0.2)
57
- minitest (5.14.0)
58
- msgpack (1.3.3)
59
- multi_json (1.14.1)
56
+ mini_mime (1.1.2)
57
+ minitest (5.14.4)
58
+ msgpack (1.4.2)
59
+ multi_json (1.15.0)
60
60
  net-http-persistent (3.1.0)
61
61
  connection_pool (~> 2.2)
62
62
  openid_connect (1.1.8)
@@ -69,69 +69,54 @@ GEM
69
69
  validate_email
70
70
  validate_url
71
71
  webfinger (>= 1.0.1)
72
- parallel (1.19.1)
73
- parser (2.7.0.2)
74
- ast (~> 2.4.0)
75
- power_assert (1.1.5)
76
- powerpack (0.1.2)
77
- prometheus-client (0.9.0)
78
- quantile (~> 0.2.1)
79
- public_suffix (4.0.3)
80
- quantile (0.2.1)
72
+ power_assert (2.0.1)
73
+ prometheus-client (2.1.0)
74
+ public_suffix (4.0.6)
81
75
  rack (2.2.3)
82
- rack-oauth2 (1.10.1)
76
+ rack-oauth2 (1.19.0)
83
77
  activesupport
84
78
  attr_required
85
79
  httpclient
86
80
  json-jwt (>= 1.11.0)
87
- rack
88
- rainbow (3.0.0)
89
- rake (12.3.3)
90
- rubocop (0.63.1)
91
- jaro_winkler (~> 1.5.1)
92
- parallel (~> 1.10)
93
- parser (>= 2.5, != 2.5.1.1)
94
- powerpack (~> 0.1)
95
- rainbow (>= 2.2.2, < 4.0)
96
- ruby-progressbar (~> 1.7)
97
- unicode-display_width (~> 1.4.0)
98
- ruby-progressbar (1.10.1)
99
- safe_yaml (1.0.5)
100
- serverengine (2.2.1)
81
+ rack (>= 2.1.0)
82
+ rake (13.0.6)
83
+ rexml (3.2.5)
84
+ serverengine (2.2.4)
101
85
  sigdump (~> 0.2.2)
102
86
  sigdump (0.2.4)
103
- simplecov (0.16.1)
87
+ simplecov (0.21.2)
104
88
  docile (~> 1.1)
105
- json (>= 1.8, < 3)
106
- simplecov-html (~> 0.10.0)
107
- simplecov-html (0.10.2)
108
- strptime (0.2.3)
109
- swd (1.1.2)
89
+ simplecov-html (~> 0.11)
90
+ simplecov_json_formatter (~> 0.1)
91
+ simplecov-html (0.12.3)
92
+ simplecov_json_formatter (0.1.3)
93
+ strptime (0.2.5)
94
+ swd (1.3.0)
110
95
  activesupport (>= 3)
111
96
  attr_required (>= 0.0.5)
112
97
  httpclient (>= 2.4)
113
- test-unit (3.3.5)
98
+ test-unit (3.5.0)
114
99
  power_assert
115
- thread_safe (0.3.6)
116
- tzinfo (1.2.6)
117
- thread_safe (~> 0.1)
118
- tzinfo-data (1.2019.3)
100
+ tzinfo (2.0.4)
101
+ concurrent-ruby (~> 1.0)
102
+ tzinfo-data (1.2021.5)
119
103
  tzinfo (>= 1.0.0)
120
- unicode-display_width (1.4.1)
121
104
  validate_email (0.1.6)
122
105
  activemodel (>= 3.0)
123
106
  mail (>= 2.2.5)
124
- validate_url (1.0.8)
107
+ validate_url (1.0.13)
125
108
  activemodel (>= 3.0.0)
126
109
  public_suffix
127
- webfinger (1.1.0)
110
+ webfinger (1.2.0)
128
111
  activesupport
129
112
  httpclient (>= 2.4)
130
113
  webmock (3.5.1)
131
114
  addressable (>= 2.3.6)
132
115
  crack (>= 0.3.2)
133
116
  hashdiff
117
+ webrick (1.7.0)
134
118
  yajl-ruby (1.4.1)
119
+ zeitwerk (2.5.1)
135
120
 
136
121
  PLATFORMS
137
122
  ruby
@@ -141,10 +126,9 @@ DEPENDENCIES
141
126
  fluent-plugin-splunk-hec!
142
127
  minitest (~> 5.0)
143
128
  rake (>= 12.0)
144
- rubocop (~> 0.63.1)
145
129
  simplecov
146
130
  test-unit (~> 3.0)
147
131
  webmock (~> 3.5.0)
148
132
 
149
133
  BUNDLED WITH
150
- 2.1.4
134
+ 2.2.30
data/LICENSE CHANGED
@@ -270,7 +270,6 @@ The following components are provided under the MIT License. See project link fo
270
270
  (MIT License) rake (https://github.com/ruby/rake/blob/master/MIT-LICENSE)
271
271
  (MIT License) recursive-open-struct (https://github.com/aetherknight/recursive-open-struct/blob/master/LICENSE.txt)
272
272
  (MIT License) rest-client (https://github.com/rest-client/rest-client/blob/master/LICENSE)
273
- (MIT License) rubocop (https://github.com/rubocop-hq/rubocop/blob/master/LICENSE.txt)
274
273
  (MIT License) ruby-progressbar (https://github.com/jfelchner/ruby-progressbar/blob/master/LICENSE.txt)
275
274
  (MIT License) safe_yaml (https://github.com/dtao/safe_yaml/blob/master/LICENSE.txt)
276
275
  (MIT License) sigdump (https://github.com/frsyuki/sigdump/blob/master/LICENSE)
data/README.md CHANGED
@@ -1,4 +1,3 @@
1
- [![CircleCI](https://circleci.com/gh/git-lfs/git-lfs.svg?style=shield&circle-token=856152c2b02bfd236f54d21e1f581f3e4ebf47ad)](https://circleci.com/gh/splunk/fluent-plugin-splunk-hec)
2
1
  # fluent-plugin-splunk-hec
3
2
 
4
3
  [Fluentd](https://fluentd.org/) output plugin to send events and metrics to [Splunk](https://www.splunk.com) in 2 modes:<br/>
@@ -260,6 +259,10 @@ Cannot set both `source` and `source_key` parameters at the same time.
260
259
 
261
260
  Field name that contains the sourcetype. Cannot set both `source` and `source_key` parameters at the same time.
262
261
 
262
+ ### time_key (string) (optional)
263
+
264
+ Field name to contain Splunk event time. By default will use fluentd\'d time.
265
+
263
266
  ### fields (init) (optional)
264
267
 
265
268
  Lets you specify the index-time fields for the event data type, or metric dimensions for the metric data type. Null value fields are removed.
@@ -293,7 +296,7 @@ In this case, parameters inside `<fields>` are used as indexed fields and remove
293
296
  <fields>
294
297
  file
295
298
  level
296
- app applicatioin
299
+ app application
297
300
  </fields>
298
301
  </match>
299
302
  ```
@@ -340,7 +343,7 @@ For metrics, parameters inside `<fields>` are used as dimensions. If `<fields>`
340
343
  <fields>
341
344
  file
342
345
  level
343
- app applicatioin
346
+ app application
344
347
  </fields>
345
348
  </match>
346
349
  ```
@@ -432,6 +435,14 @@ List of SSl ciphers allowed.
432
435
 
433
436
  Specifies whether an insecure SSL connection is allowed. If set to false, Splunk does not verify an insecure server certificate. This parameter is set to `false` by default. Ensure parameter `ca_file` is not configured in order to allow insecure SSL connections when this value is set to `true`.
434
437
 
438
+ #### require_ssl_min_version (bool)
439
+
440
+ When set to true, TLS version 1.1 and above is required.
441
+
442
+ #### consume_chunk_on_4xx_errors (bool)
443
+
444
+ Specifies whether any 4xx HTTP response status code consumes the buffer chunks. If set to false, Splunk will fail to flush the buffer on such status codes. This parameter is set to `true` by default for backwards compatibility.
445
+
435
446
  ## About Buffer
436
447
 
437
448
  This plugin sends events to HEC using [batch mode](https://docs.splunk.com/Documentation/Splunk/7.1.0/Data/FormateventsforHTTPEventCollector#Event_data).
data/Rakefile CHANGED
@@ -2,9 +2,6 @@
2
2
 
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rake/testtask'
5
- require 'rubocop/rake_task'
6
-
7
- RuboCop::RakeTask.new
8
5
 
9
6
  Rake::TestTask.new(:test) do |t|
10
7
  t.libs << 'test'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.4
1
+ 1.2.8
@@ -37,13 +37,12 @@ Gem::Specification.new do |spec|
37
37
  spec.add_runtime_dependency 'multi_json', '~> 1.13'
38
38
  spec.add_runtime_dependency 'net-http-persistent', '~> 3.1'
39
39
  spec.add_runtime_dependency 'openid_connect', '~> 1.1.8'
40
- spec.add_runtime_dependency 'prometheus-client', '< 0.10.0'
40
+ spec.add_runtime_dependency 'prometheus-client', '>= 2.1.0'
41
41
 
42
42
  spec.add_development_dependency 'bundler', '~> 2.0'
43
43
  spec.add_development_dependency 'rake', '>= 12.0'
44
44
  # required by fluent/test.rb
45
45
  spec.add_development_dependency 'minitest', '~> 5.0'
46
- spec.add_development_dependency 'rubocop', '~> 0.63.1'
47
46
  spec.add_development_dependency 'simplecov', '~> 0.16.1'
48
47
  spec.add_development_dependency 'test-unit', '~> 3.0'
49
48
  spec.add_development_dependency 'webmock', '~> 3.5.0'
@@ -13,7 +13,7 @@ module Fluent::Plugin
13
13
  autoload :VERSION, 'fluent/plugin/out_splunk/version'
14
14
  autoload :MatchFormatter, 'fluent/plugin/out_splunk/match_formatter'
15
15
 
16
- KEY_FIELDS = %w[index host source sourcetype metric_name metric_value].freeze
16
+ KEY_FIELDS = %w[index host source sourcetype metric_name metric_value time].freeze
17
17
  TAG_PLACEHOLDER = '${tag}'
18
18
 
19
19
  desc 'The host field for events, by default it uses the hostname of the machine that runnning fluentd. This is exclusive with `host_key`.'
@@ -51,6 +51,9 @@ module Fluent::Plugin
51
51
  # this is blank on purpose
52
52
  end
53
53
 
54
+ desc 'Indicates if 4xx errors should consume chunk'
55
+ config_param :consume_chunk_on_4xx_errors, :bool, :default => true
56
+
54
57
  config_section :format do
55
58
  config_set_default :usage, '**'
56
59
  config_set_default :@type, 'json'
@@ -97,11 +100,11 @@ module Fluent::Plugin
97
100
  write_to_splunk(chunk)
98
101
  end
99
102
 
100
- @metrics[:record_counter].increment(metric_labels, chunk.size_of_events)
101
- @metrics[:bytes_counter].increment(metric_labels, chunk.bytesize)
102
- @metrics[:write_records_histogram].observe(metric_labels, chunk.size_of_events)
103
- @metrics[:write_bytes_histogram].observe(metric_labels, chunk.bytesize)
104
- @metrics[:write_latency_histogram].observe(metric_labels, t)
103
+ @metrics[:record_counter].increment(labels: metric_labels, by: chunk.size_of_events)
104
+ @metrics[:bytes_counter].increment(labels: metric_labels, by: chunk.bytesize)
105
+ @metrics[:write_records_histogram].observe(chunk.size_of_events, labels: metric_labels)
106
+ @metrics[:write_bytes_histogram].observe(chunk.bytesize, labels: metric_labels, )
107
+ @metrics[:write_latency_histogram].observe(t, labels: metric_labels, )
105
108
  end
106
109
 
107
110
  def write_to_splunk(_chunk)
@@ -150,13 +153,14 @@ module Fluent::Plugin
150
153
  def process_response(response, _request_body)
151
154
  log.trace { "[Response] POST #{@api}: #{response.inspect}" }
152
155
 
153
- @metrics[:status_counter].increment(metric_labels(status: response.code.to_s))
156
+ @metrics[:status_counter].increment(labels: metric_labels(status: response.code.to_s))
157
+
158
+ raise_err = response.code.to_s.start_with?('5') || (!@consume_chunk_on_4xx_errors && response.code.to_s.start_with?('4'))
154
159
 
155
160
  # raise Exception to utilize Fluentd output plugin retry mechanism
156
- raise "Server error (#{response.code}) for POST #{@api}, response: #{response.body}" if response.code.to_s.start_with?('5')
161
+ raise "Server error (#{response.code}) for POST #{@api}, response: #{response.body}" if raise_err
157
162
 
158
- # For both success response (2xx) and client errors (4xx), we will consume the chunk.
159
- # Because there probably a bug in the code if we get 4xx errors, retry won't do any good.
163
+ # For both success response (2xx) we will consume the chunk.
160
164
  unless response.code.to_s.start_with?('2')
161
165
  log.error "#{self.class}: Failed POST to #{@api}, response: #{response.body}"
162
166
  log.error { "#{self.class}: Failed request body: #{post.body}" }
@@ -205,7 +209,7 @@ module Fluent::Plugin
205
209
  # This loop looks dump, but it is used to suppress the unused parameter configuration warning
206
210
  # Learned from `filter_record_transformer`.
207
211
  conf.elements.select { |element| element.name == 'fields' }.each do |element|
208
- element.each_pair { |k, _v| element.key?(k) }
212
+ element.each_pair { |k, _v| element.has_key?(k) }
209
213
  end
210
214
 
211
215
  return unless @fields
@@ -231,28 +235,34 @@ module Fluent::Plugin
231
235
 
232
236
  @metrics = {
233
237
  record_counter: register_metric(::Prometheus::Client::Counter.new(
234
- :splunk_output_write_records_count,
235
- 'The number of log records being sent'
238
+ :splunk_output_write_records_count, docstring:
239
+ 'The number of log records being sent',
240
+ labels: metric_label_keys
236
241
  )),
237
242
  bytes_counter: register_metric(::Prometheus::Client::Counter.new(
238
- :splunk_output_write_bytes_count,
239
- 'The number of log bytes being sent'
243
+ :splunk_output_write_bytes_count, docstring:
244
+ 'The number of log bytes being sent',
245
+ labels: metric_label_keys
240
246
  )),
241
247
  status_counter: register_metric(::Prometheus::Client::Counter.new(
242
- :splunk_output_write_status_count,
243
- 'The count of sends by response_code'
248
+ :splunk_output_write_status_count, docstring:
249
+ 'The count of sends by response_code',
250
+ labels: metric_label_keys(status: "")
244
251
  )),
245
252
  write_bytes_histogram: register_metric(::Prometheus::Client::Histogram.new(
246
- :splunk_output_write_payload_bytes,
247
- 'The size of the write payload in bytes', {}, [1024, 23_937, 47_875, 95_750, 191_500, 383_000, 766_000, 1_149_000]
253
+ :splunk_output_write_payload_bytes, docstring:
254
+ 'The size of the write payload in bytes', buckets: [1024, 23_937, 47_875, 95_750, 191_500, 383_000, 766_000, 1_149_000],
255
+ labels: metric_label_keys
248
256
  )),
249
257
  write_records_histogram: register_metric(::Prometheus::Client::Histogram.new(
250
- :splunk_output_write_payload_records,
251
- 'The number of records written per write', {}, [1, 10, 25, 100, 200, 300, 500, 750, 1000, 1500]
258
+ :splunk_output_write_payload_records, docstring:
259
+ 'The number of records written per write', buckets: [1, 10, 25, 100, 200, 300, 500, 750, 1000, 1500],
260
+ labels: metric_label_keys
252
261
  )),
253
262
  write_latency_histogram: register_metric(::Prometheus::Client::Histogram.new(
254
- :splunk_output_write_latency_seconds,
255
- 'The latency of writes'
263
+ :splunk_output_write_latency_seconds, docstring:
264
+ 'The latency of writes',
265
+ labels: metric_label_keys
256
266
  ))
257
267
  }
258
268
  end
@@ -262,6 +272,10 @@ module Fluent::Plugin
262
272
  @metric_labels.merge other_labels
263
273
  end
264
274
 
275
+ def metric_label_keys(other_labels = {})
276
+ (@metric_labels.merge other_labels).keys
277
+ end
278
+
265
279
  # Encode as UTF-8. If 'coerce_to_utf8' is set to true in the config, any
266
280
  # non-UTF-8 character would be replaced by the string specified by
267
281
  # 'non_utf8_replacement_string'. If 'coerce_to_utf8' is set to false, any
@@ -63,6 +63,9 @@ module Fluent::Plugin
63
63
  desc 'List of SSL ciphers allowed.'
64
64
  config_param :ssl_ciphers, :array, default: nil
65
65
 
66
+ desc 'When set to true, TLS version 1.1 and above is required.'
67
+ config_param :require_ssl_min_version, :bool, default: true
68
+
66
69
  desc 'Indicates if insecure SSL connection is allowed.'
67
70
  config_param :insecure_ssl, :bool, default: false
68
71
 
@@ -97,7 +100,10 @@ module Fluent::Plugin
97
100
  config_section :fields, init: false, multi: false, required: false do
98
101
  # this is blank on purpose
99
102
  end
100
-
103
+
104
+ desc 'Indicates if 4xx errors should consume chunk'
105
+ config_param :consume_chunk_on_4xx_errors, :bool, :default => true
106
+
101
107
  config_section :format do
102
108
  config_set_default :usage, '**'
103
109
  config_set_default :@type, 'json'
@@ -140,6 +146,8 @@ module Fluent::Plugin
140
146
  c.ca_file = @ca_file
141
147
  c.ca_path = @ca_path
142
148
  c.ciphers = @ssl_ciphers
149
+ c.proxy = :ENV
150
+ c.min_version = OpenSSL::SSL::TLS1_1_VERSION if @require_ssl_min_version
143
151
 
144
152
  c.override_headers['Content-Type'] = 'application/json'
145
153
  c.override_headers['User-Agent'] = "fluent-plugin-splunk_hec_out/#{VERSION}"
@@ -179,7 +187,7 @@ module Fluent::Plugin
179
187
  end
180
188
 
181
189
  def format_event(tag, time, record)
182
- MultiJson.dump({
190
+ d = {
183
191
  host: @host ? @host.(tag, record) : @default_host,
184
192
  # From the API reference
185
193
  # http://docs.splunk.com/Documentation/Splunk/latest/RESTREF/RESTinput#services.2Fcollector
@@ -212,7 +220,12 @@ module Fluent::Plugin
212
220
  record = formatter.format(tag, time, record)
213
221
  end
214
222
  payload[:event] = convert_to_utf8 record
215
- })
223
+ }
224
+ if d[:event] == "{}"
225
+ log.warn { "Event after formatting was blank, not sending" }
226
+ return ""
227
+ end
228
+ MultiJson.dump(d)
216
229
  end
217
230
 
218
231
  def format_metric(tag, time, record)
@@ -224,7 +237,7 @@ module Fluent::Plugin
224
237
  # That's why we use `to_s` here.
225
238
  time: time.to_f.to_s,
226
239
  event: 'metric'
227
- }.tap do |payload|
240
+ }.tap do |payload|
228
241
  if @time
229
242
  time_value = @time.(tag, record)
230
243
  # if no value is found don't override and use fluentd's time
@@ -279,9 +292,11 @@ module Fluent::Plugin
279
292
  c.ca_file = @ca_file
280
293
  c.ca_path = @ca_path
281
294
  c.ciphers = @ssl_ciphers
295
+ c.proxy = :ENV
282
296
  c.idle_timeout = @idle_timeout
283
297
  c.read_timeout = @read_timeout
284
298
  c.open_timeout = @open_timeout
299
+ c.min_version = OpenSSL::SSL::TLS1_1_VERSION if @require_ssl_min_version
285
300
 
286
301
  c.override_headers['Content-Type'] = 'application/json'
287
302
  c.override_headers['User-Agent'] = "fluent-plugin-splunk_hec_out/#{VERSION}"
@@ -302,11 +317,12 @@ module Fluent::Plugin
302
317
  response = @conn.request @api, post
303
318
  t2 = Time.now
304
319
 
305
- # raise Exception to utilize Fluentd output plugin retry machanism
306
- raise "Server error (#{response.code}) for POST #{@api}, response: #{response.body}" if response.code.start_with?('5')
320
+ raise_err = response.code.to_s.start_with?('5') || (!@consume_chunk_on_4xx_errors && response.code.to_s.start_with?('4'))
321
+
322
+ # raise Exception to utilize Fluentd output plugin retry mechanism
323
+ raise "Server error (#{response.code}) for POST #{@api}, response: #{response.body}" if raise_err
307
324
 
308
- # For both success response (2xx) and client errors (4xx), we will consume the chunk.
309
- # Because there probably a bug in the code if we get 4xx errors, retry won't do any good.
325
+ # For both success response (2xx) we will consume the chunk.
310
326
  if not response.code.start_with?('2')
311
327
  log.error "Failed POST to #{@api}, response: #{response.body}"
312
328
  log.debug { "Failed request body: #{post.body}" }
@@ -340,7 +356,7 @@ module Fluent::Plugin
340
356
  invalid: :replace,
341
357
  undef: :replace,
342
358
  replace: @non_utf8_replacement_string)
343
- else
359
+ else
344
360
  begin
345
361
  input.encode('utf-8')
346
362
  rescue EncodingError
@@ -57,6 +57,9 @@ describe Fluent::Plugin::SplunkHecOutput do
57
57
  assert_nil(create_hec_output_driver('hec_host hec_token').instance.index_key)
58
58
  expect(create_hec_output_driver('hec_host hec_token').instance.index_key).is_a? String
59
59
  end
60
+ it 'should consume chunks on 4xx errors' do
61
+ expect(create_hec_output_driver('hec_host hec_token').instance.consume_chunk_on_4xx_errors).must_equal true
62
+ end
60
63
  end
61
64
 
62
65
  describe 'hec_host validation' do
@@ -139,6 +142,7 @@ describe Fluent::Plugin::SplunkHecOutput do
139
142
  host_key from
140
143
  source_key file
141
144
  sourcetype_key agent.name
145
+ time_key timestamp
142
146
  CONF
143
147
  batch.each do |item|
144
148
  expect(item['index']).must_equal 'info'
@@ -147,7 +151,7 @@ describe Fluent::Plugin::SplunkHecOutput do
147
151
  expect(item['sourcetype']).must_equal 'test'
148
152
 
149
153
  JSON.load(item['event']).tap do |event|
150
- %w[level from file].each { |field| expect(event).wont_include field }
154
+ %w[level from file timestamp].each { |field| expect(event).wont_include field }
151
155
  expect(event['agent']).wont_include 'name'
152
156
  end
153
157
  end
@@ -220,6 +224,24 @@ describe Fluent::Plugin::SplunkHecOutput do
220
224
  end
221
225
  end
222
226
 
227
+ it 'should not send blank events' do
228
+ verify_sent_events(<<~CONF) do |batch|
229
+ <fields>
230
+ from
231
+ logLevel level
232
+ nonexist
233
+ log
234
+ file
235
+ value
236
+ id
237
+ agent
238
+ timestamp
239
+ </fields>
240
+ CONF
241
+ expect(batch.length).must_equal 0
242
+ end
243
+ end
244
+
223
245
  describe 'metric' do
224
246
  it 'should check related configs' do
225
247
  expect(
@@ -349,7 +371,8 @@ describe Fluent::Plugin::SplunkHecOutput do
349
371
  'agent' => {
350
372
  'name' => 'test',
351
373
  'version' => '1.0.0'
352
- }
374
+ },
375
+ 'timestamp' => 'time'
353
376
  }
354
377
  events = [
355
378
  ['tag.event1', event_time, { 'id' => '1st' }.merge(Marshal.load(Marshal.dump(event)))],
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-splunk-hec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Splunk Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-06 00:00:00.000000000 Z
11
+ date: 2021-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: prometheus-client
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "<"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: 0.10.0
75
+ version: 2.1.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "<"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: 0.10.0
82
+ version: 2.1.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: bundler
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -122,20 +122,6 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '5.0'
125
- - !ruby/object:Gem::Dependency
126
- name: rubocop
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: 0.63.1
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: 0.63.1
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: simplecov
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -230,18 +216,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
216
  - !ruby/object:Gem::Version
231
217
  version: '0'
232
218
  requirements: []
233
- rubygems_version: 3.0.6
219
+ rubygems_version: 3.1.4
234
220
  signing_key:
235
221
  specification_version: 4
236
222
  summary: Fluentd plugin for Splunk HEC.
237
223
  test_files:
224
+ - test/test_helper.rb
238
225
  - test/fluent/plugin/out_splunk_hec_test.rb
239
226
  - test/fluent/plugin/out_splunk_ingest_api_test.rb
240
- - test/lib/webmock/http_lib_adapters/patron_adapter.rb
241
- - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
242
- - test/lib/webmock/http_lib_adapters/em_http_request_adapter.rb
243
- - test/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
244
227
  - test/lib/webmock/http_lib_adapters/curb_adapter.rb
228
+ - test/lib/webmock/http_lib_adapters/em_http_request_adapter.rb
245
229
  - test/lib/webmock/http_lib_adapters/http_rb_adapter.rb
230
+ - test/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
231
+ - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
246
232
  - test/lib/webmock/http_lib_adapters/excon_adapter.rb
247
- - test/test_helper.rb
233
+ - test/lib/webmock/http_lib_adapters/patron_adapter.rb