fluent-plugin-elasticsearch 4.0.5 → 4.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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-elasticsearch'
6
- s.version = '4.0.5'
6
+ s.version = '4.0.10'
7
7
  s.authors = ['diogo', 'pitr', 'Hiroshi Hatake']
8
8
  s.email = ['pitr.vern@gmail.com', 'me@diogoterror.com', 'cosmo0920.wp@gmail.com']
9
9
  s.description = %q{Elasticsearch output plugin for Fluent event collector}
@@ -4,7 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec :path => "../"
5
5
 
6
6
  gem 'simplecov', require: false
7
- gem 'coveralls', require: false
7
+ gem 'coveralls', ">= 0.8.0", require: false
8
8
  gem 'strptime', require: false if RUBY_ENGINE == "ruby" && RUBY_VERSION =~ /^2/
9
9
  gem "irb" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.6"
10
10
  gem "elasticsearch", "~> 6.8.1"
@@ -4,8 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec :path => "../"
5
5
 
6
6
  gem 'simplecov', require: false
7
- gem 'coveralls', require: false
7
+ gem 'coveralls', ">= 0.8.0", require: false
8
8
  gem 'strptime', require: false if RUBY_ENGINE == "ruby" && RUBY_VERSION =~ /^2/
9
9
  gem "irb" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.6"
10
- gem "elasticsearch-xpack"
11
10
  gem "oj"
@@ -58,7 +58,7 @@ module Fluent::ElasticsearchIndexTemplate
58
58
  def indexcreation(index_name, host = nil)
59
59
  client(host).indices.create(:index => index_name)
60
60
  rescue Elasticsearch::Transport::Transport::Error => e
61
- if e.message =~ /"already exists"/
61
+ if e.message =~ /"already exists"/ || e.message =~ /resource_already_exists_exception/
62
62
  log.debug("Index #{index_name} already exists")
63
63
  else
64
64
  log.error("Error while index creation - #{index_name}: #{e.inspect}")
@@ -10,7 +10,7 @@ module Fluent::Plugin
10
10
  [:SSLv23, :TLSv1, :TLSv1_1, :TLSv1_2].freeze
11
11
  end
12
12
 
13
- DEFAULT_VERSION = :TLSv1
13
+ DEFAULT_VERSION = :TLSv1_2
14
14
  METHODS_MAP = begin
15
15
  # When openssl supports OpenSSL::SSL::TLSXXX constants representations, we use them.
