logstash-output-elasticsearch_java 2.0.2 → 2.1.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile +1 -1
  4. data/lib/logstash/outputs/elasticsearch_java.rb +37 -386
  5. data/lib/logstash/outputs/elasticsearch_java/protocol.rb +201 -228
  6. data/logstash-output-elasticsearch_java.gemspec +2 -1
  7. data/spec/integration/outputs/elasticsearch/node_spec.rb +0 -25
  8. data/spec/integration/outputs/index_spec.rb +2 -4
  9. data/spec/integration/outputs/retry_spec.rb +24 -14
  10. data/spec/integration/outputs/routing_spec.rb +1 -2
  11. data/spec/integration/outputs/secure_spec.rb +4 -4
  12. data/spec/integration/outputs/templates_spec.rb +13 -11
  13. data/spec/integration/outputs/transport_create_spec.rb +5 -6
  14. data/spec/integration/outputs/update_spec.rb +5 -6
  15. data/spec/unit/outputs/elasticsearch/protocol_spec.rb +6 -3
  16. data/spec/unit/outputs/elasticsearch_spec.rb +0 -1
  17. data/vendor/jar-dependencies/runtime-jars/{elasticsearch-2.0.0.jar → elasticsearch-2.1.0.jar} +0 -0
  18. data/vendor/jar-dependencies/runtime-jars/jackson-core-2.6.2.jar +0 -0
  19. data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-cbor-2.6.2.jar +0 -0
  20. data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-smile-2.6.2.jar +0 -0
  21. data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-yaml-2.6.2.jar +0 -0
  22. data/vendor/jar-dependencies/runtime-jars/{lucene-analyzers-common-5.2.1.jar → lucene-analyzers-common-5.3.1.jar} +0 -0
  23. data/vendor/jar-dependencies/runtime-jars/{lucene-backward-codecs-5.2.1.jar → lucene-backward-codecs-5.3.1.jar} +0 -0
  24. data/vendor/jar-dependencies/runtime-jars/{lucene-core-5.2.1.jar → lucene-core-5.3.1.jar} +0 -0
  25. data/vendor/jar-dependencies/runtime-jars/{lucene-expressions-5.2.1.jar → lucene-expressions-5.3.1.jar} +0 -0
  26. data/vendor/jar-dependencies/runtime-jars/{lucene-grouping-5.2.1.jar → lucene-grouping-5.3.1.jar} +0 -0
  27. data/vendor/jar-dependencies/runtime-jars/{lucene-highlighter-5.2.1.jar → lucene-highlighter-5.3.1.jar} +0 -0
  28. data/vendor/jar-dependencies/runtime-jars/lucene-join-5.3.1.jar +0 -0
  29. data/vendor/jar-dependencies/runtime-jars/lucene-memory-5.3.1.jar +0 -0
  30. data/vendor/jar-dependencies/runtime-jars/{lucene-misc-5.2.1.jar → lucene-misc-5.3.1.jar} +0 -0
  31. data/vendor/jar-dependencies/runtime-jars/{lucene-queries-5.2.1.jar → lucene-queries-5.3.1.jar} +0 -0
  32. data/vendor/jar-dependencies/runtime-jars/{lucene-queryparser-5.2.1.jar → lucene-queryparser-5.3.1.jar} +0 -0
  33. data/vendor/jar-dependencies/runtime-jars/lucene-sandbox-5.3.1.jar +0 -0
  34. data/vendor/jar-dependencies/runtime-jars/{lucene-spatial-5.2.1.jar → lucene-spatial-5.3.1.jar} +0 -0
  35. data/vendor/jar-dependencies/runtime-jars/lucene-spatial3d-5.3.1.jar +0 -0
  36. data/vendor/jar-dependencies/runtime-jars/lucene-suggest-5.3.1.jar +0 -0
  37. data/vendor/jar-dependencies/runtime-jars/snakeyaml-1.15.jar +0 -0
  38. data/vendor/jar-dependencies/runtime-jars/spatial4j-0.5.jar +0 -0
  39. metadata +105 -91
  40. data/lib/logstash/outputs/elasticsearch_java/elasticsearch-template.json +0 -93
  41. data/vendor/jar-dependencies/runtime-jars/jackson-core-2.5.3.jar +0 -0
  42. data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-cbor-2.5.3.jar +0 -0
  43. data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-smile-2.5.3.jar +0 -0
  44. data/vendor/jar-dependencies/runtime-jars/jackson-dataformat-yaml-2.5.3.jar +0 -0
  45. data/vendor/jar-dependencies/runtime-jars/lucene-join-5.2.1.jar +0 -0
  46. data/vendor/jar-dependencies/runtime-jars/lucene-memory-5.2.1.jar +0 -0
  47. data/vendor/jar-dependencies/runtime-jars/lucene-sandbox-5.2.1.jar +0 -0
  48. data/vendor/jar-dependencies/runtime-jars/lucene-suggest-5.2.1.jar +0 -0
  49. data/vendor/jar-dependencies/runtime-jars/snakeyaml-1.12.jar +0 -0
  50. 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
