logstash-output-opensearch 1.3.0-java → 2.0.3-java

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/COMPATIBILITY.md +5 -3
  4. data/DEVELOPER_GUIDE.md +6 -1
  5. data/MAINTAINERS.md +15 -64
  6. data/README.md +57 -35
  7. data/RELEASING.md +5 -1
  8. data/docs/building_custom_docker_images.md +79 -0
  9. data/docs/ecs_compatibility.md +42 -0
  10. data/lib/logstash/outputs/opensearch/http_client/manticore_adapter.rb +47 -14
  11. data/lib/logstash/outputs/opensearch/http_client/pool.rb +11 -2
  12. data/lib/logstash/outputs/opensearch/http_client.rb +28 -6
  13. data/lib/logstash/outputs/opensearch/http_client_builder.rb +4 -2
  14. data/lib/logstash/outputs/opensearch/template_manager.rb +6 -5
  15. data/lib/logstash/outputs/opensearch/templates/ecs-disabled/1x_index.json +66 -0
  16. data/lib/logstash/outputs/opensearch/templates/ecs-disabled/2x_index.json +66 -0
  17. data/lib/logstash/outputs/opensearch/templates/ecs-disabled/7x_index.json +66 -0
  18. data/lib/logstash/outputs/opensearch/templates/ecs-v8/1x_index.json +5254 -0
  19. data/lib/logstash/outputs/opensearch/templates/ecs-v8/2x_index.json +5254 -0
  20. data/lib/logstash/outputs/opensearch/templates/ecs-v8/7x_index.json +5254 -0
  21. data/lib/logstash/outputs/opensearch.rb +7 -0
  22. data/lib/logstash/plugin_mixins/opensearch/common.rb +1 -0
  23. data/logstash-output-opensearch.gemspec +2 -2
  24. data/spec/integration/outputs/index_spec.rb +3 -2
  25. data/spec/opensearch_spec_helper.rb +9 -0
  26. data/spec/unit/outputs/opensearch/http_client/manticore_adapter_spec.rb +72 -14
  27. data/spec/unit/outputs/opensearch/http_client_spec.rb +20 -0
  28. data/spec/unit/outputs/opensearch/template_manager_spec.rb +8 -20
  29. data/spec/unit/outputs/opensearch_spec.rb +24 -0
  30. data.tar.gz.sig +0 -0
  31. metadata +32 -30
  32. metadata.gz.sig +0 -0
@@ -107,7 +107,6 @@ module LogStash; module Outputs; class OpenSearch;
107
107
 
108
108
  body_stream = StringIO.new
109
109
  if http_compression
110
- body_stream.set_encoding "BINARY"
111
110
  stream_writer = gzip_writer(body_stream)
112
111
  else
113
112
  stream_writer = body_stream
@@ -126,9 +125,24 @@ module LogStash; module Outputs; class OpenSearch;
126
125
  :payload_size => stream_writer.pos,
127
126
  :content_length => body_stream.size,
128
127
  :batch_offset => (index + 1 - batch_actions.size))
128
+
129
+ # Have to close gzip writer before reading from body_stream; otherwise stream doesn't end properly
130
+ # and will cause server side error
131
+ if http_compression
132
+ stream_writer.close
133
+ end
134
+
129
135
  bulk_responses << bulk_send(body_stream, batch_actions)
130
- body_stream.truncate(0) && body_stream.seek(0)
131
- stream_writer = gzip_writer(body_stream) if http_compression
136
+
137
+ if http_compression
138
+ # Get a new StringIO object and gzip writer
139
+ body_stream = StringIO.new
140
+ stream_writer = gzip_writer(body_stream)
141
+ else
142
+ # Clear existing StringIO object and reuse existing stream writer
143
+ body_stream.truncate(0) && body_stream.seek(0)
144
+ end
145
+
132
146
  batch_actions.clear
133
147
  end
134
148
  stream_writer.write(as_json)
@@ -149,6 +163,7 @@ module LogStash; module Outputs; class OpenSearch;
149
163
  fail(ArgumentError, "Cannot create gzip writer on IO with unread bytes") unless io.eof?
150
164
  fail(ArgumentError, "Cannot create gzip writer on non-empty IO") unless io.pos == 0
151
165
 
166
+ io.set_encoding "BINARY"
152
167
  Zlib::GzipWriter.new(io, Zlib::DEFAULT_COMPRESSION, Zlib::DEFAULT_STRATEGY)
153
168
  end