16
16
  map = {
@@ -48,8 +48,8 @@ module Fluent::Plugin
48
48
  if USE_TLS_MINMAX_VERSION
49
49
  case
50
50
  when ssl_min_version.nil? && ssl_max_version.nil?
51
- ssl_min_version = METHODS_MAP[ssl_version]
52
- ssl_max_version = METHODS_MAP[ssl_version]
51
+ ssl_min_version = METHODS_MAP[:TLSv1_2]
52
+ ssl_max_version = METHODS_MAP[:TLSv1_3]
53
53
  when ssl_min_version && ssl_max_version.nil?
54
54
  raise Fluent::ConfigError, "When you set 'ssl_min_version', must set 'ssl_max_version' together."
55
55
  when ssl_min_version.nil? && ssl_max_version
@@ -7,6 +7,13 @@ module Fluent::Plugin
7
7
  Fluent::Plugin.register_filter('elasticsearch_genid', self)
8
8
 
9
9
  config_param :hash_id_key, :string, :default => '_hash'
10
+ config_param :include_tag_in_seed, :bool, :default => false
11
+ config_param :include_time_in_seed, :bool, :default => false
12
+ config_param :use_record_as_seed, :bool, :default => false
13
+ config_param :use_entire_record, :bool, :default => false
14
+ config_param :record_keys, :array, :default => []
15
+ config_param :separator, :string, :default => '_'
16
+ config_param :hash_type, :enum, list: [:md5, :sha1, :sha256, :sha512], :default => :sha1
10
17
 
11
18
  def initialize
12
19
  super
@@ -14,12 +21,57 @@ module Fluent::Plugin
14
21
 
15
22
  def configure(conf)
16
23
  super
24
+
25
+ if !@use_entire_record
26
+ if @record_keys.empty? && @use_record_as_seed
27
+ raise Fluent::ConfigError, "When using record as hash seed, users must specify `record_keys`."
28
+ end
29
+ end
30
+
31
+ if @use_record_as_seed
32
+ class << self
33
+ alias_method :filter, :filter_seed_as_record
34
+ end
35
+ else
36
+ class << self
37
+ alias_method :filter, :filter_simple
38
+ end
39
+ end
17
40
  end
18
41
 
19
42
  def filter(tag, time, record)
43
+ # for safety.
44
+ end
45
+
46
+ def filter_simple(tag, time, record)
20
47
  record[@hash_id_key] = Base64.strict_encode64(SecureRandom.uuid)
21
48
  record
22
49
  end
23
50
 
51
+ def filter_seed_as_record(tag, time, record)
52
+ seed = ""
53
+ seed += tag + separator if @include_tag_in_seed
54
+ seed += time.to_s + separator if @include_time_in_seed
55
+ if @use_entire_record
56
+ record.each {|k,v| seed += "|#{k}|#{v}"}
57
+ else
58
+ seed += record_keys.map {|k| record[k]}.join(separator)
59
+ end
60
+ record[@hash_id_key] = Base64.strict_encode64(encode_hash(@hash_type, seed))
61
+ record
62
+ end
63
+
64
+ def encode_hash(type, seed)
65
+ case type
66
+ when :md5
67
+ Digest::MD5.digest(seed)
68
+ when :sha1
69
+ Digest::SHA1.digest(seed)
70
+ when :sha256
71
+ Digest::SHA256.digest(seed)
72
+ when :sha512
73
+ Digest::SHA512.digest(seed)
74
+ end
75
+ end
24
76
  end
25
77
  end
@@ -55,6 +55,7 @@ module Fluent::Plugin
55
55
  attr_reader :alias_indexes
56
56
  attr_reader :template_names
57
57
  attr_reader :ssl_version_options
58
+ attr_reader :compressable_connection
58
59
 
59
60
  helpers :event_emitter, :compat_parameters, :record_accessor, :timer
60
61
 
@@ -89,6 +90,7 @@ EOC
89
90
  config_param :logstash_dateformat, :string, :default => "%Y.%m.%d"
90
91
  config_param :utc_index, :bool, :default => true
91
92
  config_param :type_name, :string, :default => DEFAULT_TYPE_NAME
93
+ config_param :suppress_type_name, :bool, :default => false
92
94
  config_param :index_name, :string, :default => "fluentd"
93
95
  config_param :id_key, :string, :default => nil
94
96
  config_param :write_operation, :string, :default => "index"
@@ -125,6 +127,7 @@ EOC
125
127
  config_param :templates, :hash, :default => nil
126
128
  config_param :max_retry_putting_template, :integer, :default => 10
127
129
  config_param :fail_on_putting_template_retry_exceed, :bool, :default => true
130
+ config_param :fail_on_detecting_es_version_retry_exceed, :bool, :default => true
128
131
  config_param :max_retry_get_es_version, :integer, :default => 15
129
132
  config_param :include_tag_key, :bool, :default => false
130
133
  config_param :tag_key, :string, :default => 'tag'
@@ -142,6 +145,7 @@ see: https://github.com/elastic/elasticsearch-ruby/pull/514
142
145
  EOC
143
146
  config_param :include_index_in_url, :bool, :default => false
144
147
  config_param :http_backend, :enum, list: [:excon, :typhoeus], :default => :excon
148
+ config_param :http_backend_excon_nonblock, :bool, :default => true
145
149
  config_param :validate_client_version, :bool, :default => false
146
150
  config_param :prefer_oj_serializer, :bool, :default => false
147
151
  config_param :unrecoverable_error_types, :array, :default => ["out_of_memory_error", "es_rejected_execution_exception"]
@@ -157,6 +161,7 @@ EOC
157
161
  config_param :enable_ilm, :bool, :default => false
158
162
  config_param :ilm_policy_id, :string, :default => DEFAULT_POLICY_ID
159
163
  config_param :ilm_policy, :hash, :default => {}
164
+ config_param :ilm_policies, :hash, :default => {}
160
165
  config_param :ilm_policy_overwrite, :bool, :default => false
161
166
  config_param :truncate_caches_interval, :time, :default => nil
162
167
 
@@ -217,6 +222,11 @@ EOC
217
222
  log.info "host placeholder and template installation makes your Elasticsearch cluster a bit slow down(beta)."
218
223
  end
219
224
 
225
+ raise Fluent::ConfigError, "You can't specify ilm_policy and ilm_policies at the same time" unless @ilm_policy.empty? or @ilm_policies.empty?
226
+
227
+ unless @ilm_policy.empty?
228
+ @ilm_policies = { @ilm_policy_id => @ilm_policy }
229
+ end
220
230
  @alias_indexes = []
221
231
  @template_names = []
222
232
  if !dry_run?
@@ -225,14 +235,14 @@ EOC
225
235
  raise Fluent::ConfigError, "deflector_alias is prohibited to use with 'logstash_format at same time." if @logstash_format and @deflector_alias
226
236
  end
227
237
  if @ilm_policy.empty? && @ilm_policy_overwrite
228
- raise Fluent::ConfigError, "ilm_policy_overwrite can work with non empty ilm_policy. Specify non-empty ilm policy into ilm_policy. "
238
+ raise Fluent::ConfigError, "ilm_policy_overwrite requires a non empty ilm_policy."
229
239
  end
230
240
  if @logstash_format || placeholder_substitution_needed_for_template?
231
241
  class << self
232
242
  alias_method :template_installation, :template_installation_actual
233
243
  end
234
244
  else
235
- template_installation_actual(@deflector_alias ? @deflector_alias : @index_name, @template_name, @customize_template, @application_name, @index_name)
245
+ template_installation_actual(@deflector_alias ? @deflector_alias : @index_name, @template_name, @customize_template, @application_name, @index_name, @ilm_policy_id)
236
246
  end
237
247
  verify_ilm_working if @enable_ilm
238
248
  elsif @templates
@@ -290,24 +300,25 @@ EOC
290
300
  raise Fluent::ConfigError, "Could not load sniffer class #{@sniffer_class_name}: #{ex}"
291
301
  end
292
302
 
293
- @last_seen_major_version =
294
- if @verify_es_version_at_startup && !dry_run?
295
- retry_operate(@max_retry_get_es_version) do
296
- detect_es_major_version
297
- end
298
- else
299
- @default_elasticsearch_version
300
- end
301
- if @last_seen_major_version == 6 && @type_name != DEFAULT_TYPE_NAME_ES_7x
302
- log.info "Detected ES 6.x: ES 7.x will only accept `_doc` in type_name."
303
- end
304
- if @last_seen_major_version == 7 && @type_name != DEFAULT_TYPE_NAME_ES_7x
305
- log.warn "Detected ES 7.x: `_doc` will be used as the document `_type`."
306
- @type_name = '_doc'.freeze
307
- end
308
- if @last_seen_major_version >= 8 && @type_name != DEFAULT_TYPE_NAME_ES_7x
309
- log.info "Detected ES 8.x or above: This parameter has no effect."
303
+ @last_seen_major_version = if major_version = handle_last_seen_es_major_version
304
+ major_version
305
+ else
306
+ @default_elasticsearch_version
307
+ end
308
+ if @suppress_type_name && @last_seen_major_version >= 7
310
309
  @type_name = nil
310
+ else
311
+ if @last_seen_major_version == 6 && @type_name != DEFAULT_TYPE_NAME_ES_7x
312
+ log.info "Detected ES 6.x: ES 7.x will only accept `_doc` in type_name."
313
+ end
314
+ if @last_seen_major_version == 7 && @type_name != DEFAULT_TYPE_NAME_ES_7x
315
+ log.warn "Detected ES 7.x: `_doc` will be used as the document `_type`."
316
+ @type_name = '_doc'.freeze
317
+ end
318
+ if @last_seen_major_version >= 8 && @type_name != DEFAULT_TYPE_NAME_ES_7x
319
+ log.info "Detected ES 8.x or above: This parameter has no effect."
320
+ @type_name = nil
321
+ end
311
322
  end
312
323
 
313
324
  if @validate_client_version && !dry_run?
@@ -329,6 +340,13 @@ EOC
329
340
  end
330
341
  end
331
342
 
343
+ if @ssl_version && @scheme == :https
344
+ if !@http_backend_excon_nonblock
345
+ log.warn "TLS handshake will be stucked with block connection.
346
+ Consider to set `http_backend_excon_nonblock` as true"
347
+ end
348
+ end
349
+
332
350
  # Consider missing the prefix of "$." in nested key specifiers.
333
351
  @id_key = convert_compat_id_key(@id_key) if @id_key
334
352
  @parent_key = convert_compat_id_key(@parent_key) if @parent_key
@@ -337,6 +355,7 @@ EOC
337
355
  @routing_key_name = configure_routing_key_name
338
356
  @meta_config_map = create_meta_config_map
339
357
  @current_config = nil
358
+ @compressable_connection = false
340
359
 
341
360
  @ignore_exception_classes = @ignore_exceptions.map do |exception|
342
361
  unless Object.const_defined?(exception)
@@ -411,7 +430,7 @@ EOC
411
430
  def backend_options
412
431
  case @http_backend
413
432
  when :excon
414
- { client_key: @client_key, client_cert: @client_cert, client_key_pass: @client_key_pass }
433
+ { client_key: @client_key, client_cert: @client_cert, client_key_pass: @client_key_pass, nonblock: @http_backend_excon_nonblock }
415
434
  when :typhoeus
416
435
  require 'typhoeus'
417
436
  { sslkey: @client_key, sslcert: @client_cert, keypasswd: @client_key_pass }
@@ -421,6 +440,16 @@ EOC
421
440
  raise Fluent::ConfigError, "You must install #{@http_backend} gem. Exception: #{ex}"
422
441
  end
423
442
 
443
+ def handle_last_seen_es_major_version
444
+ if @verify_es_version_at_startup && !dry_run?
445
+ retry_operate(@max_retry_get_es_version, @fail_on_detecting_es_version_retry_exceed) do
446
+ detect_es_major_version
447
+ end
448
+ else
449
+ nil
450
+ end
451
+ end
452
+
424
453
  def detect_es_major_version
425
454
  @_es_info ||= client.info
426
455
  @_es_info["version"]["number"].to_i
@@ -495,13 +524,15 @@ EOC
495
524
  return Time.at(event_time).to_datetime
496
525
  end
497
526
 
498
- def client(host = nil)
527
+ def client(host = nil, compress_connection = false)
499
528
  # check here to see if we already have a client connection for the given host
500
529
  connection_options = get_connection_options(host)
501
530
 
502
531
  @_es = nil unless is_existing_connection(connection_options[:hosts])
532
+ @_es = nil unless @compressable_connection == compress_connection
503
533
 
504
534
  @_es ||= begin
535
+ @compressable_connection = compress_connection
505
536
  @current_config = connection_options[:hosts].clone
506
537
  adapter_conf = lambda {|f| f.adapter @http_backend, @backend_options }
507
538
  local_reload_connections = @reload_connections
@@ -509,7 +540,7 @@ EOC
509
540
  local_reload_connections = @reload_after
510
541
  end
511
542
 
512
- gzip_headers = if compression
543
+ gzip_headers = if compress_connection
513
544
  {'Content-Encoding' => 'gzip'}
514
545
  else
515
546
  {}
@@ -535,7 +566,7 @@ EOC
535
566
  },
536
567
  sniffer_class: @sniffer_class,
537
568
  serializer_class: @serializer_class,
538
- compression: compression,
569
+ compression: compress_connection,
539
570
  }), &adapter_conf)
540
571
  Elasticsearch::Client.new transport: transport
541
572
  end
@@ -699,7 +730,12 @@ EOC
699
730
  else
700
731
  pipeline = nil
701
732
  end
702
- return logstash_prefix, logstash_dateformat, index_name, type_name, template_name, customize_template, deflector_alias, application_name, pipeline
733
+ if @ilm_policy_id
734
+ ilm_policy_id = extract_placeholders(@ilm_policy_id, chunk)
735
+ else
736
+ ilm_policy_id = nil
737
+ end
738
+ return logstash_prefix, logstash_dateformat, index_name, type_name, template_name, customize_template, deflector_alias, application_name, pipeline, ilm_policy_id
703
739
  end
704
740
 
705
741
  def multi_workers_ready?
@@ -773,7 +809,7 @@ EOC
773
809
  end
774
810
 
775
811
  def process_message(tag, meta, header, time, record, extracted_values)
776
- logstash_prefix, logstash_dateformat, index_name, type_name, _template_name, _customize_template, _deflector_alias, _application_name, pipeline = extracted_values
812
+ logstash_prefix, logstash_dateformat, index_name, type_name, _template_name, _customize_template, _deflector_alias, _application_name, pipeline, _ilm_policy_id = extracted_values
777
813
 