- module Outputs
8
- module ElasticSearchJavaPlugins
9
- module Protocols
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
- def template_install(name, template, force=false)
18
- if template_exists?(name) && !force
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
- # Do a bulk request with the given actions.
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
- public(:initialize, :template_install)
41
- end
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
- class NodeClient < Base
44
- CLIENT_MUTEX = Mutex.new
26
+ def client
27
+ client_mutex_synchronize { @@client ||= make_client }
28
+ end
45
29
 
46
- def self.get_client(settings)
47
- CLIENT_MUTEX.synchronize {
48
- if @client
49
- @client
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
- def self.clear_client()
58
- CLIENT_MUTEX.synchronize {
59
- @client = null
60
- }
61
- end
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
- private
42
+ @settings.put("node.client", true)
43
+ @settings.put("http.enabled", false)
44
+ @settings.put("path.home", Dir.pwd)
64
45
 
65
- DEFAULT_OPTIONS = {
66
- :port => 9300,
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
- def initialize(options={})
70
- super
71
- require "java"
72
- @options = DEFAULT_OPTIONS.merge(options)
73
- setup(@options)
74
- end # def initialize
52
+ @settings
53
+ end
75
54
 
76
- def settings
77
- return @settings
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
- def client
81
- self.class.get_client(settings)
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
- def setup(options={})
85
- @settings = org.elasticsearch.common.settings.Settings.settingsBuilder()
86
- if options[:hosts]
87
- @settings.put("discovery.zen.ping.multicast.enabled", false)
88
- @settings.put("discovery.zen.ping.unicast.hosts", NodeClient.hosts(options))
89
- end
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
- @settings.put("node.client", true)
92
- @settings.put("http.enabled", false)
93
- @settings.put("path.home", Dir.pwd)
110
+ def make_client
111
+ nodebuilder = org.elasticsearch.node.NodeBuilder.nodeBuilder
112
+ nodebuilder.settings(settings.build).node().client()
113
+ end
94
114
 
95
- if options[:client_settings]
96
- options[:client_settings].each do |key, value|
97
- @settings.put(key, value)
98
- end
99
- end
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
- return @settings
102
- end
123
+ self.normalize_bulk_response(response)
124
+ end
103
125
 
104
- def self.hosts(options)
105
- # http://www.elasticsearch.org/guide/reference/modules/discovery/zen/
106
- result = Array.new
107
- if options[:hosts].class == Array
108
- options[:hosts].each do |host|
109
- if host.to_s =~ /^.+:.+$/
110
- # For host in format: host:port, ignore options[:port]
111
- result << host
112
- else
113
- if options[:port].to_s =~ /^\d+-\d+$/
114
- # port ranges are 'host[port1-port2]'
115
- result << Range.new(*options[:port].split("-")).collect { |p| "#{host}:#{p}" }
116
- else
117
- result << "#{host}:#{options[:port]}"
118
- end
119
- end
120
- end
121
- else
122
- if options[:hosts].to_s =~ /^.+:.+$/
123
- # For host in format: host:port, ignore options[:port]
124
- result << options[:hosts]
125
- else
126
- if options[:port].to_s =~ /^\d+-\d+$/
127
- # port ranges are 'host[port1-port2]' according to
128
- # http://www.elasticsearch.org/guide/reference/modules/discovery/zen/
129
- # However, it seems to only query the first port.
130
- # So generate our own list of unicast hosts to scan.
131
- range = Range.new(*options[:port].split("-"))
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
- def self.normalize_bulk_response(bulk_response)
142
- # TODO(talevy): parse item response objects to retrieve correct 200 (OK) or 201(created) status codes
143
- if bulk_response.has_failures()
144
- {"errors" => true,
145
- "statuses" => bulk_response.map { |i| (i.is_failed && i.get_failure.get_status.get_status) || 200 }}
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
- {"errors" => false}
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
- def bulk(actions)
152
- # Actions an array of [ action, action_metadata, source ]
153
- prep = client.prepareBulk
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
- raise "Could not index template!" unless response.isAcknowledged
227
- end # template_put
176
+ # def build_request
228
177
 
229
- public(:initialize, :bulk)
230
- end # class NodeClient
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
- class TransportClient < NodeClient
233
- def client
234
- return @client if @client
235
- @client = build_client(@options)
236
- return @client
237
- end
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
- private
241
- def build_client(options)
242
- client = org.elasticsearch.client.transport.TransportClient.
243
- builder().
244
- settings((settings.build)).
245
- build()
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
- options[:hosts].each do |host|
248
- matches = host.match /(.+)(?:.*)/
226
+ return client
227
+ end
249
228
 
250
- inet_addr = java.net.InetAddress.getByName(matches[1])
251
- port = (matches[2] || options[:port]).to_i
252
- client.addTransportAddress(
253
- org.elasticsearch.common.transport.InetSocketTransportAddress.new(
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
- return client
260
- end
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