154
169
 
@@ -328,7 +343,8 @@ module LogStash; module Outputs; class OpenSearch;
328
343
  :healthcheck_path => options[:healthcheck_path],
329
344
  :resurrect_delay => options[:resurrect_delay],
330
345
  :url_normalizer => self.method(:host_to_url),
331
- :metric => options[:metric]
346
+ :metric => options[:metric],
347
+ :default_server_major_version => options[:default_server_major_version]
332
348
  }
333
349
  pool_options[:scheme] = self.scheme if self.scheme
334
350
 
@@ -388,10 +404,16 @@ module LogStash; module Outputs; class OpenSearch;
388
404
  @pool.put(path, nil, LogStash::Json.dump(template))
389
405
  end
390
406
 
407
+ def legacy_template?()
408
+ # TODO: Also check Version and return true for < 7.8 even if :legacy_template=false
409
+ # Need to figure a way to distinguish between OpenSearch, OpenDistro and other
410
+ # variants, since they have version numbers in different ranges.
411
+ client_settings.fetch(:legacy_template, true)
412
+ end
413
+
391
414
  def template_endpoint
392
- # TODO: Check Version < 7.8 and use index template for >= 7.8 & OpenSearch
393
415
  # https://opensearch.org/docs/opensearch/index-templates/
394
- '_template'
416
+ legacy_template?() ? '_template' : '_index_template'
395
417
  end
396
418
 
397
419
  # check whether rollover alias already exists
@@ -18,7 +18,8 @@ module LogStash; module Outputs; class OpenSearch;
18
18
  :pool_max_per_route => params["pool_max_per_route"],
19
19
  :check_connection_timeout => params["validate_after_inactivity"],
20
20
  :http_compression => params["http_compression"],
21
- :headers => params["custom_headers"] || {}
21
+ :headers => params["custom_headers"] || {},
22
+ :legacy_template => params["legacy_template"]
22
23
  }
23
24
 
24
25
  client_settings[:proxy] = params["proxy"] if params["proxy"]
@@ -26,7 +27,8 @@ module LogStash; module Outputs; class OpenSearch;
26
27
  common_options = {
27
28
  :client_settings => client_settings,
28
29
  :metric => params["metric"],
29
- :resurrect_delay => params["resurrect_delay"]
30
+ :resurrect_delay => params["resurrect_delay"],
31
+ :default_server_major_version => params["default_server_major_version"]
30
32
  }
31
33
 
32
34
  if params["sniffing"]
@@ -18,7 +18,7 @@ module LogStash; module Outputs; class OpenSearch
18
18
  else
19
19
  plugin.logger.info("Using a default mapping template", :version => plugin.maximum_seen_major_version,
20
20
  :ecs_compatibility => plugin.ecs_compatibility)
21
- template = load_default_template(plugin.maximum_seen_major_version, plugin.ecs_compatibility)
21
+ template = load_default_template(plugin.maximum_seen_major_version, plugin.ecs_compatibility, plugin.client.legacy_template?)
22
22
  end
23
23
 
24
24
  plugin.logger.debug("Attempting to install template", template: template)
@@ -26,8 +26,8 @@ module LogStash; module Outputs; class OpenSearch
26
26
  end
27
27
 
28
28
  private
29
- def self.load_default_template(major_version, ecs_compatibility)
30
- template_path = default_template_path(major_version, ecs_compatibility)
29
+ def self.load_default_template(major_version, ecs_compatibility, legacy_template)
30
+ template_path = default_template_path(major_version, ecs_compatibility, legacy_template)
31
31
  read_template_file(template_path)
32
32
  rescue => e
33
33
  fail "Failed to load default template for OpenSearch v#{major_version} with ECS #{ecs_compatibility}; caused by: #{e.inspect}"
@@ -45,9 +45,10 @@ module LogStash; module Outputs; class OpenSearch
45
45
  plugin.template_name
46
46
  end
47
47
 
48
- def self.default_template_path(major_version, ecs_compatibility=:disabled)
48
+ def self.default_template_path(major_version, ecs_compatibility=:disabled, legacy_template=true)
49
49
  template_version = major_version
50
- default_template_name = "templates/ecs-#{ecs_compatibility}/#{template_version}x.json"
50
+ suffix = legacy_template ? "" : "_index"
51
+ default_template_name = "templates/ecs-#{ecs_compatibility}/#{template_version}x#{suffix}.json"
51
52
  ::File.expand_path(default_template_name, ::File.dirname(__FILE__))
