logstash-output-elasticsearch 12.0.1-java → 12.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/docs/index.asciidoc +18 -8
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +0 -1
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +1 -4
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +17 -20
- data/lib/logstash/outputs/elasticsearch/http_client.rb +25 -24
- data/lib/logstash/outputs/elasticsearch/ilm.rb +1 -11
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +1 -1
- data/lib/logstash/outputs/elasticsearch.rb +10 -45
- data/logstash-output-elasticsearch.gemspec +1 -1
- data/spec/es_spec_helper.rb +35 -27
- data/spec/integration/outputs/compressed_indexing_spec.rb +5 -5
- data/spec/integration/outputs/delete_spec.rb +4 -4
- data/spec/integration/outputs/ilm_spec.rb +18 -12
- data/spec/integration/outputs/index_spec.rb +7 -7
- data/spec/integration/outputs/index_version_spec.rb +7 -7
- data/spec/integration/outputs/no_es_on_startup_spec.rb +1 -1
- data/spec/integration/outputs/painless_update_spec.rb +11 -10
- data/spec/integration/outputs/parent_spec.rb +2 -3
- data/spec/integration/outputs/retry_spec.rb +2 -10
- data/spec/integration/outputs/sniffer_spec.rb +5 -40
- data/spec/integration/outputs/unsupported_actions_spec.rb +15 -10
- data/spec/integration/outputs/update_spec.rb +11 -9
- data/spec/spec_helper.rb +8 -0
- data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +0 -23
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +12 -54
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +3 -8
- data/spec/unit/outputs/elasticsearch_spec.rb +15 -17
- data/spec/unit/outputs/error_whitelist_spec.rb +0 -1
- metadata +2 -12
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-6x.json +0 -45
- data/lib/logstash/outputs/elasticsearch/templates/ecs-v1/elasticsearch-6x.json +0 -3695
- data/spec/fixtures/_nodes/6x.json +0 -81
- data/spec/fixtures/template-with-policy-es6x.json +0 -48
- data/spec/support/elasticsearch/api/actions/get_alias.rb +0 -18
- data/spec/support/elasticsearch/api/actions/put_alias.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5b6e330ff67352acd72041d917885768b47d2808bce5d116e555d61eb89e6b5
|
4
|
+
data.tar.gz: f450de9ab1542645aea2072702252d0c1ecba00110ebbf035571319e83dd1468
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14a820573d8d16ea69ad91e281c36a0c4c4aac863053596a50c72b065803f7e2afa3f849f662d185e2baebd089605c8dc77d445985ddf7a43afceb7e9d20b1be
|
7
|
+
data.tar.gz: 58b5159e08b621602b892f3ea7d7911f47f1236144e35980582e6dda511edd81350d850c3ae73abde6cd298c664f737ba0a64de61a5c35a963e40bec28f692f2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 12.0.3
|
2
|
+
- Demote connection log entry from WARN to INFO connection during register phase [#1211](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1211)
|
3
|
+
|
4
|
+
## 12.0.2
|
5
|
+
- Properly handle http code 413 (Payload Too Large) [#1199](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1199)
|
6
|
+
|
1
7
|
## 12.0.1
|
2
8
|
- Remove irrelevant log warning about elastic stack version [#1200](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1200)
|
3
9
|
|
data/docs/index.asciidoc
CHANGED
@@ -196,7 +196,22 @@ This plugin uses the Elasticsearch bulk API to optimize its imports into Elastic
|
|
196
196
|
either partial or total failures. The bulk API sends batches of requests to an HTTP endpoint. Error codes for the HTTP
|
197
197
|
request are handled differently than error codes for individual documents.
|
198
198
|
|
199
|
-
|
199
|
+
|
200
|
+
HTTP requests to the bulk API are expected to return a 200 response code. All other response codes are retried indefinitely,
|
201
|
+
including 413 (Payload Too Large) responses.
|
202
|
+
|
203
|
+
If you want to handle large payloads differently, you can configure 413 responses to go to the Dead Letter Queue instead:
|
204
|
+
|
205
|
+
[source,ruby]
|
206
|
+
-----
|
207
|
+
output {
|
208
|
+
elasticsearch {
|
209
|
+
hosts => ["localhost:9200"]
|
210
|
+
dlq_custom_codes => [413] # Send 413 errors to DLQ instead of retrying
|
211
|
+
}
|
212
|
+
-----
|
213
|
+
|
214
|
+
This will capture oversized payloads in the DLQ for analysis rather than retrying them.
|
200
215
|
|
201
216
|
The following document errors are handled as follows:
|
202
217
|
|
@@ -612,8 +627,7 @@ Elasticsearch with the same ID.
|
|
612
627
|
|
613
628
|
NOTE: This option is deprecated due to the
|
614
629
|
https://www.elastic.co/guide/en/elasticsearch/reference/6.0/removal-of-types.html[removal
|
615
|
-
of types in Elasticsearch 6.0].
|
616
|
-
Logstash.
|
630
|
+
of types in Elasticsearch 6.0].
|
617
631
|
|
618
632
|
NOTE: This value is ignored and has no effect for Elasticsearch clusters `8.x`.
|
619
633
|
|
@@ -622,9 +636,7 @@ similar events to the same 'type'. String expansion `%{foo}` works here.
|
|
622
636
|
If you don't set a value for this option:
|
623
637
|
|
624
638
|
- for elasticsearch clusters 8.x: no value will be used;
|
625
|
-
- for elasticsearch clusters 7.x: the value of '_doc' will be used
|
626
|
-
- for elasticsearch clusters 6.x: the value of 'doc' will be used;
|
627
|
-
- for elasticsearch clusters 5.x and below: the event's 'type' field will be used, if the field is not present the value of 'doc' will be used.
|
639
|
+
- for elasticsearch clusters 7.x: the value of '_doc' will be used.
|
628
640
|
|
629
641
|
[id="plugins-{type}s-{plugin}-ecs_compatibility"]
|
630
642
|
===== `ecs_compatibility`
|
@@ -1039,8 +1051,6 @@ NOTE: Deprecates <<plugins-{type}s-{plugin}-failure_type_logging_whitelist>>.
|
|
1039
1051
|
|
1040
1052
|
This setting asks Elasticsearch for the list of all cluster nodes and adds them
|
1041
1053
|
to the hosts list.
|
1042
|
-
For Elasticsearch 5.x and 6.x any nodes with `http.enabled` (on by default) will
|
1043
|
-
be added to the hosts list, excluding master-only nodes.
|
1044
1054
|
|
1045
1055
|
[id="plugins-{type}s-{plugin}-sniffing_delay"]
|
1046
1056
|
===== `sniffing_delay`
|
@@ -127,7 +127,6 @@ module LogStash module Outputs class ElasticSearch
|
|
127
127
|
value.to_s == 'true'
|
128
128
|
when 'manage_template'
|
129
129
|
value.to_s == 'false'
|
130
|
-
when 'ecs_compatibility' then true # required for LS <= 6.x
|
131
130
|
else
|
132
131
|
name.start_with?('data_stream_') ||
|
133
132
|
shared_params.include?(name) ||
|
@@ -76,11 +76,8 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
76
76
|
raise ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError.new(e, request_uri_as_string)
|
77
77
|
end
|
78
78
|
|
79
|
-
# 404s are excluded because they are valid codes in the case of
|
80
|
-
# template installation. We might need a better story around this later
|
81
|
-
# but for our current purposes this is correct
|
82
79
|
code = resp.code
|
83
|
-
if code < 200 || code > 299
|
80
|
+
if code < 200 || code > 299 # assume anything not 2xx is an error that the layer above needs to interpret
|
84
81
|
raise ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(code, request_uri, body, resp.body)
|
85
82
|
end
|
86
83
|
|
@@ -52,7 +52,6 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
52
52
|
ROOT_URI_PATH = '/'.freeze
|
53
53
|
LICENSE_PATH = '/_license'.freeze
|
54
54
|
|
55
|
-
VERSION_6_TO_7 = ::Gem::Requirement.new([">= 6.0.0", "< 7.0.0"])
|
56
55
|
VERSION_7_TO_7_14 = ::Gem::Requirement.new([">= 7.0.0", "< 7.14.0"])
|
57
56
|
|
58
57
|
DEFAULT_OPTIONS = {
|
@@ -253,13 +252,11 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
253
252
|
def health_check_request(url)
|
254
253
|
logger.debug("Running health check to see if an Elasticsearch connection is working",
|
255
254
|
:healthcheck_url => url.sanitized.to_s, :path => @healthcheck_path)
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
return nil, e
|
262
|
-
end
|
255
|
+
response = perform_request_to_url(url, :head, @healthcheck_path)
|
256
|
+
return response, nil
|
257
|
+
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
258
|
+
logger.warn("Health check failed", code: e.response_code, url: e.url, message: e.message)
|
259
|
+
return nil, e
|
263
260
|
end
|
264
261
|
|
265
262
|
def healthcheck!(register_phase = true)
|
@@ -289,7 +286,11 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
289
286
|
raise root_bad_code_err if root_bad_code_err
|
290
287
|
|
291
288
|
# If no exception was raised it must have succeeded!
|
292
|
-
|
289
|
+
if register_phase
|
290
|
+
logger.info("Connected to ES instance", url: url.sanitized.to_s)
|
291
|
+
else
|
292
|
+
logger.warn("Restored connection to ES instance", url: url.sanitized.to_s)
|
293
|
+
end
|
293
294
|
|
294
295
|
# We check its ES version
|
295
296
|
es_version, build_flavor = parse_es_version(root_response)
|
@@ -312,13 +313,11 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
312
313
|
end
|
313
314
|
|
314
315
|
def get_root_path(url, params={})
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
return nil, e
|
321
|
-
end
|
316
|
+
resp = perform_request_to_url(url, :get, ROOT_URI_PATH, params)
|
317
|
+
return resp, nil
|
318
|
+
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
319
|
+
logger.warn("Elasticsearch main endpoint returns #{e.response_code}", message: e.message, body: e.response_body)
|
320
|
+
return nil, e
|
322
321
|
end
|
323
322
|
|
324
323
|
def test_serverless_connection(url, root_response)
|
@@ -550,11 +549,9 @@ module LogStash; module Outputs; class ElasticSearch; class HttpClient;
|
|
550
549
|
return false if version_info['version'].nil?
|
551
550
|
|
552
551
|
version = ::Gem::Version.new(version_info["version"]['number'])
|
553
|
-
return false if version < ::Gem::Version.new('
|
552
|
+
return false if version < ::Gem::Version.new('7.0.0')
|
554
553
|
|
555
|
-
if
|
556
|
-
return valid_tagline?(version_info)
|
557
|
-
elsif VERSION_7_TO_7_14.satisfied_by?(version)
|
554
|
+
if VERSION_7_TO_7_14.satisfied_by?(version)
|
558
555
|
build_flavor = version_info["version"]['build_flavor']
|
559
556
|
return false if build_flavor.nil? || build_flavor != 'default' || !valid_tagline?(version_info)
|
560
557
|
else
|
@@ -182,22 +182,20 @@ module LogStash; module Outputs; class ElasticSearch;
|
|
182
182
|
def bulk_send(body_stream, batch_actions)
|
183
183
|
params = compression_level? ? {:headers => {"Content-Encoding" => "gzip"}} : {}
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
when 413 # Payload Too Large
|
185
|
+
begin
|
186
|
+
response = @pool.post(@bulk_path, params, body_stream.string)
|
187
|
+
@bulk_response_metrics.increment(response.code.to_s)
|
188
|
+
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
189
|
+
@bulk_response_metrics.increment(e.response_code.to_s)
|
190
|
+
raise e unless e.response_code == 413
|
191
|
+
# special handling for 413, treat it as a document level issue
|
193
192
|
logger.warn("Bulk request rejected: `413 Payload Too Large`", :action_count => batch_actions.size, :content_length => body_stream.size)
|
194
|
-
emulate_batch_error_response(batch_actions,
|
195
|
-
|
196
|
-
|
197
|
-
raise ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError.new(
|
198
|
-
response.code, url, body_stream.to_s, response.body
|
199
|
-
)
|
193
|
+
return emulate_batch_error_response(batch_actions, 413, 'payload_too_large')
|
194
|
+
rescue => e # it may be a network issue instead, re-raise
|
195
|
+
raise e
|
200
196
|
end
|
197
|
+
|
198
|
+
LogStash::Json.load(response.body)
|
201
199
|
end
|
202
200
|
|
203
201
|
def emulate_batch_error_response(actions, http_code, reason)
|
@@ -411,6 +409,9 @@ module LogStash; module Outputs; class ElasticSearch;
|
|
411
409
|
def exists?(path, use_get=false)
|
412
410
|
response = use_get ? @pool.get(path) : @pool.head(path)
|
413
411
|
response.code >= 200 && response.code <= 299
|
412
|
+
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
413
|
+
return false if e.response_code == 404
|
414
|
+
raise e
|
414
415
|
end
|
415
416
|
|
416
417
|
def template_exists?(template_endpoint, name)
|
@@ -421,6 +422,8 @@ module LogStash; module Outputs; class ElasticSearch;
|
|
421
422
|
path = "#{template_endpoint}/#{name}"
|
422
423
|
logger.info("Installing Elasticsearch template", name: name)
|
423
424
|
@pool.put(path, nil, LogStash::Json.dump(template))
|
425
|
+
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
426
|
+
raise e unless e.response_code == 404
|
424
427
|
end
|
425
428
|
|
426
429
|
# ILM methods
|
@@ -432,17 +435,15 @@ module LogStash; module Outputs; class ElasticSearch;
|
|
432
435
|
|
433
436
|
# Create a new rollover alias
|
434
437
|
def rollover_alias_put(alias_name, alias_definition)
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
return
|
443
|
-
end
|
444
|
-
raise e
|
438
|
+
@pool.put(CGI::escape(alias_name), nil, LogStash::Json.dump(alias_definition))
|
439
|
+
logger.info("Created rollover alias", name: alias_name)
|
440
|
+
# If the rollover alias already exists, ignore the error that comes back from Elasticsearch
|
441
|
+
rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
|
442
|
+
if e.response_code == 400
|
443
|
+
logger.info("Rollover alias already exists, skipping", name: alias_name)
|
444
|
+
return
|
445
445
|
end
|
446
|
+
raise e
|
446
447
|
end
|
447
448
|
|
448
449
|
def get_xpack_info
|
@@ -21,13 +21,7 @@ module LogStash; module Outputs; class ElasticSearch
|
|
21
21
|
"Serverless Elasticsearch cluster does not support Index Lifecycle Management.") if @ilm_enabled == 'auto'
|
22
22
|
false
|
23
23
|
elsif @ilm_enabled == 'auto'
|
24
|
-
|
25
|
-
ilm_alias_set?
|
26
|
-
else
|
27
|
-
@logger.info("ILM auto configuration (`ilm_enabled => auto` or unset) resolved to `false`."\
|
28
|
-
" Elasticsearch cluster is before 7.0.0, which is the minimum version required to automatically run Index Lifecycle Management")
|
29
|
-
false
|
30
|
-
end
|
24
|
+
ilm_alias_set?
|
31
25
|
elsif @ilm_enabled.to_s == 'true'
|
32
26
|
ilm_alias_set?
|
33
27
|
else
|
@@ -42,10 +36,6 @@ module LogStash; module Outputs; class ElasticSearch
|
|
42
36
|
default_index?(@index) || !default_rollover_alias?(@ilm_rollover_alias)
|
43
37
|
end
|
44
38
|
|
45
|
-
def ilm_on_by_default?
|
46
|
-
maximum_seen_major_version >= 7
|
47
|
-
end
|
48
|
-
|
49
39
|
def default_index?(index)
|
50
40
|
index == @default_index
|
51
41
|
end
|
@@ -47,7 +47,7 @@ module LogStash; module Outputs; class ElasticSearch
|
|
47
47
|
def self.add_ilm_settings_to_template(plugin, template)
|
48
48
|
# Overwrite any index patterns, and use the rollover alias. Use 'index_patterns' rather than 'template' for pattern
|
49
49
|
# definition - remove any existing definition of 'template'
|
50
|
-
template.delete('template') if template.include?('template') if plugin.maximum_seen_major_version
|
50
|
+
template.delete('template') if template.include?('template') if plugin.maximum_seen_major_version == 7
|
51
51
|
template['index_patterns'] = "#{plugin.ilm_rollover_alias}-*"
|
52
52
|
settings = resolve_template_settings(plugin, template)
|
53
53
|
if settings && (settings['index.lifecycle.name'] || settings['index.lifecycle.rollover_alias'])
|
@@ -14,39 +14,16 @@ require "set"
|
|
14
14
|
# .Compatibility Note
|
15
15
|
# [NOTE]
|
16
16
|
# ================================================================================
|
17
|
-
# Starting with Elasticsearch 5.3, there's an {ref}modules-http.html[HTTP setting]
|
18
|
-
# called `http.content_type.required`. If this option is set to `true`, and you
|
19
|
-
# are using Logstash 2.4 through 5.2, you need to update the Elasticsearch output
|
20
|
-
# plugin to version 6.2.5 or higher.
|
21
|
-
#
|
22
|
-
# ================================================================================
|
23
17
|
#
|
24
18
|
# This plugin is the recommended method of storing logs in Elasticsearch.
|
25
19
|
# If you plan on using the Kibana web interface, you'll want to use this output.
|
26
20
|
#
|
27
|
-
# This output only speaks the HTTP protocol.
|
28
|
-
# We strongly encourage the use of HTTP over the node protocol for a number of reasons. HTTP is only marginally slower,
|
29
|
-
# yet far easier to administer and work with. When using the HTTP protocol one may upgrade Elasticsearch versions without having
|
30
|
-
# to upgrade Logstash in lock-step.
|
21
|
+
# This output only speaks the HTTP protocol.
|
31
22
|
#
|
32
23
|
# You can learn more about Elasticsearch at <https://www.elastic.co/products/elasticsearch>
|
33
24
|
#
|
34
|
-
# ==== Template management for Elasticsearch 5.x
|
35
|
-
# Index template for this version (Logstash 5.0) has been changed to reflect Elasticsearch's mapping changes in version 5.0.
|
36
|
-
# Most importantly, the subfield for string multi-fields has changed from `.raw` to `.keyword` to match ES default
|
37
|
-
# behavior.
|
38
|
-
#
|
39
|
-
# ** Users installing ES 5.x and LS 5.x **
|
40
|
-
# This change will not affect you and you will continue to use the ES defaults.
|
41
|
-
#
|
42
|
-
# ** Users upgrading from LS 2.x to LS 5.x with ES 5.x **
|
43
|
-
# LS will not force upgrade the template, if `logstash` template already exists. This means you will still use
|
44
|
-
# `.raw` for sub-fields coming from 2.x. If you choose to use the new template, you will have to reindex your data after
|
45
|
-
# the new template is installed.
|
46
|
-
#
|
47
25
|
# ==== Retry Policy
|
48
26
|
#
|
49
|
-
# The retry policy has changed significantly in the 2.2.0 release.
|
50
27
|
# This plugin uses the Elasticsearch bulk API to optimize its imports into Elasticsearch. These requests may experience
|
51
28
|
# either partial or total failures.
|
52
29
|
#
|
@@ -129,8 +106,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
129
106
|
# - delete: deletes a document by id (An id is required for this action)
|
130
107
|
# - create: indexes a document, fails if a document by that id already exists in the index.
|
131
108
|
# - update: updates a document by id. Update has a special case where you can upsert -- update a
|
132
|
-
# document if not already present. See the `upsert` option.
|
133
|
-
# in Elasticsearch 1.x. Please upgrade to ES 2.x or greater to use this feature with Logstash!
|
109
|
+
# document if not already present. See the `upsert` option.
|
134
110
|
# - A sprintf style string to change the action based on the content of the event. The value `%{[foo]}`
|
135
111
|
# would use the foo field for the action
|
136
112
|
#
|
@@ -148,7 +124,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
148
124
|
|
149
125
|
config :document_type,
|
150
126
|
:validate => :string,
|
151
|
-
:deprecated => "Document types
|
127
|
+
:deprecated => "Document types were deprecated in Elasticsearch 7.0, and no longer configurable since 8.0. You should avoid this feature."
|
152
128
|
|
153
129
|
# From Logstash 1.3 onwards, a template is applied to Elasticsearch during
|
154
130
|
# Logstash's startup if one with the name `template_name` does not already exist.
|
@@ -483,7 +459,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
483
459
|
join_value = event.get(@join_field)
|
484
460
|
parent_value = event.sprintf(@parent)
|
485
461
|
event.set(@join_field, { "name" => join_value, "parent" => parent_value })
|
486
|
-
params[
|
462
|
+
params[:routing] = event.sprintf(@parent)
|
487
463
|
else
|
488
464
|
params[:parent] = event.sprintf(@parent)
|
489
465
|
end
|
@@ -495,7 +471,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
495
471
|
if action == 'update'
|
496
472
|
params[:_upsert] = LogStash::Json.load(event.sprintf(@upsert)) if @upsert != ""
|
497
473
|
params[:_script] = event.sprintf(@script) if @script != ""
|
498
|
-
params[
|
474
|
+
params[:retry_on_conflict] = @retry_on_conflict
|
499
475
|
end
|
500
476
|
|
501
477
|
event_control = event.get("[@metadata][_ingest_document]")
|
@@ -552,7 +528,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
552
528
|
params = {
|
553
529
|
:_id => resolve_document_id(event, event_id),
|
554
530
|
:_index => resolve_index!(event, event_index),
|
555
|
-
|
531
|
+
:routing => resolve_routing(event, event_routing)
|
556
532
|
}
|
557
533
|
|
558
534
|
target_pipeline = resolve_pipeline(event, event_pipeline)
|
@@ -615,16 +591,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
615
591
|
require "logstash/outputs/elasticsearch/#{name}"
|
616
592
|
end
|
617
593
|
|
618
|
-
def retry_on_conflict_action_name
|
619
|
-
maximum_seen_major_version >= 7 ? :retry_on_conflict : :_retry_on_conflict
|
620
|
-
end
|
621
|
-
|
622
|
-
def routing_field_name
|
623
|
-
:routing
|
624
|
-
end
|
625
|
-
|
626
594
|
# Determine the correct value for the 'type' field for the given event
|
627
|
-
DEFAULT_EVENT_TYPE_ES6 = "doc".freeze
|
628
595
|
DEFAULT_EVENT_TYPE_ES7 = "_doc".freeze
|
629
596
|
|
630
597
|
def get_event_type(event)
|
@@ -633,9 +600,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
633
600
|
event.sprintf(@document_type)
|
634
601
|
else
|
635
602
|
major_version = maximum_seen_major_version
|
636
|
-
if major_version ==
|
637
|
-
DEFAULT_EVENT_TYPE_ES6
|
638
|
-
elsif major_version == 7
|
603
|
+
if major_version == 7
|
639
604
|
DEFAULT_EVENT_TYPE_ES7
|
640
605
|
else
|
641
606
|
nil
|
@@ -653,9 +618,9 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
653
618
|
# @param noop_required_client [nil]: required `nil` for legacy reasons.
|
654
619
|
# @return [Boolean]
|
655
620
|
def use_event_type?(noop_required_client)
|
656
|
-
#
|
657
|
-
#
|
658
|
-
|
621
|
+
# never use event type unless
|
622
|
+
# ES is 7.x and the user defined it
|
623
|
+
maximum_seen_major_version == 7 && @document_type
|
659
624
|
end
|
660
625
|
|
661
626
|
def install_template
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-elasticsearch'
|
3
|
-
s.version = '12.0.
|
3
|
+
s.version = '12.0.3'
|
4
4
|
s.licenses = ['apache-2.0']
|
5
5
|
s.summary = "Stores logs in Elasticsearch"
|
6
6
|
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
|
data/spec/es_spec_helper.rb
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
require_relative './spec_helper'
|
2
2
|
|
3
3
|
require 'elasticsearch'
|
4
|
-
require_relative "support/elasticsearch/api/actions/delete_ilm_policy"
|
5
|
-
require_relative "support/elasticsearch/api/actions/get_alias"
|
6
|
-
require_relative "support/elasticsearch/api/actions/put_alias"
|
7
|
-
require_relative "support/elasticsearch/api/actions/get_ilm_policy"
|
8
|
-
require_relative "support/elasticsearch/api/actions/put_ilm_policy"
|
9
4
|
|
10
5
|
require 'json'
|
11
6
|
require 'cabin'
|
12
7
|
|
8
|
+
# remove this condition and support package once plugin starts consuming elasticsearch-ruby v8 client
|
9
|
+
# in elasticsearch-ruby v7, ILM APIs were in a separate xpack gem, now directly available
|
10
|
+
unless elastic_ruby_v8_client_available?
|
11
|
+
require_relative "support/elasticsearch/api/actions/delete_ilm_policy"
|
12
|
+
require_relative "support/elasticsearch/api/actions/get_ilm_policy"
|
13
|
+
require_relative "support/elasticsearch/api/actions/put_ilm_policy"
|
14
|
+
end
|
15
|
+
|
13
16
|
module ESHelper
|
14
17
|
def get_host_port
|
15
18
|
if ENV["INTEGRATION"] == "true"
|
@@ -20,8 +23,12 @@ module ESHelper
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def get_client
|
23
|
-
|
24
|
-
|
26
|
+
if elastic_ruby_v8_client_available?
|
27
|
+
Elasticsearch::Client.new(:hosts => [get_host_port])
|
28
|
+
else
|
29
|
+
Elasticsearch::Client.new(:hosts => [get_host_port]).tap do |client|
|
30
|
+
allow(client).to receive(:verify_elasticsearch).and_return(true) # bypass client side version checking
|
31
|
+
end
|
25
32
|
end
|
26
33
|
end
|
27
34
|
|
@@ -30,8 +37,6 @@ module ESHelper
|
|
30
37
|
nil
|
31
38
|
elsif ESHelper.es_version_satisfies?(">=7")
|
32
39
|
"_doc"
|
33
|
-
else
|
34
|
-
"doc"
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
@@ -70,7 +75,7 @@ module ESHelper
|
|
70
75
|
end
|
71
76
|
|
72
77
|
RSpec::Matchers.define :have_hits do |expected|
|
73
|
-
hits_count_path =
|
78
|
+
hits_count_path = %w(hits total value)
|
74
79
|
|
75
80
|
match do |actual|
|
76
81
|
@actual_hits_count = actual&.dig(*hits_count_path)
|
@@ -128,31 +133,36 @@ module ESHelper
|
|
128
133
|
end
|
129
134
|
|
130
135
|
def get_policy(client, policy_name)
|
131
|
-
|
136
|
+
if elastic_ruby_v8_client_available?
|
137
|
+
client.index_lifecycle_management.get_lifecycle(policy: policy_name)
|
138
|
+
else
|
139
|
+
client.get_ilm_policy(name: policy_name)
|
140
|
+
end
|
132
141
|
end
|
133
142
|
|
134
143
|
def put_policy(client, policy_name, policy)
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
"aliases" => {
|
141
|
-
index => {
|
142
|
-
"is_write_index"=> true
|
143
|
-
}
|
144
|
-
}
|
145
|
-
}
|
146
|
-
client.put_alias({name: the_alias, body: body})
|
144
|
+
if elastic_ruby_v8_client_available?
|
145
|
+
client.index_lifecycle_management.put_lifecycle({:policy => policy_name, :body=> policy})
|
146
|
+
else
|
147
|
+
client.put_ilm_policy({:name => policy_name, :body=> policy})
|
148
|
+
end
|
147
149
|
end
|
148
150
|
|
149
151
|
def clean_ilm(client)
|
150
|
-
|
152
|
+
if elastic_ruby_v8_client_available?
|
153
|
+
client.index_lifecycle_management.get_lifecycle.each_key { |key| client.index_lifecycle_management.delete_lifecycle(policy: key) if key =~ /logstash-policy/ }
|
154
|
+
else
|
155
|
+
client.get_ilm_policy.each_key { |key| client.delete_ilm_policy(name: key) if key =~ /logstash-policy/ }
|
156
|
+
end
|
151
157
|
end
|
152
158
|
|
153
159
|
def supports_ilm?(client)
|
154
160
|
begin
|
155
|
-
|
161
|
+
if elastic_ruby_v8_client_available?
|
162
|
+
client.index_lifecycle_management.get_lifecycle
|
163
|
+
else
|
164
|
+
client.get_ilm_policy
|
165
|
+
end
|
156
166
|
true
|
157
167
|
rescue
|
158
168
|
false
|
@@ -214,8 +224,6 @@ module ESHelper
|
|
214
224
|
template['template']['mappings']
|
215
225
|
elsif ESHelper.es_version_satisfies?(">=7")
|
216
226
|
template['mappings']
|
217
|
-
else
|
218
|
-
template['mappings']["_default_"]
|
219
227
|
end
|
220
228
|
end
|
221
229
|
end
|
@@ -14,7 +14,7 @@ end
|
|
14
14
|
let(:event_with_invalid_utf_8_bytes) { LogStash::Event.new("message" => "Message from spacecraft which contains \xAC invalid \xD7 byte sequences.", "type" => type) }
|
15
15
|
|
16
16
|
let(:index) { 10.times.collect { rand(10).to_s }.join("") }
|
17
|
-
let(:type) {
|
17
|
+
let(:type) { "_doc" }
|
18
18
|
let(:event_count) { 10000 + rand(500) }
|
19
19
|
# mix the events with valid and invalid UTF-8 payloads
|
20
20
|
let(:events) { event_count.times.map { |i| i%3 == 0 ? event : event_with_invalid_utf_8_bytes }.to_a }
|
@@ -59,10 +59,10 @@ end
|
|
59
59
|
response = http_client.get("#{index_url}/_search?q=*&size=1000")
|
60
60
|
result = LogStash::Json.load(response.body)
|
61
61
|
result["hits"]["hits"].each do |doc|
|
62
|
-
if ESHelper.es_version_satisfies?("
|
63
|
-
expect(doc["_type"]).to eq(type)
|
64
|
-
else
|
62
|
+
if ESHelper.es_version_satisfies?(">= 8")
|
65
63
|
expect(doc).not_to include("_type")
|
64
|
+
else
|
65
|
+
expect(doc["_type"]).to eq(type)
|
66
66
|
end
|
67
67
|
expect(doc["_index"]).to eq(index)
|
68
68
|
end
|
@@ -78,4 +78,4 @@ end
|
|
78
78
|
|
79
79
|
it_behaves_like("an indexer")
|
80
80
|
end
|
81
|
-
end
|
81
|
+
end
|
@@ -39,12 +39,12 @@ describe "Versioned delete", :integration => true do
|
|
39
39
|
it "should ignore non-monotonic external version updates" do
|
40
40
|
id = "ev2"
|
41
41
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "index", "message" => "foo", "my_version" => 99)])
|
42
|
-
r = es.get(:index => 'logstash-delete', :
|
42
|
+
r = es.get(:index => 'logstash-delete', :id => id, :refresh => true)
|
43
43
|
expect(r['_version']).to eq(99)
|
44
44
|
expect(r['_source']['message']).to eq('foo')
|
45
45
|
|
46
46
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "delete", "message" => "foo", "my_version" => 98)])
|
47
|
-
r2 = es.get(:index => 'logstash-delete', :
|
47
|
+
r2 = es.get(:index => 'logstash-delete', :id => id, :refresh => true)
|
48
48
|
expect(r2['_version']).to eq(99)
|
49
49
|
expect(r2['_source']['message']).to eq('foo')
|
50
50
|
end
|
@@ -52,12 +52,12 @@ describe "Versioned delete", :integration => true do
|
|
52
52
|
it "should commit monotonic external version updates" do
|
53
53
|
id = "ev3"
|
54
54
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "index", "message" => "foo", "my_version" => 99)])
|
55
|
-
r = es.get(:index => 'logstash-delete', :
|
55
|
+
r = es.get(:index => 'logstash-delete', :id => id, :refresh => true)
|
56
56
|
expect(r['_version']).to eq(99)
|
57
57
|
expect(r['_source']['message']).to eq('foo')
|
58
58
|
|
59
59
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "delete", "message" => "foo", "my_version" => 100)])
|
60
|
-
expect { es.get(:index => 'logstash-delete', :
|
60
|
+
expect { es.get(:index => 'logstash-delete', :id => id, :refresh => true) }.to raise_error(get_expected_error_class)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|