logstash-output-elasticsearch-test 10.3.0-x86_64-linux

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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +397 -0
  3. data/CONTRIBUTORS +33 -0
  4. data/Gemfile +15 -0
  5. data/LICENSE +13 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +106 -0
  8. data/docs/index.asciidoc +899 -0
  9. data/lib/logstash/outputs/elasticsearch/common.rb +441 -0
  10. data/lib/logstash/outputs/elasticsearch/common_configs.rb +167 -0
  11. data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
  12. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es2x.json +95 -0
  13. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es5x.json +46 -0
  14. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es6x.json +45 -0
  15. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es7x.json +44 -0
  16. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es8x.json +44 -0
  17. data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +131 -0
  18. data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +495 -0
  19. data/lib/logstash/outputs/elasticsearch/http_client.rb +432 -0
  20. data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +159 -0
  21. data/lib/logstash/outputs/elasticsearch/ilm.rb +113 -0
  22. data/lib/logstash/outputs/elasticsearch/template_manager.rb +61 -0
  23. data/lib/logstash/outputs/elasticsearch.rb +263 -0
  24. data/logstash-output-elasticsearch.gemspec +33 -0
  25. data/spec/es_spec_helper.rb +189 -0
  26. data/spec/fixtures/_nodes/2x_1x.json +27 -0
  27. data/spec/fixtures/_nodes/5x_6x.json +81 -0
  28. data/spec/fixtures/_nodes/7x.json +92 -0
  29. data/spec/fixtures/htpasswd +2 -0
  30. data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
  31. data/spec/fixtures/scripts/groovy/scripted_update.groovy +2 -0
  32. data/spec/fixtures/scripts/groovy/scripted_update_nested.groovy +2 -0
  33. data/spec/fixtures/scripts/groovy/scripted_upsert.groovy +2 -0
  34. data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
  35. data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
  36. data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
  37. data/spec/fixtures/template-with-policy-es6x.json +48 -0
  38. data/spec/fixtures/template-with-policy-es7x.json +45 -0
  39. data/spec/fixtures/test_certs/ca/ca.crt +32 -0
  40. data/spec/fixtures/test_certs/ca/ca.key +51 -0
  41. data/spec/fixtures/test_certs/test.crt +36 -0
  42. data/spec/fixtures/test_certs/test.key +51 -0
  43. data/spec/integration/outputs/compressed_indexing_spec.rb +69 -0
  44. data/spec/integration/outputs/create_spec.rb +67 -0
  45. data/spec/integration/outputs/delete_spec.rb +65 -0
  46. data/spec/integration/outputs/groovy_update_spec.rb +150 -0
  47. data/spec/integration/outputs/ilm_spec.rb +531 -0
  48. data/spec/integration/outputs/index_spec.rb +178 -0
  49. data/spec/integration/outputs/index_version_spec.rb +102 -0
  50. data/spec/integration/outputs/ingest_pipeline_spec.rb +74 -0
  51. data/spec/integration/outputs/metrics_spec.rb +70 -0
  52. data/spec/integration/outputs/no_es_on_startup_spec.rb +58 -0
  53. data/spec/integration/outputs/painless_update_spec.rb +189 -0
  54. data/spec/integration/outputs/parent_spec.rb +102 -0
  55. data/spec/integration/outputs/retry_spec.rb +169 -0
  56. data/spec/integration/outputs/routing_spec.rb +61 -0
  57. data/spec/integration/outputs/sniffer_spec.rb +133 -0
  58. data/spec/integration/outputs/templates_5x_spec.rb +98 -0
  59. data/spec/integration/outputs/templates_spec.rb +98 -0
  60. data/spec/integration/outputs/update_spec.rb +116 -0
  61. data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
  62. data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
  63. data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
  64. data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
  65. data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
  66. data/spec/unit/http_client_builder_spec.rb +185 -0
  67. data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +149 -0
  68. data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +274 -0
  69. data/spec/unit/outputs/elasticsearch/http_client_spec.rb +250 -0
  70. data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +25 -0
  71. data/spec/unit/outputs/elasticsearch_proxy_spec.rb +72 -0
  72. data/spec/unit/outputs/elasticsearch_spec.rb +675 -0
  73. data/spec/unit/outputs/elasticsearch_ssl_spec.rb +82 -0
  74. data/spec/unit/outputs/error_whitelist_spec.rb +54 -0
  75. metadata +300 -0
