logstash-output-elasticsearch_java 2.0.2 → 2.1.1.beta1
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/Gemfile +1 -1
- data/lib/logstash/outputs/elasticsearch_java.rb +37 -386
- data/lib/logstash/outputs/elasticsearch_java/protocol.rb +201 -228
- data/logstash-output-elasticsearch_java.gemspec +2 -1
- data/spec/integration/outputs/elasticsearch/node_spec.rb +0 -25
- data/spec/integration/outputs/index_spec.rb +2 -4
- data/spec/integration/outputs/retry_spec.rb +24 -14
- data/spec/integration/outputs/routing_spec.rb +1 -2
- data/spec/integration/outputs/secure_spec.rb +4 -4
- data/spec/integration/outputs/templates_spec.rb +13 -11
- data/spec/integration/outputs/transport_create_spec.rb +5 -6
- data/spec/integration/outputs/update_spec.rb +5 -6
- data/spec/unit/outputs/elasticsearch/protocol_spec.rb +6 -3
- data/spec/unit/outputs/elasticsearch_spec.rb +0 -1
- data/vendor/jar-dependencies/runtime-jars/{elasticsearch-2.0.0.jar → elasticsearch-2.1.0.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-core-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-cbor-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-smile-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-yaml-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-analyzers-common-5.2.1.jar → lucene-analyzers-common-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-backward-codecs-5.2.1.jar → lucene-backward-codecs-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-core-5.2.1.jar → lucene-core-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-expressions-5.2.1.jar → lucene-expressions-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-grouping-5.2.1.jar → lucene-grouping-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-highlighter-5.2.1.jar → lucene-highlighter-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-join-5.3.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-memory-5.3.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-misc-5.2.1.jar → lucene-misc-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-queries-5.2.1.jar → lucene-queries-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-queryparser-5.2.1.jar → lucene-queryparser-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-sandbox-5.3.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/{lucene-spatial-5.2.1.jar → lucene-spatial-5.3.1.jar} +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-spatial3d-5.3.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-suggest-5.3.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/snakeyaml-1.15.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/spatial4j-0.5.jar +0 -0
- metadata +105 -91
- data/lib/logstash/outputs/elasticsearch_java/elasticsearch-template.json +0 -93
- data/vendor/jar-dependencies/runtime-jars/jackson-core-2.5.3.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-cbor-2.5.3.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-smile-2.5.3.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-yaml-2.5.3.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-join-5.2.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-memory-5.2.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-sandbox-5.2.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/lucene-suggest-5.2.1.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/snakeyaml-1.12.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/spatial4j-0.4.1.jar +0 -0
@@ -3,263 +3,236 @@ require "base64"
|
|
3
3
|
require 'logstash-output-elasticsearch_java_jars.rb'
|
4
4
|
require 'logstash/outputs/elasticsearch_java'
|
5
5
|
|
6
|
-
module LogStash
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
class Base
|
11
|
-
private
|
12
|
-
def initialize(options={})
|
13
|
-
# host(s), port, cluster
|
14
|
-
@logger = Cabin::Channel.get
|
15
|
-
end
|
6
|
+
module LogStash module Outputs module ElasticSearchJavaPlugins module Protocols
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
:port => 9300,
|
9
|
+
}
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
@logger.debug("Found existing Elasticsearch template. Skipping template management", :name => name)
|
20
|
-
return
|
21
|
-
end
|
22
|
-
template_put(name, template)
|
23
|
-
end
|
11
|
+
class NodeClient
|
12
|
+
attr_reader :settings, :client_options
|
24
13
|
|
25
|
-
|
26
|
-
#
|
27
|
-
# 'actions' is expected to be an array of bulk requests as string json
|
28
|
-
# values.
|
29
|
-
#
|
30
|
-
# Each 'action' becomes a single line in the bulk api call. For more
|
31
|
-
# details on the format of each.
|
32
|
-
def bulk(actions)
|
33
|
-
raise NotImplemented, "You must implement this yourself"
|
34
|
-
# bulk([
|
35
|
-
# '{ "index" : { "_index" : "test", "_type" : "type1", "_id" : "1" } }',
|
36
|
-
# '{ "field1" : "value1" }'
|
37
|
-
#])
|
38
|
-
end
|
14
|
+
CLIENT_MUTEX = Mutex.new
|
39
15
|
|
40
|
-
|
41
|
-
|
16
|
+
def initialize(options={})
|
17
|
+
@logger = Cabin::Channel.get
|
18
|
+
@client_options = DEFAULT_OPTIONS.merge(options)
|
19
|
+
create_settings
|
20
|
+
end
|
21
|
+
|
22
|
+
def client_mutex_synchronize
|
23
|
+
CLIENT_MUTEX.synchronize { yield }
|
24
|
+
end
|
42
25
|
|
43
|
-
|
44
|
-
|
26
|
+
def client
|
27
|
+
client_mutex_synchronize { @@client ||= make_client }
|
28
|
+
end
|
45
29
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
else
|
51
|
-
nodebuilder = org.elasticsearch.node.NodeBuilder.nodeBuilder
|
52
|
-
@client = nodebuilder.settings(settings.build).node().client()
|
53
|
-
end
|
54
|
-
}
|
55
|
-
end
|
30
|
+
# For use in test helpers
|
31
|
+
def self.clear_node_client
|
32
|
+
client_mutex_synchronize { @@client = nil }
|
33
|
+
end
|
56
34
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
35
|
+
def create_settings
|
36
|
+
@settings = org.elasticsearch.common.settings.Settings.settingsBuilder()
|
37
|
+
if @client_options[:hosts]
|
38
|
+
@settings.put("discovery.zen.ping.multicast.enabled", false)
|
39
|
+
@settings.put("discovery.zen.ping.unicast.hosts", hosts(@client_options))
|
40
|
+
end
|
62
41
|
|
63
|
-
|
42
|
+
@settings.put("node.client", true)
|
43
|
+
@settings.put("http.enabled", false)
|
44
|
+
@settings.put("path.home", Dir.pwd)
|
64
45
|
|
65
|
-
|
66
|
-
|
67
|
-
|
46
|
+
if @client_options[:client_settings]
|
47
|
+
@client_options[:client_settings].each do |key, value|
|
48
|
+
@settings.put(key, value)
|
49
|
+
end
|
50
|
+
end
|
68
51
|
|
69
|
-
|
70
|
-
|
71
|
-
require "java"
|
72
|
-
@options = DEFAULT_OPTIONS.merge(options)
|
73
|
-
setup(@options)
|
74
|
-
end # def initialize
|
52
|
+
@settings
|
53
|
+
end
|
75
54
|
|
76
|
-
|
77
|
-
|
55
|
+
def hosts(options)
|
56
|
+
# http://www.elasticsearch.org/guide/reference/modules/discovery/zen/
|
57
|
+
result = Array.new
|
58
|
+
if options[:hosts].class == Array
|
59
|
+
options[:hosts].each do |host|
|
60
|
+
if host.to_s =~ /^.+:.+$/
|
61
|
+
# For host in format: host:port, ignore options[:port]
|
62
|
+
result << host
|
63
|
+
else
|
64
|
+
if options[:port].to_s =~ /^\d+-\d+$/
|
65
|
+
# port ranges are 'host[port1-port2]'b
|
66
|
+
result << Range.new(*options[:port].split("-")).collect { |p| "#{host}:#{p}" }
|
67
|
+
else
|
68
|
+
result << "#{host}:#{options[:port]}"
|
69
|
+
end
|
78
70
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
71
|
+
end
|
72
|
+
else
|
73
|
+
if options[:hosts].to_s =~ /^.+:.+$/
|
74
|
+
# For host in format: host:port, ignore options[:port]
|
75
|
+
result << options[:hosts]
|
76
|
+
else
|
77
|
+
if options[:port].to_s =~ /^\d+-\d+$/
|
78
|
+
# port ranges are 'host[port1-port2]' according to
|
79
|
+
# http://www.elasticsearch.org/guide/reference/modules/discovery/zen/
|
80
|
+
# However, it seems to only query the first port.
|
81
|
+
# So generate our own list of unicast hosts to scan.
|
82
|
+
range = Range.new(*options[:port].split("-"))
|
83
|
+
result << range.collect { |p| "#{options[:hosts]}:#{p}" }
|
84
|
+
else
|
85
|
+
result << "#{options[:hosts]}:#{options[:port]}"
|
82
86
|
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
result.flatten.join(",")
|
90
|
+
end
|
83
91
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
92
|
+
# Normalizes the Java response to a reasonable approximation of the HTTP datastructure for interop
|
93
|
+
# with the HTTP code
|
94
|
+
def normalize_bulk_response(bulk_response)
|
95
|
+
# TODO(talevy): parse item response objects to retrieve correct 200 (OK) or 201(created) status codes + items = bulk_response.map {|i|
|
96
|
+
items = bulk_response.map { |i|
|
97
|
+
if i.is_failed
|
98
|
+
[[i.get_op_type, {"status" => i.get_failure.get_status.get_status, "message" => i.failureMessage}]]
|
99
|
+
else
|
100
|
+
[[i.get_op_type, {"status" => 200, "message" => "OK"}]]
|
101
|
+
end
|
102
|
+
}
|
103
|
+
if bulk_response.has_failures()
|
104
|
+
{"errors" => true, "items" => items}
|
105
|
+
else
|
106
|
+
{"errors" => false}
|
107
|
+
end
|
108
|
+
end
|
90
109
|
|
91
|
-
|
92
|
-
|
93
|
-
|
110
|
+
def make_client
|
111
|
+
nodebuilder = org.elasticsearch.node.NodeBuilder.nodeBuilder
|
112
|
+
nodebuilder.settings(settings.build).node().client()
|
113
|
+
end
|
94
114
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
115
|
+
def bulk(actions)
|
116
|
+
# Actions an array of [ action, action_metadata, source ]
|
117
|
+
prep = client.prepareBulk
|
118
|
+
actions.each do |action, args, source|
|
119
|
+
prep.add(build_request(action, args, source))
|
120
|
+
end
|
121
|
+
response = prep.execute.actionGet()
|
100
122
|
|
101
|
-
|
102
|
-
|
123
|
+
self.normalize_bulk_response(response)
|
124
|
+
end
|
103
125
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
result << range.collect { |p| "#{options[:hosts]}:#{p}" }
|
133
|
-
else
|
134
|
-
result << "#{options[:hosts]}:#{options[:port]}"
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
result.flatten.join(",")
|
126
|
+
# def bulk
|
127
|
+
|
128
|
+
def build_request(action, args, source)
|
129
|
+
case action
|
130
|
+
when "index"
|
131
|
+
request = org.elasticsearch.action.index.IndexRequest.new(args[:_index])
|
132
|
+
request.id(args[:_id]) if args[:_id]
|
133
|
+
request.routing(args[:_routing]) if args[:_routing]
|
134
|
+
request.source(source)
|
135
|
+
when "delete"
|
136
|
+
request = org.elasticsearch.action.delete.DeleteRequest.new(args[:_index])
|
137
|
+
request.id(args[:_id])
|
138
|
+
request.routing(args[:_routing]) if args[:_routing]
|
139
|
+
when "create"
|
140
|
+
request = org.elasticsearch.action.index.IndexRequest.new(args[:_index])
|
141
|
+
request.id(args[:_id]) if args[:_id]
|
142
|
+
request.routing(args[:_routing]) if args[:_routing]
|
143
|
+
request.source(source)
|
144
|
+
request.opType("create")
|
145
|
+
when "create_unless_exists"
|
146
|
+
unless args[:_id].nil?
|
147
|
+
request = org.elasticsearch.action.index.IndexRequest.new(args[:_index])
|
148
|
+
request.id(args[:_id])
|
149
|
+
request.routing(args[:_routing]) if args[:_routing]
|
150
|
+
request.source(source)
|
151
|
+
request.opType("create")
|
152
|
+
else
|
153
|
+
raise(LogStash::ConfigurationError, "Specifying action => 'create_unless_exists' without a document '_id' is not supported.")
|
139
154
|
end
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
155
|
+
when "update"
|
156
|
+
unless args[:_id].nil?
|
157
|
+
request = org.elasticsearch.action.update.UpdateRequest.new(args[:_index], args[:_type], args[:_id])
|
158
|
+
request.routing(args[:_routing]) if args[:_routing]
|
159
|
+
request.doc(source)
|
160
|
+
if @client_options[:doc_as_upsert]
|
161
|
+
request.docAsUpsert(true)
|
146
162
|
else
|
147
|
-
|
163
|
+
request.upsert(args[:_upsert]) if args[:_upsert]
|
148
164
|
end
|
165
|
+
else
|
166
|
+
raise(LogStash::ConfigurationError, "Specifying action => 'update' without a document '_id' is not supported.")
|
149
167
|
end
|
168
|
+
else
|
169
|
+
raise(LogStash::ConfigurationError, "action => '#{action_name}' is not currently supported.")
|
170
|
+
end # case action
|
150
171
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
actions.each do |action, args, source|
|
155
|
-
prep.add(build_request(action, args, source))
|
156
|
-
end
|
157
|
-
response = prep.execute.actionGet()
|
158
|
-
|
159
|
-
self.class.normalize_bulk_response(response)
|
160
|
-
end # def bulk
|
161
|
-
|
162
|
-
def build_request(action, args, source)
|
163
|
-
case action
|
164
|
-
when "index"
|
165
|
-
request = org.elasticsearch.action.index.IndexRequest.new(args[:_index])
|
166
|
-
request.id(args[:_id]) if args[:_id]
|
167
|
-
request.routing(args[:_routing]) if args[:_routing]
|
168
|
-
request.source(source)
|
169
|
-
when "delete"
|
170
|
-
request = org.elasticsearch.action.delete.DeleteRequest.new(args[:_index])
|
171
|
-
request.id(args[:_id])
|
172
|
-
request.routing(args[:_routing]) if args[:_routing]
|
173
|
-
when "create"
|
174
|
-
request = org.elasticsearch.action.index.IndexRequest.new(args[:_index])
|
175
|
-
request.id(args[:_id]) if args[:_id]
|
176
|
-
request.routing(args[:_routing]) if args[:_routing]
|
177
|
-
request.source(source)
|
178
|
-
request.opType("create")
|
179
|
-
when "create_unless_exists"
|
180
|
-
unless args[:_id].nil?
|
181
|
-
request = org.elasticsearch.action.index.IndexRequest.new(args[:_index])
|
182
|
-
request.id(args[:_id])
|
183
|
-
request.routing(args[:_routing]) if args[:_routing]
|
184
|
-
request.source(source)
|
185
|
-
request.opType("create")
|
186
|
-
else
|
187
|
-
raise(LogStash::ConfigurationError, "Specifying action => 'create_unless_exists' without a document '_id' is not supported.")
|
188
|
-
end
|
189
|
-
when "update"
|
190
|
-
unless args[:_id].nil?
|
191
|
-
request = org.elasticsearch.action.update.UpdateRequest.new(args[:_index], args[:_type], args[:_id])
|
192
|
-
request.routing(args[:_routing]) if args[:_routing]
|
193
|
-
request.doc(source)
|
194
|
-
if @options[:doc_as_upsert]
|
195
|
-
request.docAsUpsert(true)
|
196
|
-
else
|
197
|
-
request.upsert(args[:_upsert]) if args[:_upsert]
|
198
|
-
end
|
199
|
-
else
|
200
|
-
raise(LogStash::ConfigurationError, "Specifying action => 'update' without a document '_id' is not supported.")
|
201
|
-
end
|
202
|
-
else
|
203
|
-
raise(LogStash::ConfigurationError, "action => '#{action_name}' is not currently supported.")
|
204
|
-
end # case action
|
205
|
-
|
206
|
-
request.type(args[:_type]) if args[:_type]
|
207
|
-
return request
|
208
|
-
end # def build_request
|
209
|
-
|
210
|
-
def template_exists?(name)
|
211
|
-
return !client.admin.indices.
|
212
|
-
prepareGetTemplates(name).
|
213
|
-
execute().
|
214
|
-
actionGet().
|
215
|
-
getIndexTemplates().
|
216
|
-
isEmpty
|
217
|
-
end # def template_exists?
|
218
|
-
|
219
|
-
def template_put(name, template)
|
220
|
-
response = client.admin.indices.
|
221
|
-
preparePutTemplate(name).
|
222
|
-
setSource(LogStash::Json.dump(template)).
|
223
|
-
execute().
|
224
|
-
actionGet()
|
172
|
+
request.type(args[:_type]) if args[:_type]
|
173
|
+
return request
|
174
|
+
end
|
225
175
|
|
226
|
-
|
227
|
-
end # template_put
|
176
|
+
# def build_request
|
228
177
|
|
229
|
-
|
230
|
-
|
178
|
+
def template_exists?(name)
|
179
|
+
return !client.admin.indices.
|
180
|
+
prepareGetTemplates(name).
|
181
|
+
execute().
|
182
|
+
actionGet().
|
183
|
+
getIndexTemplates().
|
184
|
+
isEmpty
|
185
|
+
end
|
231
186
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
187
|
+
def template_install(name, template, force=false)
|
188
|
+
if template_exists?(name) && !force
|
189
|
+
@logger.debug("Found existing Elasticsearch template. Skipping template management", :name => name)
|
190
|
+
return
|
191
|
+
end
|
192
|
+
template_put(name, template)
|
193
|
+
end
|
238
194
|
|
195
|
+
def template_put(name, template)
|
196
|
+
response = client.admin.indices.
|
197
|
+
preparePutTemplate(name).
|
198
|
+
setSource(LogStash::Json.dump(template)).
|
199
|
+
execute().
|
200
|
+
actionGet()
|
239
201
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
202
|
+
raise "Could not index template!" unless response.isAcknowledged
|
203
|
+
end
|
204
|
+
end # class NodeClient
|
205
|
+
|
206
|
+
class TransportClient < NodeClient
|
207
|
+
private
|
208
|
+
def make_client
|
209
|
+
client = org.elasticsearch.client.transport.TransportClient.
|
210
|
+
builder().
|
211
|
+
settings((settings.build)).
|
212
|
+
build()
|
213
|
+
|
214
|
+
client_options[:hosts].each do |host|
|
215
|
+
matches = host.match /([^:+]+)(:(\d+))?/
|
216
|
+
|
217
|
+
inet_addr = java.net.InetAddress.getByName(matches[1])
|
218
|
+
port = (matches[3] || 9300).to_i
|
219
|
+
client.addTransportAddress(
|
220
|
+
org.elasticsearch.common.transport.InetSocketTransportAddress.new(
|
221
|
+
inet_addr, port
|
222
|
+
)
|
223
|
+
)
|
224
|
+
end
|
246
225
|
|
247
|
-
|
248
|
-
|
226
|
+
return client
|
227
|
+
end
|
249
228
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
inet_addr, port
|
255
|
-
)
|
256
|
-
)
|
257
|
-
end
|
229
|
+
# We want a separate client per instance for transport
|
230
|
+
def client
|
231
|
+
client_mutex_synchronize { @client ||= make_client }
|
232
|
+
end
|
258
233
|
|
259
|
-
|
260
|
-
|
261
|
-
end
|
262
|
-
end
|
234
|
+
def clear_client()
|
235
|
+
client_mutex_synchronize { @client = nil }
|
263
236
|
end
|
264
237
|
end
|
265
|
-
end
|
238
|
+
end end end end
|