778
814
  if @flatten_hashes
779
815
  record = flatten_record(record)
@@ -825,7 +861,9 @@ EOC
825
861
  target_type = nil
826
862
  end
827
863
  else
828
- if @last_seen_major_version == 7 && @type_name != DEFAULT_TYPE_NAME_ES_7x
864
+ if @suppress_type_name && @last_seen_major_version >= 7
865
+ target_type = nil
866
+ elsif @last_seen_major_version == 7 && @type_name != DEFAULT_TYPE_NAME_ES_7x
829
867
  log.warn "Detected ES 7.x: `_doc` will be used as the document `_type`."
830
868
  target_type = '_doc'.freeze
831
869
  elsif @last_seen_major_version >= 8
@@ -881,16 +919,17 @@ EOC
881
919
  placeholder?(:logstash_prefix, @logstash_prefix.to_s) ||
882
920
  placeholder?(:logstash_dateformat, @logstash_dateformat.to_s) ||
883
921
  placeholder?(:deflector_alias, @deflector_alias.to_s) ||
884
- placeholder?(:application_name, @application_name.to_s)
922
+ placeholder?(:application_name, @application_name.to_s) ||
923
+ placeholder?(:ilm_policy_id, @ilm_policy_id.to_s)
885
924
  log.debug("Need substitution: #{need_substitution}")
