fluent-plugin-input-opensearch 1.1.9 → 1.2.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: 52ccf524b6427d6a8191410da0ed878ed988ac91881ad741d1b9464356ebdb0a
4
- data.tar.gz: 0da3d50a8c427537fd307fabc5400775d4c26bb0e8eda131fd7eb4b89174c249
3
+ metadata.gz: 0bf5409e93f99297d1e0f3474d8534eecd62315fbbafa8c0e3085ee7108d8daa
4
+ data.tar.gz: bbf84fc1ce4485450b57a264c5f9517cc2465191e4755bc972f0b315fc3df809
5
5
  SHA512:
6
- metadata.gz: 849df809ddd94adc13b5a66ee21302c9fa59e7a4bf732678c15ca0a8acbb2d2e57e52c54f03f76a4537e2a363b5f6eb1a13ebc41a741dfc625ef12b5ce449641
7
- data.tar.gz: 7b4172bfa6cdeb847e8a595f64086d2f26171aca71ed762acc3f746d5af1be19e5b06df400118a9bd35ed57e73d0ad8460871b8b1244571cd252a4345b5a1a60
6
+ metadata.gz: a17efc75fc7dd5979dbf85d26af0ba6a6b770865f1b2c2de9110265ebfa9c3538da8353f3c6d7d98ba7248e3c722c404a3d58ae93972ae268bb3db32c1b3f745
7
+ data.tar.gz: 75ac7e8e7385f19e2f57aa5b7cda3134cb073de9d421f3dfdfe9f2db118f94ec8b8fe9fac03a24a22936d8fb40513c844a1a85b3cb827a7b7bff6f925a9f84b5
@@ -24,7 +24,16 @@
24
24
  + [docinfo_fields](#docinfo_fields)
25
25
  + [docinfo_target](#docinfo_target)
26
26
  + [docinfo](#docinfo)
27
- + [infinite_check_connection](#infinite_check_connection)
27
+ + [check_connection](#check_connection)
28
+ + [retry_forever](#retry_forever)
29
+ + [retry_timeout](#retry_timeout)
30
+ + [retry_max_times](#retry_max_times)
31
+ + [retry_type](#retry_type)
32
+ + [retry_wait](#retry_wait)
33
+ + [retry_exponential_backoff_base](#retry_exponential_backoff_base)
34
+ + [retry_max_interval](#retry_max_interval)
35
+ + [retry_randomize](#retry_randomize)
36
+
28
37
  * [Advanced Usage](#advanced-usage)
29
38
 
30
39
  ## Usage
@@ -275,14 +284,87 @@ This parameter specifies whether docinfo information including or not. The defau
275
284
  docinfo false
276
285
  ```
277
286
 
278
- ### infinite_check_connection
287
+ ### check_connection
288
+
289
+ The parameter for checking on connection availability with Elasticsearch or Opensearch hosts. The default value is `true`.
290
+
291
+ ```
292
+ check_connection true
293
+ ```
294
+ ### retry_forever
295
+
296
+ The parameter If true, plugin will ignore retry_timeout and retry_max_times options and retry forever. The default value is `true`.
297
+
298
+ ```
299
+ retry_forever true
300
+ ```
301
+
302
+ ### retry_timeout
303
+
304
+ The parameter maximum time (seconds) to retry again the failed try, until the plugin discards the retry.
305
+ If the next retry is going to exceed this time limit, the last retry will be made at exactly this time limit..
306
+ The default value is `72h`.
307
+ 72hours == 17 times with exponential backoff (not to change default behavior)
308
+
309
+ ```
310
+ retry_timeout 72 * 60 * 60
311
+ ```
312
+
313
+ ### retry_max_times
314
+
315
+ The parameter maximum number of times to retry the failed try. The default value is `5`
316
+
317
+ ```
318
+ retry_max_times 5
319
+ ```
320
+
321
+ ### retry_type
279
322
 
280
- The parameter infinite checking on connection availability with Elasticsearch or opensearch hosts, every request_timeout (default 5) seconds. The default value is `true,`. But if value is `false` then checking of connection will be only 3 times
323
+ The parameter needs for how long need to wait (time in seconds) to retry again:
324
+ `exponential_backoff`: wait in seconds will become large exponentially per failure,
325
+ `periodic`: plugin will retry periodically with fixed intervals (configured via retry_wait). The default value is `:exponential_backoff`
326
+ Periodic -> fixed :retry_wait
327
+ Exponential backoff: k is number of retry times
328
+ c: constant factor, @retry_wait
329
+ b: base factor, @retry_exponential_backoff_base
330
+ k: times
331
+ total retry time: c + c * b^1 + (...) + c*b^k = c*b^(k+1) - 1
281
332
 
282
333
  ```
283
- infinite_check_connection true
334
+ retry_type exponential_backoff
284
335
  ```
285
336
 
337
+ ### retry_wait
338
+
339
+ The parameter needs for wait in seconds before the next retry to again or constant factor of exponential backoff. The default value is `5`
340
+
341
+ ```
342
+ retry_wait 5
343
+ ```
344
+
345
+ ### retry_exponential_backoff_base
346
+
347
+ The parameter The base number of exponential backoff for retries. The default value is `2`
348
+
349
+ ```
350
+ retry_exponential_backoff_base 2
351
+ ```
352
+
353
+ ### retry_max_interval
354
+
355
+ The parameter maximum interval (seconds) for exponential backoff between retries while failing. The default value is `nil`
356
+
357
+ ```
358
+ retry_max_interval nil
359
+ ```
360
+
361
+ ### retry_randomize
362
+
363
+ The parameter If true, the plugin will retry after randomized interval not to do burst retries. The default value is `false`
364
+
365
+ ```
366
+ retry_randomize false
367
+ ```
286
368
 
287
369
  ## Advanced Usage
288
370
 
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'fluent-plugin-input-opensearch'
6
- s.version = '1.1.9'
6
+ s.version = '1.2.0'
7
7
  s.authors = ['imcotop']
8
8
  s.email = ['imcotop@icloud.com']
9
9
  s.description = %q{Opensearch output plugin for Fluent event collector}
@@ -29,6 +29,7 @@ require 'opensearch'
29
29
  require 'faraday/excon'
30
30
  require 'fluent/log-ext'
31
31
  require 'fluent/plugin/input'
32
+ require 'fluent/plugin_helper'
32
33
  require_relative 'opensearch_constants'
33
34
 
34
35
  module Fluent::Plugin
@@ -39,7 +40,7 @@ module Fluent::Plugin
39
40
  DEFAULT_STORAGE_TYPE = 'local'
40
41
  METADATA = "@metadata".freeze
41
42
 
42
- helpers :timer, :thread
43
+ helpers :timer, :thread, :retry_state
43
44
 
44
45
  Fluent::Plugin.register_input('opensearch', self)
45
46
 
@@ -80,7 +81,23 @@ module Fluent::Plugin
80
81
  config_param :docinfo_fields, :array, :default => ['_index', '_type', '_id']
81
82
  config_param :docinfo_target, :string, :default => METADATA
82
83
  config_param :docinfo, :bool, :default => false
83
- config_param :infinite_check_connection, :bool, :default => true
84
+ config_param :check_connection, :bool, :default => true
85
+ config_param :retry_forever, :bool, default: true, desc: 'If true, plugin will ignore retry_timeout and retry_max_times options and retry forever.'
86
+ config_param :retry_timeout, :time, default: 72 * 60 * 60, desc: 'The maximum seconds to retry'
87
+ # 72hours == 17 times with exponential backoff (not to change default behavior)
88
+ config_param :retry_max_times, :integer, default: 5, desc: 'The maximum number of times to retry'
89
+ # exponential backoff sequence will be initialized at the time of this threshold
90
+ config_param :retry_type, :enum, list: [:exponential_backoff, :periodic], default: :exponential_backoff
91
+ ### Periodic -> fixed :retry_wait
92
+ ### Exponential backoff: k is number of retry times
93
+ # c: constant factor, @retry_wait
94
+ # b: base factor, @retry_exponential_backoff_base
95
+ # k: times
96
+ # total retry time: c + c * b^1 + (...) + c*b^k = c*b^(k+1) - 1
97
+ config_param :retry_wait, :time, default: 5, desc: 'Seconds to wait before next retry , or constant factor of exponential backoff.'
98
+ config_param :retry_exponential_backoff_base, :float, default: 2, desc: 'The base number of exponential backoff for retries.'
99
+ config_param :retry_max_interval, :time, default: nil, desc: 'The maximum interval seconds for exponential backoff between retries while failing.'
100
+ config_param :retry_randomize, :bool, default: false, desc: 'If true, output plugin will retry after randomized interval not to do burst retries.'
84
101
 
85
102
  include Fluent::Plugin::OpenSearchConstants
86
103
 
@@ -93,6 +110,7 @@ module Fluent::Plugin
93
110
 
94
111
  @timestamp_parser = create_time_parser
95
112
  @backend_options = backend_options
113
+ @retry = nil
96
114
 
97
115
  raise Fluent::ConfigError, "`password` must be present if `user` is present" if @user && @password.nil?
98
116
 
@@ -139,6 +157,15 @@ module Fluent::Plugin
139
157
  raise Fluent::ConfigError, "You must install #{@http_backend} gem. Exception: #{ex}"
140
158
  end
141
159
 
160
+ def retry_state(randomize)
161
+ retry_state_create(
162
+ :input_retries, @retry_type, @retry_wait, @retry_timeout,
163
+ forever: @retry_forever, max_steps: @retry_max_times,
164
+ max_interval: @retry_max_interval, backoff_base: @retry_exponential_backoff_base,
165
+ randomize: randomize
166
+ )
167
+ end
168
+
142
169
  def get_escaped_userinfo(host_str)
143
170
  if m = host_str.match(/(?<scheme>.*)%{(?<user>.*)}:%{(?<password>.*)}(?<path>@.*)/)
144
171
  m["scheme"] +
@@ -177,12 +204,29 @@ module Fluent::Plugin
177
204
  host.merge!(user: @user, password: @password) if !host[:user] && @user
178
205
  host.merge!(path: @path) if !host[:path] && @path
179
206
  end
180
-
207
+ live_hosts = @check_connection ? hosts.select { |host| reachable_host?(host) } : hosts
181
208
  {
182
- hosts: get_reachable_hosts(hosts)
209
+ hosts: live_hosts
183
210
  }
184
211
  end
185
212
 
213
+ def reachable_host?(host)
214
+ client = OpenSearch::Client.new(
215
+ host: ["#{host[:scheme]}://#{host[:host]}:#{host[:port]}"],
216
+ user: host[:user],
217
+ password: host[:password],
218
+ reload_connections: @reload_connections,
219
+ request_timeout: @request_timeout,
220
+ resurrect_after: @resurrect_after,
221
+ reload_on_failure: @reload_on_failure,
222
+ transport_options: { ssl: { verify: @ssl_verify, ca_file: @ca_file, version: @ssl_version } }
223
+ )
224
+ client.ping
225
+ rescue => e
226
+ log.warn "Failed to connect to #{host[:scheme]}://#{host[:host]}:#{host[:port]}: #{e.message}"
227
+ false
228
+ end
229
+
186
230
  def emit_error_label_event(&block)
187
231
  # If `emit_error_label_event` is specified as false, error event emittions are not occurred.
188
232
  if emit_error_label_event
@@ -240,43 +284,6 @@ module Fluent::Plugin
240
284
  return Time.at(event_time).to_time
241
285
  end
242
286
 
243
- def get_reachable_hosts(hosts=nil)
244
- reachable_hosts = []
245
- attempt = 0
246
- loop do
247
- hosts.each do |host|
248
- begin
249
- if @infinite_check_connection == true
250
- check_host = OpenSearch::Client.new(
251
- host: ["#{host[:scheme]}://#{host[:host]}:#{host[:port]}"],
252
- user: host[:user],
253
- password: host[:password],
254
- reload_connections: true,
255
- resurrect_after: @resurrect_after,
256
- reload_on_failure: @reload_on_failure,
257
- transport_options: { ssl: { verify: @ssl_verify, ca_file: @ca_file, version: @ssl_version } }
258
- )
259
- response = check_host.ping #https://github.com/opensearch-project/opensearch-ruby/blob/136e1c975fc91b8cb80d7d1134e32c6dbefdb3eb/lib/opensearch/api/actions/ping.rb#L33
260
- if response == true
261
- reachable_hosts << host
262
- else
263
- log.warn "Connection to #{host[:scheme]}://#{host[:host]}:#{host[:port]} failed with status code #{response.status}"
264
- end
265
- else
266
- reachable_hosts << host
267
- end
268
- rescue => e
269
- log.warn "Failed to connect to #{host[:scheme]}://#{host[:host]}:#{host[:port]}"
270
- end
271
- end
272
- break unless reachable_hosts.empty?
273
- log.info "Attempt ##{attempt += 1} to get reachable hosts"
274
- log.info "No reachable hosts found. Retrying in #{@request_timeout} seconds..."
275
- sleep(@request_timeout)
276
- end
277
- reachable_hosts
278
- end
279
-
280
287
  def client(host = nil)
281
288
  # check here to see if we already have a client connection for the given host
282
289
  connection_options = get_connection_options(host)
@@ -330,6 +337,25 @@ module Fluent::Plugin
330
337
  return true
331
338
  end
332
339
 
340
+ def update_retry_state(error=nil)
341
+ if error
342
+ unless @retry
343
+ @retry = retry_state(@retry_randomize)
344
+ end
345
+ @retry.step
346
+ #Raise error if the retry limit has been reached
347
+ raise "Hit limit for retries. retry_times: #{@retry.steps}, error: #{error.message}" if @retry.limit?
348
+ #Retry if the limit hasn't been reached
349
+ log.warn("failed to connect or search.", retry_times: @retry.steps, next_retry_time: @retry.next_time.round, error: error.message)
350
+ sleep(@retry.next_time - Time.now)
351
+ else
352
+ unless @retry.nil?
353
+ log.debug("retry succeeded.")
354
+ @retry = nil
355
+ end
356
+ end
357
+ end
358
+
333
359
  def run
334
360
  return run_slice if @num_slices <= 1
335
361
 
@@ -340,8 +366,8 @@ module Fluent::Plugin
340
366
  run_slice(slice_id)
341
367
  end
342
368
  end
343
- rescue Faraday::ConnectionFailed => e
344
- log.warn "Connection to OpenSearch failed during search in the 'run' method: #{e.message}. Retrying..."
369
+ rescue Faraday::ConnectionFailed, OpenSearch::Transport::Transport::Error => error
370
+ update_retry_state(error)
345
371
  retry
346
372
  end
347
373
 
@@ -363,6 +389,7 @@ module Fluent::Plugin
363
389
 
364
390
  router.emit_stream(@tag, es)
365
391
  clear_scroll(scroll_id)
392
+ update_retry_state
366
393
  end
367
394
 
368
395
  def clear_scroll(scroll_id)
@@ -39,7 +39,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
39
39
  CONFIG = %[
40
40
  tag raw.opensearch
41
41
  interval 2
42
- infinite_check_connection false
42
+ check_connection false
43
43
  ]
44
44
 
45
45
  def setup
@@ -191,7 +191,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
191
191
  user john
192
192
  password doe
193
193
  tag raw.opensearch
194
- infinite_check_connection false
194
+ check_connection false
195
195
  }
196
196
  instance = driver(config).instance
197
197
 
@@ -230,7 +230,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
230
230
  user john
231
231
  password doe
232
232
  tag raw.opensearch
233
- infinite_check_connection false
233
+ check_connection false
234
234
  }
235
235
  instance = driver(config).instance
236
236
 
@@ -252,7 +252,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
252
252
  user %{j+hn}
253
253
  password %{d@e}
254
254
  tag raw.opensearch
255
- infinite_check_connection false
255
+ check_connection false
256
256
  }
257
257
  instance = driver(config).instance
258
258
 
@@ -275,7 +275,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
275
275
  path /es/
276
276
  port 123
277
277
  tag raw.opensearch
278
- infinite_check_connection false
278
+ check_connection false
279
279
  }
280
280
  instance = driver(config).instance
281
281
 
@@ -300,7 +300,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
300
300
  user default_user
301
301
  password default_password
302
302
  tag raw.opensearch
303
- infinite_check_connection false
303
+ check_connection false
304
304
  }
305
305
  instance = driver(config).instance
306
306
 
@@ -329,7 +329,7 @@ class OpenSearchInputTest < Test::Unit::TestCase
329
329
  user default_user
330
330
  password default_password
331
331
  tag raw.opensearch
332
- infinite_check_connection false
332
+ check_connection false
333
333
  }
334
334
  instance = driver(config).instance
335
335
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-input-opensearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.9
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - imcotop
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-15 00:00:00.000000000 Z
11
+ date: 2024-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd