logstash-output-elasticsearch 1.0.6-java → 1.0.7-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|