886
925
  need_substitution
887
926
  end
888
927
 
889
- def template_installation(deflector_alias, template_name, customize_template, application_name, target_index, host)
928
+ def template_installation(deflector_alias, template_name, customize_template, application_name, ilm_policy_id, target_index, host)
890
929
  # for safety.
891
930
  end
892
931
 
893
- def template_installation_actual(deflector_alias, template_name, customize_template, application_name, target_index, host=nil)
932
+ def template_installation_actual(deflector_alias, template_name, customize_template, application_name, target_index, ilm_policy_id, host=nil)
894
933
  if template_name && @template_file
895
934
  if @alias_indexes.include? deflector_alias
896
935
  log.debug("Index alias #{deflector_alias} already exists (cached)")
@@ -899,11 +938,12 @@ EOC
899
938
  else
900
939
  retry_operate(@max_retry_putting_template, @fail_on_putting_template_retry_exceed) do
901
940
  if customize_template
902
- template_custom_install(template_name, @template_file, @template_overwrite, customize_template, @enable_ilm, deflector_alias, @ilm_policy_id, host)
941
+ template_custom_install(template_name, @template_file, @template_overwrite, customize_template, @enable_ilm, deflector_alias, ilm_policy_id, host)
903
942
  else
904
- template_install(template_name, @template_file, @template_overwrite, @enable_ilm, deflector_alias, @ilm_policy_id, host)
943
+ template_install(template_name, @template_file, @template_overwrite, @enable_ilm, deflector_alias, ilm_policy_id, host)
905
944
  end