52
53
  end
53
54
 
@@ -0,0 +1,66 @@
1
+ {
2
+ "index_patterns": "logstash-*",
3
+ "version": 60001,
4
+ "priority": 10,
5
+ "template": {
6
+ "settings": {
7
+ "index.refresh_interval": "5s",
8
+ "number_of_shards": 1
9
+ },
10
+ "mappings": {
11
+ "dynamic_templates": [
12
+ {
13
+ "message_field": {
14
+ "path_match": "message",
15
+ "match_mapping_type": "string",
16
+ "mapping": {
17
+ "type": "text",
18
+ "norms": false
19
+ }
20
+ }
21
+ },
22
+ {
23
+ "string_fields": {
24
+ "match": "*",
25
+ "match_mapping_type": "string",
26
+ "mapping": {
27
+ "type": "text",
28
+ "norms": false,
29
+ "fields": {
30
+ "keyword": {
31
+ "type": "keyword",
32
+ "ignore_above": 256
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ ],
39
+ "properties": {
40
+ "@timestamp": {
41
+ "type": "date"
42
+ },
43
+ "@version": {
44
+ "type": "keyword"
45
+ },
46
+ "geoip": {
47
+ "dynamic": true,
48
+ "properties": {
49
+ "ip": {
50
+ "type": "ip"
51
+ },
52
+ "location": {
53
+ "type": "geo_point"
54
+ },
55
+ "latitude": {
56
+ "type": "half_float"
57
+ },
58
+ "longitude": {
59
+ "type": "half_float"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "index_patterns": "logstash-*",
3
+ "version": 60001,
4
+ "priority": 10,
5
+ "template": {
6
+ "settings": {
7
+ "index.refresh_interval": "5s",
8
+ "number_of_shards": 1
9
+ },
10
+ "mappings": {
11
+ "dynamic_templates": [
12
+ {
13
+ "message_field": {
14
+ "path_match": "message",
15
+ "match_mapping_type": "string",
16
+ "mapping": {
17
+ "type": "text",
18
+ "norms": false
19
+ }
20
+ }
21
+ },
22
+ {
23
+ "string_fields": {
24
+ "match": "*",
25
+ "match_mapping_type": "string",
26
+ "mapping": {
27
+ "type": "text",
28
+ "norms": false,
29
+ "fields": {
30
+ "keyword": {
31
+ "type": "keyword",
32
+ "ignore_above": 256
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ ],
39
+ "properties": {
40
+ "@timestamp": {
41
+ "type": "date"
42
+ },
43
+ "@version": {
44
+ "type": "keyword"
45
+ },
46
+ "geoip": {
47
+ "dynamic": true,
48
+ "properties": {
49
+ "ip": {
50
+ "type": "ip"
51
+ },
52
+ "location": {
53
+ "type": "geo_point"
54
+ },
55
+ "latitude": {
56
+ "type": "half_float"
57
+ },
58
+ "longitude": {
59
+ "type": "half_float"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,66 @@
1
+ {
2
+ "index_patterns": "logstash-*",
3
+ "version": 60001,
4
+ "priority": 10,
5
+ "template": {
6
+ "settings": {
7
+ "index.refresh_interval": "5s",
8
+ "number_of_shards": 1
9
+ },
10
+ "mappings": {
11
+ "dynamic_templates": [
12
+ {
13
+ "message_field": {
14
+ "path_match": "message",
15
+ "match_mapping_type": "string",
16
+ "mapping": {
17
+ "type": "text",
18
+ "norms": false
19
+ }
20
+ }
21
+ },
22
+ {
23
+ "string_fields": {
24
+ "match": "*",
25
+ "match_mapping_type": "string",
26
+ "mapping": {
27
+ "type": "text",
28
+ "norms": false,
29
+ "fields": {
30
+ "keyword": {
31
+ "type": "keyword",
32
+ "ignore_above": 256
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ ],
39
+ "properties": {
40
+ "@timestamp": {
41
+ "type": "date"
42
+ },
43
+ "@version": {
44
+ "type": "keyword"
45
+ },
46
+ "geoip": {
47
+ "dynamic": true,
48
+ "properties": {
49
+ "ip": {
50
+ "type": "ip"
51
+ },
52
+ "location": {
53
+ "type": "geo_point"
54
+ },
55
+ "latitude": {
56
+ "type": "half_float"
57
+ },
58
+ "longitude": {
59
+ "type": "half_float"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }