logstash-output-elasticsearch 1.0.6-java → 1.0.7-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 +3 -0
- data/lib/logstash/outputs/elasticsearch/protocol.rb +26 -1
- data/lib/logstash/outputs/elasticsearch.rb +26 -5
- data/logstash-output-elasticsearch.gemspec +1 -1
- data/spec/integration/outputs/update_spec.rb +87 -0
- data/spec/unit/outputs/elasticsearch/protocol_spec.rb +6 -3
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6859ba9736d257c039dd16c08ee0d9e6e233c914
|
4
|
+
data.tar.gz: f645572dac0a860dce40e09d5f81e732b37abab3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3fb6d1a7ecb3c40b2f376cb50f00db79e9573cd2cdad844d71e4aae3523aa76a2d2e018fa72916625d9eab414a4bfdd16733b1a8ec01add0020fe530268622ae
|
7
|
+
data.tar.gz: f05821d1741b5b478090cbcb328aa4e33141d2b796b0dcf02bccaea3ab7c18910564f54bdc631b23effb7063e25d4f2c1b119f8febc5b5cb6c9f9d3d924d079c
|
data/CHANGELOG.md
CHANGED
@@ -102,6 +102,19 @@ module LogStash::Outputs::Elasticsearch
|
|
102
102
|
|
103
103
|
def bulk(actions)
|
104
104
|
bulk_response = @client.bulk(:body => actions.collect do |action, args, source|
|
105
|
+
if action == 'update'
|
106
|
+
if args[:_id]
|
107
|
+
source = { 'doc' => source }
|
108
|
+
if @options[:doc_as_upsert]
|
109
|
+
source['doc_as_upsert'] = true
|
110
|
+
else
|
111
|
+
source['upsert'] = args[:_upsert] if args[:_upsert]
|
112
|
+
end
|
113
|
+
else
|
114
|
+
raise(LogStash::ConfigurationError, "Specifying action => 'update' without a document '_id' is not supported.")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
args.delete(:_upsert)
|
105
118
|
if source
|
106
119
|
next [ { action => args }, source ]
|
107
120
|
else
|
@@ -254,9 +267,21 @@ module LogStash::Outputs::Elasticsearch
|
|
254
267
|
else
|
255
268
|
raise(LogStash::ConfigurationError, "Specifying action => 'create_unless_exists' without a document '_id' is not supported.")
|
256
269
|
end
|
270
|
+
when "update"
|
271
|
+
unless args[:_id].nil?
|
272
|
+
request = org.elasticsearch.action.update.UpdateRequest.new(args[:_index], args[:_type], args[:_id])
|
273
|
+
request.routing(args[:_routing]) if args[:_routing]
|
274
|
+
request.doc(source)
|
275
|
+
if @options[:doc_as_upsert]
|
276
|
+
request.docAsUpsert(true)
|
277
|
+
else
|
278
|
+
request.upsert(args[:_upsert]) if args[:_upsert]
|
279
|
+
end
|
280
|
+
else
|
281
|
+
raise(LogStash::ConfigurationError, "Specifying action => 'update' without a document '_id' is not supported.")
|
282
|
+
end
|
257
283
|
else
|
258
284
|
raise(LogStash::ConfigurationError, "action => '#{action_name}' is not currently supported.")
|
259
|
-
#when "update"
|
260
285
|
end # case action
|
261
286
|
|
262
287
|
request.type(args[:_type]) if args[:_type]
|
@@ -65,7 +65,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
65
65
|
attr_reader :client
|
66
66
|
|
67
67
|
include Stud::Buffer
|
68
|
-
RETRYABLE_CODES = [429, 503]
|
68
|
+
RETRYABLE_CODES = [409, 429, 503]
|
69
69
|
SUCCESS_CODES = [200, 201]
|
70
70
|
|
71
71
|
config_name "elasticsearch"
|
@@ -257,6 +257,7 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
257
257
|
# - index: indexes a document (an event from Logstash).
|
258
258
|
# - delete: deletes a document by id
|
259
259
|
# - create: indexes a document, fails if a document by that id already exists in the index.
|
260
|
+
# - update: updates a document by id
|
260
261
|
# following action is not supported by HTTP protocol
|
261
262
|
# - create_unless_exists: creates a document, fails if no id is provided
|
262
263
|
#
|
@@ -317,6 +318,14 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
317
318
|
# Note, this is NOT a SOCKS proxy, but a plain HTTP proxy
|
318
319
|
config :proxy
|
319
320
|
|
321
|
+
# Enable doc_as_upsert for update mode
|
322
|
+
# create a new document with source if document_id doesn't exists
|
323
|
+
config :doc_as_upsert, :validate => :boolean, :default => false
|
324
|
+
|
325
|
+
# Set upsert content for update mode
|
326
|
+
# create a new document with this parameter as json string if document_id doesn't exists
|
327
|
+
config :upsert, :validate => :string, :default => ""
|
328
|
+
|
320
329
|
public
|
321
330
|
def register
|
322
331
|
@submit_mutex = Mutex.new
|
@@ -389,6 +398,13 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
389
398
|
|
390
399
|
common_options.merge! setup_basic_auth()
|
391
400
|
|
401
|
+
# Update API setup
|
402
|
+
update_options = {
|
403
|
+
:upsert => @upsert,
|
404
|
+
:doc_as_upsert => @doc_as_upsert
|
405
|
+
}
|
406
|
+
common_options.merge! update_options if @action == 'update'
|
407
|
+
|
392
408
|
client_class = case @protocol
|
393
409
|
when "transport"
|
394
410
|
LogStash::Outputs::Elasticsearch::Protocols::TransportClient
|
@@ -503,11 +519,16 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
|
|
503
519
|
event["type"] || "logs"
|
504
520
|
end
|
505
521
|
|
506
|
-
|
522
|
+
params = {
|
523
|
+
:_id => @document_id ? event.sprintf(@document_id) : nil,
|
524
|
+
:_index => event.sprintf(@index),
|
525
|
+
:_type => type,
|
526
|
+
:_routing => @routing ? event.sprintf(@routing) : nil
|
527
|
+
}
|
528
|
+
|
529
|
+
params[:_upsert] = LogStash::Json.load(event.sprintf(@upsert)) if @action == 'update' && @upsert != ""
|
507
530
|
|
508
|
-
|
509
|
-
routing = @routing ? event.sprintf(@routing) : nil
|
510
|
-
buffer_receive([event.sprintf(@action), { :_id => document_id, :_index => index, :_type => type, :_routing => routing }, event])
|
531
|
+
buffer_receive([event.sprintf(@action), params, event])
|
511
532
|
end # def receive
|
512
533
|
|
513
534
|
public
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require_relative "../../../spec/es_spec_helper"
|
2
|
+
|
3
|
+
describe "all protocols update actions", :integration => true do
|
4
|
+
require "logstash/outputs/elasticsearch"
|
5
|
+
require "elasticsearch"
|
6
|
+
|
7
|
+
def get_es_output( protocol, id = nil, upsert = nil, doc_as_upsert=nil)
|
8
|
+
settings = {
|
9
|
+
"manage_template" => true,
|
10
|
+
"index" => "logstash-update",
|
11
|
+
"template_overwrite" => true,
|
12
|
+
"protocol" => protocol,
|
13
|
+
"host" => get_host(),
|
14
|
+
"port" => get_port(protocol),
|
15
|
+
"action" => "update"
|
16
|
+
}
|
17
|
+
settings['upsert'] = upsert unless upsert.nil?
|
18
|
+
settings['document_id'] = id unless id.nil?
|
19
|
+
settings['doc_as_upsert'] = doc_as_upsert unless doc_as_upsert.nil?
|
20
|
+
LogStash::Outputs::ElasticSearch.new(settings)
|
21
|
+
end
|
22
|
+
|
23
|
+
before :each do
|
24
|
+
@es = get_client
|
25
|
+
# Delete all templates first.
|
26
|
+
# Clean ES of data before we start.
|
27
|
+
@es.indices.delete_template(:name => "*")
|
28
|
+
# This can fail if there are no indexes, ignore failure.
|
29
|
+
@es.indices.delete(:index => "*") rescue nil
|
30
|
+
@es.index(
|
31
|
+
:index => 'logstash-update',
|
32
|
+
:type => 'logs',
|
33
|
+
:id => "123",
|
34
|
+
:body => { :message => 'Test' }
|
35
|
+
)
|
36
|
+
@es.indices.refresh
|
37
|
+
end
|
38
|
+
|
39
|
+
["node", "transport", "http"].each do |protocol|
|
40
|
+
context "update only with #{protocol} protocol" do
|
41
|
+
it "should failed without a document_id" do
|
42
|
+
event = LogStash::Event.new("somevalue" => 100, "@timestamp" => "2014-11-17T20:37:17.223Z", "@metadata" => {"retry_count" => 0})
|
43
|
+
action = ["update", {:_id=>nil, :_index=>"logstash-2014.11.17", :_type=>"logs"}, event]
|
44
|
+
subject = get_es_output(protocol)
|
45
|
+
subject.register
|
46
|
+
expect { subject.flush([action]) }.to raise_error
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not create new document" do
|
50
|
+
subject = get_es_output(protocol, "456")
|
51
|
+
subject.register
|
52
|
+
subject.receive(LogStash::Event.new("message" => "sample message here"))
|
53
|
+
subject.buffer_flush(:final => true)
|
54
|
+
expect {@es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should update existing document" do
|
58
|
+
subject = get_es_output(protocol, "123")
|
59
|
+
subject.register
|
60
|
+
subject.receive(LogStash::Event.new("message" => "updated message here"))
|
61
|
+
subject.buffer_flush(:final => true)
|
62
|
+
r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "123", :refresh => true)
|
63
|
+
insist { r["_source"]["message"] } == 'updated message here'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "upsert with #{protocol} protocol" do
|
68
|
+
it "should create new documents with upsert content" do
|
69
|
+
subject = get_es_output(protocol, "456", '{"message": "upsert message"}')
|
70
|
+
subject.register
|
71
|
+
subject.receive(LogStash::Event.new("message" => "sample message here"))
|
72
|
+
subject.buffer_flush(:final => true)
|
73
|
+
r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)
|
74
|
+
insist { r["_source"]["message"] } == 'upsert message'
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should create new documents with event/doc as upsert" do
|
78
|
+
subject = get_es_output(protocol, "456", nil, true)
|
79
|
+
subject.register
|
80
|
+
subject.receive(LogStash::Event.new("message" => "sample message here"))
|
81
|
+
subject.buffer_flush(:final => true)
|
82
|
+
r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)
|
83
|
+
insist { r["_source"]["message"] } == 'sample message here'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -6,10 +6,12 @@ describe LogStash::Outputs::Elasticsearch::Protocols::NodeClient do
|
|
6
6
|
context "successful" do
|
7
7
|
it "should map correctly" do
|
8
8
|
index_response = org.elasticsearch.action.index.IndexResponse.new("my_index", "my_type", "my_id", 123, true)
|
9
|
+
update_response = org.elasticsearch.action.update.UpdateResponse.new("my_index", "my_type", "my_id", 123, false)
|
9
10
|
delete_response = org.elasticsearch.action.delete.DeleteResponse.new("my_index", "my_type", "my_id", 123, true)
|
10
11
|
bulk_item_response_index = org.elasticsearch.action.bulk.BulkItemResponse.new(32, "index", index_response)
|
12
|
+
bulk_item_response_update = org.elasticsearch.action.bulk.BulkItemResponse.new(32, "update", update_response)
|
11
13
|
bulk_item_response_delete = org.elasticsearch.action.bulk.BulkItemResponse.new(32, "delete", delete_response)
|
12
|
-
bulk_response = org.elasticsearch.action.bulk.BulkResponse.new([bulk_item_response_index, bulk_item_response_delete], 0)
|
14
|
+
bulk_response = org.elasticsearch.action.bulk.BulkResponse.new([bulk_item_response_index, bulk_item_response_update, bulk_item_response_delete], 0)
|
13
15
|
ret = LogStash::Outputs::Elasticsearch::Protocols::NodeClient.normalize_bulk_response(bulk_response)
|
14
16
|
insist { ret } == {"errors" => false}
|
15
17
|
end
|
@@ -19,10 +21,11 @@ describe LogStash::Outputs::Elasticsearch::Protocols::NodeClient do
|
|
19
21
|
it "should map correctly" do
|
20
22
|
failure = org.elasticsearch.action.bulk.BulkItemResponse::Failure.new("my_index", "my_type", "my_id", "error message", org.elasticsearch.rest.RestStatus::BAD_REQUEST)
|
21
23
|
bulk_item_response_index = org.elasticsearch.action.bulk.BulkItemResponse.new(32, "index", failure)
|
24
|
+
bulk_item_response_update = org.elasticsearch.action.bulk.BulkItemResponse.new(32, "update", failure)
|
22
25
|
bulk_item_response_delete = org.elasticsearch.action.bulk.BulkItemResponse.new(32, "delete", failure)
|
23
|
-
bulk_response = org.elasticsearch.action.bulk.BulkResponse.new([bulk_item_response_index, bulk_item_response_delete], 0)
|
26
|
+
bulk_response = org.elasticsearch.action.bulk.BulkResponse.new([bulk_item_response_index, bulk_item_response_update, bulk_item_response_delete], 0)
|
24
27
|
actual = LogStash::Outputs::Elasticsearch::Protocols::NodeClient.normalize_bulk_response(bulk_response)
|
25
|
-
insist { actual } == {"errors" => true, "statuses" => [400, 400]}
|
28
|
+
insist { actual } == {"errors" => true, "statuses" => [400, 400, 400]}
|
26
29
|
end
|
27
30
|
end
|
28
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-elasticsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.7
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -195,6 +195,7 @@ files:
|
|
195
195
|
- spec/integration/outputs/secure_spec.rb
|
196
196
|
- spec/integration/outputs/templates_spec.rb
|
197
197
|
- spec/integration/outputs/transport_create_spec.rb
|
198
|
+
- spec/integration/outputs/update_spec.rb
|
198
199
|
- spec/unit/outputs/elasticsearch/protocol_spec.rb
|
199
200
|
- spec/unit/outputs/elasticsearch_proxy_spec.rb
|
200
201
|
- spec/unit/outputs/elasticsearch_spec.rb
|
@@ -251,6 +252,7 @@ test_files:
|
|
251
252
|
- spec/integration/outputs/secure_spec.rb
|
252
253
|
- spec/integration/outputs/templates_spec.rb
|
253
254
|
- spec/integration/outputs/transport_create_spec.rb
|
255
|
+
- spec/integration/outputs/update_spec.rb
|
254
256
|
- spec/unit/outputs/elasticsearch/protocol_spec.rb
|
255
257
|
- spec/unit/outputs/elasticsearch_proxy_spec.rb
|
256
258
|
- spec/unit/outputs/elasticsearch_spec.rb
|