@@ -0,0 +1,441 @@
1
+ require "logstash/outputs/elasticsearch/template_manager"
2
+
3
+ module LogStash; module Outputs; class ElasticSearch;
4
+ module Common
5
+ attr_reader :client, :hosts
6
+
7
+ # These codes apply to documents, not at the request level
8
+ DOC_DLQ_CODES = [400, 404]
9
+ DOC_SUCCESS_CODES = [200, 201]
10
+ DOC_CONFLICT_CODE = 409
11
+
12
+ # When you use external versioning, you are communicating that you want
13
+ # to ignore conflicts. More obviously, since an external version is a
14
+ # constant part of the incoming document, we should not retry, as retrying
15
+ # will never succeed.
16
+ VERSION_TYPES_PERMITTING_CONFLICT = ["external", "external_gt", "external_gte"]
17
+
18
+ def register
19
+ @template_installed = Concurrent::AtomicBoolean.new(false)
20
+ @stopping = Concurrent::AtomicBoolean.new(false)
21
+ # To support BWC, we check if DLQ exists in core (< 5.4). If it doesn't, we use nil to resort to previous behavior.
22
+ @dlq_writer = dlq_enabled? ? execution_context.dlq_writer : nil
23
+
24
+ fill_hosts_from_cloud_id
25
+ fill_user_password_from_cloud_auth
26
+ setup_hosts # properly sets @hosts
27
+ build_client
28
+ setup_after_successful_connection
29
+ check_action_validity
30
+ @bulk_request_metrics = metric.namespace(:bulk_requests)
31
+ @document_level_metrics = metric.namespace(:documents)
32
+ @logger.info("New Elasticsearch output", :class => self.class.name, :hosts => @hosts.map(&:sanitized).map(&:to_s))
33
+ end
34
+
35
+ # Receive an array of events and immediately attempt to index them (no buffering)
36
+ def multi_receive(events)
37
+ until @template_installed.true?
38
+ sleep 1
39
+ end
40
+ retrying_submit(events.map {|e| event_action_tuple(e)})
41
+ end
42
+
43
+ def setup_after_successful_connection
44
+ @template_installer ||= Thread.new do
45
+ sleep_interval = @retry_initial_interval
46
+ until successful_connection? || @stopping.true?
47
+ @logger.debug("Waiting for connectivity to Elasticsearch cluster. Retrying in #{sleep_interval}s")
48
+ Stud.stoppable_sleep(sleep_interval) { @stopping.true? }
49
+ sleep_interval = next_sleep_interval(sleep_interval)
50
+ end
51
+ if successful_connection?
52
+ discover_cluster_uuid
53
+ install_template
54
+ setup_ilm if ilm_in_use?
55
+ end
56
+ end
57
+ end
58
+
59
+ def stop_template_installer
60
+ @template_installer.join unless @template_installer.nil?
61
+ end
62
+
63
+ def successful_connection?
64
+ !!maximum_seen_major_version
65
+ end
66
+
67
+ def use_event_type?(client)
68
+ client.maximum_seen_major_version < 8
69
+ end
70
+
71
+ # Convert the event into a 3-tuple of action, params, and event
72
+ def event_action_tuple(event)
73
+ action = event.sprintf(@action)
74
+
75
+ params = {
76
+ :_id => @document_id ? event.sprintf(@document_id) : nil,
77
+ :_index => event.sprintf(@index),
78
+ routing_field_name => @routing ? event.sprintf(@routing) : nil
79
+ }
80
+
81
+ params[:_type] = get_event_type(event) if use_event_type?(client)
82
+
83
+ if @pipeline
84
+ params[:pipeline] = event.sprintf(@pipeline)
85
+ end
86
+
87
+ if @parent
88
+ if @join_field
89
+ join_value = event.get(@join_field)
90
+ parent_value = event.sprintf(@parent)
91
+ event.set(@join_field, { "name" => join_value, "parent" => parent_value })
92
+ params[routing_field_name] = event.sprintf(@parent)
93
+ else
94
+ params[:parent] = event.sprintf(@parent)
95
+ end
96
+ end
97
+
98
+ if action == 'update'
99
+ params[:_upsert] = LogStash::Json.load(event.sprintf(@upsert)) if @upsert != ""
100
+ params[:_script] = event.sprintf(@script) if @script != ""
101
+ params[retry_on_conflict_action_name] = @retry_on_conflict
102
+ end
103
+
104
+ if @version
105
+ params[:version] = event.sprintf(@version)
106
+ end
107
+
108
+ if @version_type
109
+ params[:version_type] = event.sprintf(@version_type)
110
+ end
111
+
112
+ [action, params, event]
113
+ end
114
+
115
+ def setup_hosts
116
+ @hosts = Array(@hosts)
117
+ if @hosts.empty?
118
+ @logger.info("No 'host' set in elasticsearch output. Defaulting to localhost")
119
+ @hosts.replace(["localhost"])
120
+ end
121
+ end
122
+
123
+ def hosts_default?(hosts)
124
+ # NOTE: would be nice if pipeline allowed us a clean way to detect a config default :
125
+ hosts.is_a?(Array) && hosts.size == 1 && hosts.first.equal?(CommonConfigs::DEFAULT_HOST)
126
+ end
127
+ private :hosts_default?
128
+
129
+ def fill_hosts_from_cloud_id
130
+ return unless @cloud_id
131
+
132
+ if @hosts && !hosts_default?(@hosts)
133
+ raise LogStash::ConfigurationError, 'Both cloud_id and hosts specified, please only use one of those.'
134
+ end
135
+ @hosts = parse_host_uri_from_cloud_id(@cloud_id)
136
+ end
137
+
138
+ def fill_user_password_from_cloud_auth
139
+ return unless @cloud_auth
140
+
141
+ if @user || @password
142
+ raise LogStash::ConfigurationError, 'Both cloud_auth and user/password specified, please only use one.'
143
+ end
144
+ @user, @password = parse_user_password_from_cloud_auth(@cloud_auth)
145
+ params['user'], params['password'] = @user, @password
146
+ end
147
+
148
+ def parse_host_uri_from_cloud_id(cloud_id)
149
+ begin # might not be available on older LS
150
+ require 'logstash/util/cloud_setting_id'
151
+ rescue LoadError
152
+ raise LogStash::ConfigurationError, 'The cloud_id setting is not supported by your version of Logstash, ' +
153
+ 'please upgrade your installation (or set hosts instead).'
154
+ end
155
+
156
+ begin
157
+ cloud_id = LogStash::Util::CloudSettingId.new(cloud_id) # already does append ':{port}' to host
158
+ rescue ArgumentError => e
159
+ raise LogStash::ConfigurationError, e.message.to_s.sub(/Cloud Id/i, 'cloud_id')
160
+ end
161
+ cloud_uri = "#{cloud_id.elasticsearch_scheme}://#{cloud_id.elasticsearch_host}"
162
+ LogStash::Util::SafeURI.new(cloud_uri)
163
+ end
164
+ private :parse_host_uri_from_cloud_id
165
+
166
+ def parse_user_password_from_cloud_auth(cloud_auth)
167
+ begin # might not be available on older LS
168
+ require 'logstash/util/cloud_setting_auth'
169
+ rescue LoadError
170
+ raise LogStash::ConfigurationError, 'The cloud_auth setting is not supported by your version of Logstash, ' +
171
+ 'please upgrade your installation (or set user/password instead).'
172
+ end
173
+
174
+ cloud_auth = cloud_auth.value if cloud_auth.is_a?(LogStash::Util::Password)
175
+ begin
176
+ cloud_auth = LogStash::Util::CloudSettingAuth.new(cloud_auth)
177
+ rescue ArgumentError => e
178
+ raise LogStash::ConfigurationError, e.message.to_s.sub(/Cloud Auth/i, 'cloud_auth')
179
+ end
180
+ [ cloud_auth.username, cloud_auth.password ]
181
+ end
182
+ private :parse_user_password_from_cloud_auth
183
+
184
+ def maximum_seen_major_version
185
+ client.maximum_seen_major_version
186
+ end
187
+
188
+ def routing_field_name
189
+ maximum_seen_major_version >= 6 ? :routing : :_routing
190
+ end
191
+
192
+ def retry_on_conflict_action_name
193
+ maximum_seen_major_version >= 7 ? :retry_on_conflict : :_retry_on_conflict
194
+ end
195
+
196
+ def install_template
197
+ TemplateManager.install_template(self)
198
+ @template_installed.make_true
199
+ end
200
+
201
+ def discover_cluster_uuid
202
+ return unless defined?(plugin_metadata)
203
+ cluster_info = client.get('/')
204
+ plugin_metadata.set(:cluster_uuid, cluster_info['cluster_uuid'])
205
+ rescue => e
206
+ # TODO introducing this logging message breaks many tests that need refactoring
207
+ # @logger.error("Unable to retrieve elasticsearch cluster uuid", error => e.message)
208
+ end
209
+
210
+ def check_action_validity
211
+ raise LogStash::ConfigurationError, "No action specified!" unless @action
212
+
213
+ # If we're using string interpolation, we're good!
214
+ return if @action =~ /%{.+}/
215
+ return if valid_actions.include?(@action)
216
+
217
+ raise LogStash::ConfigurationError, "Action '#{@action}' is invalid! Pick one of #{valid_actions} or use a sprintf style statement"
218
+ end
219
+
220
+ # To be overidden by the -java version
221
+ VALID_HTTP_ACTIONS=["index", "delete", "create", "update"]
222
+ def valid_actions
223
+ VALID_HTTP_ACTIONS
224
+ end
225
+
226
+ def retrying_submit(actions)
227
+ # Initially we submit the full list of actions
228
+ submit_actions = actions
229
+
230
+ sleep_interval = @retry_initial_interval
231
+
232
+ while submit_actions && submit_actions.length > 0
233
+
234
+ # We retry with whatever is didn't succeed
235
+ begin
236
+ submit_actions = submit(submit_actions)
237
+ if submit_actions && submit_actions.size > 0
238
+ @logger.info("Retrying individual bulk actions that failed or were rejected by the previous bulk request.", :count => submit_actions.size)
239
+ end
240
+ rescue => e
241
+ @logger.error("Encountered an unexpected error submitting a bulk request! Will retry.",
242
+ :error_message => e.message,
243
+ :class => e.class.name,
244
+ :backtrace => e.backtrace)
245
+ end
246
+
247
+ # Everything was a success!
248
+ break if !submit_actions || submit_actions.empty?
249
+
250
+ # If we're retrying the action sleep for the recommended interval
251
+ # Double the interval for the next time through to achieve exponential backoff
252
+ Stud.stoppable_sleep(sleep_interval) { @stopping.true? }
253
+ sleep_interval = next_sleep_interval(sleep_interval)
254
+ end
255
+ end
256
+
257
+ def sleep_for_interval(sleep_interval)
258
+ Stud.stoppable_sleep(sleep_interval) { @stopping.true? }
259
+ next_sleep_interval(sleep_interval)
260
+ end
261
+
262
+ def next_sleep_interval(current_interval)
263
+ doubled = current_interval * 2
264
+ doubled > @retry_max_interval ? @retry_max_interval : doubled
265
+ end
266
+
267
+ def submit(actions)
268
+ bulk_response = safe_bulk(actions)
269
+
270
+ # If the response is nil that means we were in a retry loop
271
+ # and aborted since we're shutting down
272
+ return if bulk_response.nil?
273
+
274
+ # If it did return and there are no errors we're good as well
275
+ if bulk_response["errors"]
276
+ @bulk_request_metrics.increment(:with_errors)
277
+ else
278
+ @bulk_request_metrics.increment(:successes)
279
+ @document_level_metrics.increment(:successes, actions.size)
280
+ return
281
+ end
282
+
283
+ actions_to_retry = []
284
+ bulk_response["items"].each_with_index do |response,idx|
285
+ action_type, action_props = response.first
286
+
287
+ status = action_props["status"]
288
+ failure = action_props["error"]
289
+ action = actions[idx]
290
+ action_params = action[1]
291
+
292
+ # Retry logic: If it is success, we move on. If it is a failure, we have 3 paths:
293
+ # - For 409, we log and drop. there is nothing we can do
294
+ # - For a mapping error, we send to dead letter queue for a human to intervene at a later point.
295
+ # - For everything else there's mastercard. Yep, and we retry indefinitely. This should fix #572 and other transient network issues
296
+ if DOC_SUCCESS_CODES.include?(status)
297
+ @document_level_metrics.increment(:successes)
298
+ next
299
+ elsif DOC_CONFLICT_CODE == status
300
+ @document_level_metrics.increment(:non_retryable_failures)
301
+ @logger.warn "Failed action.", status: status, action: action, response: response if !failure_type_logging_whitelist.include?(failure["type"])
302
+ next
303
+ elsif DOC_DLQ_CODES.include?(status)
304
+ handle_dlq_status("Could not index event to Elasticsearch.", action, status, response)
305
+ @document_level_metrics.increment(:non_retryable_failures)
306
+ next
307
+ else
308
+ # only log what the user whitelisted
309
+ @document_level_metrics.increment(:retryable_failures)
310
+ @logger.info "retrying failed action with response code: #{status} (#{failure})" if !failure_type_logging_whitelist.include?(failure["type"])
311
+ actions_to_retry << action
312
+ end
313
+ end
314
+
315
+ actions_to_retry
316
+ end
317
+
318
+ def handle_dlq_status(message, action, status, response)
319
+ # To support bwc, we check if DLQ exists. otherwise we log and drop event (previous behavior)
320
+ if @dlq_writer
321
+ # TODO: Change this to send a map with { :status => status, :action => action } in the future
322
+ @dlq_writer.write(action[2], "#{message} status: #{status}, action: #{action}, response: #{response}")
323
+ else
324
+ error_type = response.fetch('index', {}).fetch('error', {})['type']
325
+ if 'invalid_index_name_exception' == error_type
326
+ level = :error
327
+ else
328
+ level = :warn
329
+ end
330
+ @logger.send level, message, status: status, action: action, response: response
331
+ end
332
+ end
333
+
334
+ # Determine the correct value for the 'type' field for the given event
335
+ DEFAULT_EVENT_TYPE_ES6="doc".freeze
336
+ DEFAULT_EVENT_TYPE_ES7="_doc".freeze
337
+ def get_event_type(event)
338
+ # Set the 'type' value for the index.
339
+ type = if @document_type
340
+ event.sprintf(@document_type)
341
+ else
342
+ if client.maximum_seen_major_version < 6
343
+ event.get("type") || DEFAULT_EVENT_TYPE_ES6
344
+ elsif client.maximum_seen_major_version == 6
345
+ DEFAULT_EVENT_TYPE_ES6
346
+ elsif client.maximum_seen_major_version == 7
347
+ DEFAULT_EVENT_TYPE_ES7
348
+ else
349
+ nil
350
+ end
351
+ end
352
+
353
+ if !(type.is_a?(String) || type.is_a?(Numeric))
354
+ @logger.warn("Bad event type! Non-string/integer type value set!", :type_class => type.class, :type_value => type.to_s, :event => event)
355
+ end
356
+
357
+ type.to_s
358
+ end
359
+
360
+ # Rescue retryable errors during bulk submission
361
+ def safe_bulk(actions)
362
+ sleep_interval = @retry_initial_interval
363
+ begin
364
+ es_actions = actions.map {|action_type, params, event| [action_type, params, event.to_hash]}
365
+ response = @client.bulk(es_actions)
366
+ response
367
+ rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::HostUnreachableError => e
368
+ # If we can't even connect to the server let's just print out the URL (:hosts is actually a URL)
369
+ # and let the user sort it out from there
370
+ @logger.error(
371
+ "Attempted to send a bulk request to elasticsearch'"+
372
+ " but Elasticsearch appears to be unreachable or down!",
373
+ :error_message => e.message,
374
+ :class => e.class.name,
375
+ :will_retry_in_seconds => sleep_interval
376
+ )
377
+ @logger.debug("Failed actions for last bad bulk request!", :actions => actions)
378
+
379
+ # We retry until there are no errors! Errors should all go to the retry queue
380
+ sleep_interval = sleep_for_interval(sleep_interval)
381
+ @bulk_request_metrics.increment(:failures)
382
+ retry unless @stopping.true?
383
+ rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::NoConnectionAvailableError => e
384
+ @logger.error(
385
+ "Attempted to send a bulk request to elasticsearch, but no there are no living connections in the connection pool. Perhaps Elasticsearch is unreachable or down?",
386
+ :error_message => e.message,
387
+ :class => e.class.name,
388
+ :will_retry_in_seconds => sleep_interval
389
+ )
390
+ Stud.stoppable_sleep(sleep_interval) { @stopping.true? }
391
+ sleep_interval = next_sleep_interval(sleep_interval)
392
+ @bulk_request_metrics.increment(:failures)
393
+ retry unless @stopping.true?
394
+ rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
395
+ @bulk_request_metrics.increment(:failures)
396
+ log_hash = {:code => e.response_code, :url => e.url.sanitized.to_s}
397
+ log_hash[:body] = e.response_body if @logger.debug? # Generally this is too verbose
398
+ message = "Encountered a retryable error. Will Retry with exponential backoff "
399
+
400
+ # We treat 429s as a special case because these really aren't errors, but
401
+ # rather just ES telling us to back off a bit, which we do.
402
+ # The other retryable code is 503, which are true errors
403
+ # Even though we retry the user should be made aware of these
404
+ if e.response_code == 429
405
+ logger.debug(message, log_hash)
406
+ else
407
+ logger.error(message, log_hash)
408
+ end
409
+
410
+ sleep_interval = sleep_for_interval(sleep_interval)
411
+ retry
412
+ rescue => e
413
+ # Stuff that should never happen
414
+ # For all other errors print out full connection issues
415
+ @logger.error(
416
+ "An unknown error occurred sending a bulk request to Elasticsearch. We will retry indefinitely",
417
+ :error_message => e.message,
418
+ :error_class => e.class.name,
419
+ :backtrace => e.backtrace
420
+ )
421
+
422
+ @logger.debug("Failed actions for last bad bulk request!", :actions => actions)
423
+
424
+ sleep_interval = sleep_for_interval(sleep_interval)
425
+ @bulk_request_metrics.increment(:failures)
426
+ retry unless @stopping.true?
427
+ end
428
+ end
429
+
430
+ def default_index?(index)
431
+ @index == LogStash::Outputs::ElasticSearch::CommonConfigs::DEFAULT_INDEX_NAME
432
+ end
433
+
434
+ def dlq_enabled?
435
+ # TODO there should be a better way to query if DLQ is enabled
436
+ # See more in: https://github.com/elastic/logstash/issues/8064
437
+ respond_to?(:execution_context) && execution_context.respond_to?(:dlq_writer) &&
438
+ !execution_context.dlq_writer.inner_writer.is_a?(::LogStash::Util::DummyDeadLetterQueueWriter)
439
+ end
440
+ end
441
+ end end end
@@ -0,0 +1,167 @@
1
+ require 'forwardable' # Needed for logstash core SafeURI. We need to patch this in core: https://github.com/elastic/logstash/pull/5978
2
+
3
+ module LogStash; module Outputs; class ElasticSearch
4
+ module CommonConfigs
5
+
6
+ DEFAULT_INDEX_NAME = "logstash-%{+YYYY.MM.dd}"
7
+ DEFAULT_POLICY = "logstash-policy"
8
+ DEFAULT_ROLLOVER_ALIAS = 'logstash'
9
+
10
+ DEFAULT_HOST = ::LogStash::Util::SafeURI.new("//127.0.0.1")
11
+
12
+ def self.included(mod)
13
+ # The index to write events to. This can be dynamic using the `%{foo}` syntax.
14
+ # The default value will partition your indices by day so you can more easily
15
+ # delete old data or only search specific date ranges.
16
+ # Indexes may not contain uppercase characters.
17
+ # For weekly indexes ISO 8601 format is recommended, eg. logstash-%{+xxxx.ww}.
18
+ # LS uses Joda to format the index pattern from event timestamp.
19
+ # Joda formats are defined http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html[here].
20
+ mod.config :index, :validate => :string, :default => DEFAULT_INDEX_NAME
21
+
22
+ mod.config :document_type,
23
+ :validate => :string,
24
+ :deprecated => "Document types are being deprecated in Elasticsearch 6.0, and removed entirely in 7.0. You should avoid this feature"
25
+
26
+ # From Logstash 1.3 onwards, a template is applied to Elasticsearch during
27
+ # Logstash's startup if one with the name `template_name` does not already exist.
28
+ # By default, the contents of this template is the default template for
29
+ # `logstash-%{+YYYY.MM.dd}` which always matches indices based on the pattern
30
+ # `logstash-*`. Should you require support for other index names, or would like
31
+ # to change the mappings in the template in general, a custom template can be
32
+ # specified by setting `template` to the path of a template file.
33
+ #
34
+ # Setting `manage_template` to false disables this feature. If you require more
35
+ # control over template creation, (e.g. creating indices dynamically based on
36
+ # field names) you should set `manage_template` to false and use the REST
37
+ # API to apply your templates manually.
38
+ mod.config :manage_template, :validate => :boolean, :default => true
39
+
40
+ # This configuration option defines how the template is named inside Elasticsearch.
41
+ # Note that if you have used the template management features and subsequently
42
+ # change this, you will need to prune the old template manually, e.g.
43
+ #
44
+ # `curl -XDELETE <http://localhost:9200/_template/OldTemplateName?pretty>`
45
+ #
46
+ # where `OldTemplateName` is whatever the former setting was.
47
+ mod.config :template_name, :validate => :string, :default => "logstash"
48
+
49
+ # You can set the path to your own template here, if you so desire.
50
+ # If not set, the included template will be used.
51
+ mod.config :template, :validate => :path
52
+
53
+ # The template_overwrite option will always overwrite the indicated template
54
+ # in Elasticsearch with either the one indicated by template or the included one.
55
+ # This option is set to false by default. If you always want to stay up to date
56
+ # with the template provided by Logstash, this option could be very useful to you.
57
+ # Likewise, if you have your own template file managed by puppet, for example, and
58
+ # you wanted to be able to update it regularly, this option could help there as well.
59
+ #
60
+ # Please note that if you are using your own customized version of the Logstash
61
+ # template (logstash), setting this to true will make Logstash to overwrite
62
+ # the "logstash" template (i.e. removing all customized settings)
63
+ mod.config :template_overwrite, :validate => :boolean, :default => false
64
+
65
+ # The document ID for the index. Useful for overwriting existing entries in
66
+ # Elasticsearch with the same ID.
67
+ mod.config :document_id, :validate => :string
68
+
69
+ # The version to use for indexing. Use sprintf syntax like `%{my_version}` to use a field value here.
70
+ # See https://www.elastic.co/blog/elasticsearch-versioning-support.
71
+ mod.config :version, :validate => :string
72
+
73
+ # The version_type to use for indexing.
74
+ # See https://www.elastic.co/blog/elasticsearch-versioning-support.
75
+ # See also https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#_version_types
76
+ mod.config :version_type, :validate => ["internal", 'external', "external_gt", "external_gte", "force"]
77
+
78
+ # A routing override to be applied to all processed events.
79
+ # This can be dynamic using the `%{foo}` syntax.
80
+ mod.config :routing, :validate => :string
81
+
82
+ # For child documents, ID of the associated parent.
83
+ # This can be dynamic using the `%{foo}` syntax.
84
+ mod.config :parent, :validate => :string, :default => nil
85
+
86
+ # For child documents, name of the join field
87
+ mod.config :join_field, :validate => :string, :default => nil
88
+
89
+ # Sets the host(s) of the remote instance. If given an array it will load balance requests across the hosts specified in the `hosts` parameter.
90
+ # Remember the `http` protocol uses the http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-http.html#modules-http[http] address (eg. 9200, not 9300).
91
+ # `"127.0.0.1"`
92
+ # `["127.0.0.1:9200","127.0.0.2:9200"]`
93
+ # `["http://127.0.0.1"]`
94
+ # `["https://127.0.0.1:9200"]`
95
+ # `["https://127.0.0.1:9200/mypath"]` (If using a proxy on a subpath)
96
+ # It is important to exclude http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-node.html[dedicated master nodes] from the `hosts` list
97
+ # to prevent LS from sending bulk requests to the master nodes. So this parameter should only reference either data or client nodes in Elasticsearch.
98
+ #
99
+ # Any special characters present in the URLs here MUST be URL escaped! This means `#` should be put in as `%23` for instance.
100
+ mod.config :hosts, :validate => :uri, :default => [ DEFAULT_HOST ], :list => true
101
+
102
+ # Cloud ID, from the Elastic Cloud web console. If set `hosts` should not be used.
103
+ #
104
+ # For mode details, check out the https://www.elastic.co/guide/en/logstash/current/connecting-to-cloud.html#_cloud_id[cloud documentation]
105
+ mod.config :cloud_id, :validate => :string
106
+
107
+ # Set upsert content for update mode.s
108
+ # Create a new document with this parameter as json string if `document_id` doesn't exists
109
+ mod.config :upsert, :validate => :string, :default => ""
110
+
111
+ # Enable `doc_as_upsert` for update mode.
112
+ # Create a new document with source if `document_id` doesn't exist in Elasticsearch
113
+ mod.config :doc_as_upsert, :validate => :boolean, :default => false
114
+
115
+ # Set script name for scripted update mode
116
+ mod.config :script, :validate => :string, :default => ""
117
+
118
+ # Define the type of script referenced by "script" variable
119
+ # inline : "script" contains inline script
120
+ # indexed : "script" contains the name of script directly indexed in elasticsearch
121
+ # file : "script" contains the name of script stored in elasticseach's config directory
122
+ mod.config :script_type, :validate => ["inline", 'indexed', "file"], :default => ["inline"]
123
+
124
+ # Set the language of the used script. If not set, this defaults to painless in ES 5.0
125
+ mod.config :script_lang, :validate => :string, :default => "painless"
126
+
127
+ # Set variable name passed to script (scripted update)
128
+ mod.config :script_var_name, :validate => :string, :default => "event"
129
+
130
+ # if enabled, script is in charge of creating non-existent document (scripted update)
131
+ mod.config :scripted_upsert, :validate => :boolean, :default => false
132
+
133
+ # Set initial interval in seconds between bulk retries. Doubled on each retry up to `retry_max_interval`
134
+ mod.config :retry_initial_interval, :validate => :number, :default => 2
135
+
136
+ # Set max interval in seconds between bulk retries.
137
+ mod.config :retry_max_interval, :validate => :number, :default => 64
138
+
139
+ # The number of times Elasticsearch should internally retry an update/upserted document
140
+ # See the https://www.elastic.co/guide/en/elasticsearch/guide/current/partial-updates.html[partial updates]
141
+ # for more info
142
+ mod.config :retry_on_conflict, :validate => :number, :default => 1
143
+
144
+ # Set which ingest pipeline you wish to execute for an event. You can also use event dependent configuration
145
+ # here like `pipeline => "%{INGEST_PIPELINE}"`
146
+ mod.config :pipeline, :validate => :string, :default => nil
147
+
148
+
149
+ # -----
150
+ # ILM configurations (beta)
151
+ # -----
152
+ # Flag for enabling Index Lifecycle Management integration.
153
+ mod.config :ilm_enabled, :validate => [true, false, 'true', 'false', 'auto'], :default => 'auto'
154
+
155
+ # Rollover alias used for indexing data. If rollover alias doesn't exist, Logstash will create it and map it to the relevant index
156
+ mod.config :ilm_rollover_alias, :validate => :string, :default => DEFAULT_ROLLOVER_ALIAS
157
+
158
+ # appends “{now/d}-000001” by default for new index creation, subsequent rollover indices will increment based on this pattern i.e. “000002”
159
+ # {now/d} is date math, and will insert the appropriate value automatically.
160
+ mod.config :ilm_pattern, :validate => :string, :default => '{now/d}-000001'
161
+
162
+ # ILM policy to use, if undefined the default policy will be used.
163
+ mod.config :ilm_policy, :validate => :string, :default => DEFAULT_POLICY
164
+
165
+ end
166
+ end
167
+ end end end
@@ -0,0 +1,14 @@
1
+ {
2
+ "policy" : {
3
+ "phases": {
4
+ "hot" : {
5
+ "actions" : {
6
+ "rollover" : {
7
+ "max_size" : "50gb",
8
+ "max_age":"30d"
9
+ }
10
+ }
11
+ }
12
+ }
13
+ }
14
+ }