906
- create_rollover_alias(target_index, @rollover_index, deflector_alias, application_name, @index_date_pattern, @index_separator, @enable_ilm, @ilm_policy_id, @ilm_policy, @ilm_policy_overwrite, host)
945
+ ilm_policy = @ilm_policies[ilm_policy_id] || {}
946
+ create_rollover_alias(target_index, @rollover_index, deflector_alias, application_name, @index_date_pattern, @index_separator, @enable_ilm, ilm_policy_id, ilm_policy, @ilm_policy_overwrite, host)
907
947
  end
908
948
  @alias_indexes << deflector_alias unless deflector_alias.nil?
909
949
  @template_names << template_name unless template_name.nil?
@@ -914,11 +954,11 @@ EOC
914
954
  # send_bulk given a specific bulk request, the original tag,
915
955
  # chunk, and bulk_message_count
916
956
  def send_bulk(data, tag, chunk, bulk_message_count, extracted_values, info)
917
- logstash_prefix, _logstash_dateformat, index_name, _type_name, template_name, customize_template, deflector_alias, application_name, _pipeline = extracted_values
957
+ logstash_prefix, _logstash_dateformat, index_name, _type_name, template_name, customize_template, deflector_alias, application_name, _pipeline, ilm_policy_id = extracted_values
918
958
  if deflector_alias
919
- template_installation(deflector_alias, template_name, customize_template, application_name, index_name, info.host)
959
+ template_installation(deflector_alias, template_name, customize_template, application_name, index_name, ilm_policy_id, info.host)
920
960
  else
921
- template_installation(info.ilm_index, template_name, customize_template, application_name, @logstash_format ? logstash_prefix : index_name, info.host)
961
+ template_installation(info.ilm_index, template_name, customize_template, application_name, @logstash_format ? logstash_prefix : index_name, ilm_policy_id, info.host)
922
962
  end
923
963
 
924
964
  begin
@@ -931,7 +971,7 @@ EOC
931
971
  data
932
972
  end
933
973
 
934
- response = client(info.host).bulk body: prepared_data, index: info.index
974
+ response = client(info.host, compression).bulk body: prepared_data, index: info.index
935
975
  log.on_trace { log.trace "bulk response: #{response}" }
936
976
 
937
977
  if response['errors']
@@ -35,16 +35,18 @@ module Fluent::Plugin
35
35
  end
36
36
 
37
37
 
38
- def client(host = nil)
38
+ def client(host = nil, compress_connection = false)
39
39
  # check here to see if we already have a client connection for the given host
40
40
  connection_options = get_connection_options(host)
41
41
 
42
42
  @_es = nil unless is_existing_connection(connection_options[:hosts])
43
+ @_es = nil unless @compressable_connection == compress_connection
43
44
 
44
45
  @_es ||= begin
46
+ @compressable_connection = compress_connection
45
47
  @current_config = connection_options[:hosts].clone
46
48
  adapter_conf = lambda {|f| f.adapter @http_backend, @backend_options }
47
- gzip_headers = if compression
49
+ gzip_headers = if compress_connection
48
50
  {'Content-Encoding' => 'gzip'}
49
51
  else
50
52
  {}
@@ -67,7 +69,7 @@ module Fluent::Plugin
67
69
  password: @password,
68
70
  scheme: @scheme
69
71
  },
70
- compression: compression,
72
+ compression: compress_connection,
71
73
  }), &adapter_conf)
72
74
  Elasticsearch::Client.new transport: transport
73
75
  end
@@ -228,7 +230,7 @@ module Fluent::Plugin
228
230
  else
229
231
  data
230
232
  end
231
- response = client(host).bulk body: prepared_data, index: index
233
+ response = client(host, compression).bulk body: prepared_data, index: index
232
234
  if response['errors']
233
235
  log.error "Could not push log to Elasticsearch: #{response}"
234
236
  end