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

Sign up to get free protection for your applications and to get access to all the features.
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
+ }