fluent-plugin-elasticsearch 1.15.1 → 1.15.2
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/History.md +3 -0
- data/fluent-plugin-elasticsearch.gemspec +1 -1
- data/lib/fluent/plugin/elasticsearch_error_handler.rb +13 -18
- data/test/plugin/test_elasticsearch_error_handler.rb +182 -10
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc1ee6d297a64d46320b2b48b8528faf9a377f1a9af9274c083f36e0d7f48c88
|
4
|
+
data.tar.gz: ff6de82c88a71a3f8a3c47951fadf0b555fe4118feb18fe911c4ef7b66178218
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3123a75aeee15020ec775457d36bfe6eaf52ba22309163c37859ca096556605dc400a98495f587f954e2e7b4d4ad2aa9cf9b7010c9c75158d911feaa6e181fa9
|
7
|
+
data.tar.gz: 506fc86e5930c18c38992d477d7865363bd351851e141879c67834dca05828f710795fc63725a6f5bc7fde9732660fa97a5caec45d6361b6c974e391fa1ef36c
|
data/History.md
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = 'fluent-plugin-elasticsearch'
|
6
|
-
s.version = '1.15.
|
6
|
+
s.version = '1.15.2'
|
7
7
|
s.authors = ['diogo', 'pitr']
|
8
8
|
s.email = ['pitr.vern@gmail.com', 'me@diogoterror.com']
|
9
9
|
s.description = %q{Elasticsearch output plugin for Fluent event collector}
|
@@ -53,29 +53,24 @@ class Fluent::ElasticsearchErrorHandler
|
|
53
53
|
stats[type] += 1
|
54
54
|
end
|
55
55
|
end
|
56
|
-
if stats[:errors_bad_resp] > 0
|
57
|
-
@plugin.log.on_debug { @plugin.log.debug("Unable to parse response from elasticsearch, likely an API version mismatch: #{response}") }
|
58
|
-
raise ElasticsearchVersionMismatch, "Unable to parse error response from Elasticsearch, likely an API version mismatch. Add '@log_level debug' to your config to see the full response"
|
59
|
-
end
|
60
56
|
@plugin.log.on_debug do
|
61
57
|
msg = ["Indexed (op = #{@plugin.write_operation})"]
|
62
58
|
stats.each_pair { |key, value| msg << "#{value} #{key}" }
|
63
59
|
@plugin.log.debug msg.join(', ')
|
64
60
|
end
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
stats
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
61
|
+
case
|
62
|
+
when stats[:errors_bad_resp] > 0
|
63
|
+
@plugin.log.on_debug { @plugin.log.debug("Unable to parse response from elasticsearch, likely an API version mismatch: #{response}") }
|
64
|
+
raise ElasticsearchVersionMismatch, "Unable to parse error response from Elasticsearch, likely an API version mismatch. Add '@log_level debug' to your config to see the full response"
|
65
|
+
when stats[:successes] + stats[:duplicates] == bulk_message_count
|
66
|
+
@plugin.log.info("retry succeeded - successes=#{stats[:successes]} duplicates=#{stats[:duplicates]}")
|
67
|
+
when stats['es_rejected_execution_exception'] > 0
|
68
|
+
raise BulkIndexQueueFull, 'Bulk index queue is full, retrying'
|
69
|
+
when stats['out_of_memory_error'] > 0
|
70
|
+
raise ElasticsearchOutOfMemory, 'Elasticsearch has exhausted its heap, retrying'
|
71
|
+
else
|
72
|
+
@plugin.log.on_debug { @plugin.log.debug("Elasticsearch errors returned, retrying: #{response}") }
|
73
|
+
raise ElasticsearchError, "Elasticsearch returned errors, retrying. Add '@log_level debug' to your config to see the full response"
|
79
74
|
end
|
80
75
|
end
|
81
76
|
end
|
@@ -6,20 +6,25 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
|
|
6
6
|
|
7
7
|
class TestPlugin
|
8
8
|
attr_reader :log
|
9
|
+
attr_reader :write_operation
|
9
10
|
def initialize(log)
|
10
11
|
@log = log
|
11
|
-
|
12
|
-
|
13
|
-
def write_operation
|
14
|
-
'index'
|
12
|
+
@write_operation = 'index'
|
15
13
|
end
|
16
14
|
end
|
17
15
|
|
18
16
|
def setup
|
19
17
|
Fluent::Test.setup
|
20
|
-
@
|
21
|
-
|
22
|
-
|
18
|
+
@log_device = Fluent::Test::DummyLogDevice.new
|
19
|
+
if defined?(ServerEngine::DaemonLogger)
|
20
|
+
dl_opts = {:log_level => ServerEngine::DaemonLogger::INFO}
|
21
|
+
logger = ServerEngine::DaemonLogger.new(@log_device, dl_opts)
|
22
|
+
@log = Fluent::Log.new(logger)
|
23
|
+
else
|
24
|
+
@log = Fluent::Log.new(@log_device, Fluent::Log::LEVEL_INFO)
|
25
|
+
end
|
26
|
+
@plugin = TestPlugin.new(@log)
|
27
|
+
@handler = Fluent::ElasticsearchErrorHandler.new(@plugin)
|
23
28
|
end
|
24
29
|
|
25
30
|
def parse_response(value)
|
@@ -39,7 +44,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
|
|
39
44
|
"status" : 500,
|
40
45
|
"error" : {
|
41
46
|
"type" : "some unrecognized type",
|
42
|
-
"reason":"
|
47
|
+
"reason":"unrecognized error"
|
43
48
|
}
|
44
49
|
}
|
45
50
|
},
|
@@ -51,7 +56,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
|
|
51
56
|
"status" : 500,
|
52
57
|
"error" : {
|
53
58
|
"type" : "some unrecognized type",
|
54
|
-
"reason":"
|
59
|
+
"reason":"unrecognized error"
|
55
60
|
}
|
56
61
|
}
|
57
62
|
},
|
@@ -79,7 +84,7 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
|
|
79
84
|
"status" : 400,
|
80
85
|
"error" : {
|
81
86
|
"type" : "some unrecognized type",
|
82
|
-
"reason":"
|
87
|
+
"reason":"unrecognized error"
|
83
88
|
}
|
84
89
|
}
|
85
90
|
}
|
@@ -119,4 +124,171 @@ class TestElasticsearchErrorHandler < Test::Unit::TestCase
|
|
119
124
|
|
120
125
|
end
|
121
126
|
|
127
|
+
def test_retry_with_successes_and_duplicates
|
128
|
+
response = parse_response(%(
|
129
|
+
{
|
130
|
+
"took" : 0,
|
131
|
+
"errors" : true,
|
132
|
+
"items" : [
|
133
|
+
{
|
134
|
+
"create" : {
|
135
|
+
"_index" : "foo",
|
136
|
+
"_type" : "bar",
|
137
|
+
"_id" : "abc",
|
138
|
+
"status" : 409,
|
139
|
+
"error" : {
|
140
|
+
"reason":"duplicate ID"
|
141
|
+
}
|
142
|
+
}
|
143
|
+
},
|
144
|
+
{
|
145
|
+
"create" : {
|
146
|
+
"_index" : "foo",
|
147
|
+
"_type" : "bar",
|
148
|
+
"_id" : "abc",
|
149
|
+
"status" : 201
|
150
|
+
}
|
151
|
+
}
|
152
|
+
]
|
153
|
+
}
|
154
|
+
))
|
155
|
+
|
156
|
+
@plugin.instance_variable_set(:@write_operation, 'create')
|
157
|
+
@handler.instance_variable_set(:@bulk_message_count, 2)
|
158
|
+
@handler.handle_error(response)
|
159
|
+
assert_match /retry succeeded - successes=1 duplicates=1/, @log.out.logs[0]
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_bulk_rejection_errors
|
163
|
+
response = parse_response(%({
|
164
|
+
"took" : 0,
|
165
|
+
"errors" : true,
|
166
|
+
"items" : [
|
167
|
+
{
|
168
|
+
"create" : {
|
169
|
+
"_index" : "foo",
|
170
|
+
"_type" : "bar",
|
171
|
+
"_id" : "abc",
|
172
|
+
"status" : 500,
|
173
|
+
"error" : {
|
174
|
+
"type" : "some unrecognized type",
|
175
|
+
"reason":"unrecognized error"
|
176
|
+
}
|
177
|
+
}
|
178
|
+
},
|
179
|
+
{
|
180
|
+
"create" : {
|
181
|
+
"_index" : "foo",
|
182
|
+
"_type" : "bar",
|
183
|
+
"_id" : "abc",
|
184
|
+
"status" : 500,
|
185
|
+
"error" : {
|
186
|
+
"type" : "some unrecognized type",
|
187
|
+
"reason":"unrecognized error"
|
188
|
+
}
|
189
|
+
}
|
190
|
+
},
|
191
|
+
{
|
192
|
+
"create" : {
|
193
|
+
"_index" : "foo",
|
194
|
+
"_type" : "bar",
|
195
|
+
"_id" : "abc",
|
196
|
+
"status" : 201
|
197
|
+
}
|
198
|
+
},
|
199
|
+
{
|
200
|
+
"create" : {
|
201
|
+
"_index" : "foo",
|
202
|
+
"_type" : "bar",
|
203
|
+
"_id" : "abc",
|
204
|
+
"status" : 409
|
205
|
+
}
|
206
|
+
},
|
207
|
+
{
|
208
|
+
"create" : {
|
209
|
+
"_index" : "foo",
|
210
|
+
"_type" : "bar",
|
211
|
+
"_id" : "abc",
|
212
|
+
"status" : 429,
|
213
|
+
"error" : {
|
214
|
+
"type" : "es_rejected_execution_exception",
|
215
|
+
"reason":"Elasticsearch could not process bulk index request"
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
]
|
220
|
+
}))
|
221
|
+
|
222
|
+
assert_raise Fluent::ElasticsearchErrorHandler::BulkIndexQueueFull do
|
223
|
+
@handler.handle_error(response)
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_out_of_memory_errors
|
229
|
+
response = parse_response(%({
|
230
|
+
"took" : 0,
|
231
|
+
"errors" : true,
|
232
|
+
"items" : [
|
233
|
+
{
|
234
|
+
"create" : {
|
235
|
+
"_index" : "foo",
|
236
|
+
"_type" : "bar",
|
237
|
+
"_id" : "abc",
|
238
|
+
"status" : 500,
|
239
|
+
"error" : {
|
240
|
+
"type" : "some unrecognized type",
|
241
|
+
"reason":"unrecognized error"
|
242
|
+
}
|
243
|
+
}
|
244
|
+
},
|
245
|
+
{
|
246
|
+
"create" : {
|
247
|
+
"_index" : "foo",
|
248
|
+
"_type" : "bar",
|
249
|
+
"_id" : "abc",
|
250
|
+
"status" : 500,
|
251
|
+
"error" : {
|
252
|
+
"type" : "some unrecognized type",
|
253
|
+
"reason":"unrecognized error"
|
254
|
+
}
|
255
|
+
}
|
256
|
+
},
|
257
|
+
{
|
258
|
+
"create" : {
|
259
|
+
"_index" : "foo",
|
260
|
+
"_type" : "bar",
|
261
|
+
"_id" : "abc",
|
262
|
+
"status" : 201
|
263
|
+
}
|
264
|
+
},
|
265
|
+
{
|
266
|
+
"create" : {
|
267
|
+
"_index" : "foo",
|
268
|
+
"_type" : "bar",
|
269
|
+
"_id" : "abc",
|
270
|
+
"status" : 409
|
271
|
+
}
|
272
|
+
},
|
273
|
+
{
|
274
|
+
"create" : {
|
275
|
+
"_index" : "foo",
|
276
|
+
"_type" : "bar",
|
277
|
+
"_id" : "abc",
|
278
|
+
"status" : 400,
|
279
|
+
"error" : {
|
280
|
+
"type" : "out_of_memory_error",
|
281
|
+
"reason":"Elasticsearch exhausted its heap"
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
]
|
286
|
+
}))
|
287
|
+
|
288
|
+
assert_raise Fluent::ElasticsearchErrorHandler::ElasticsearchOutOfMemory do
|
289
|
+
@handler.handle_error(response)
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|
293
|
+
|
122
294
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-elasticsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.15.
|
4
|
+
version: 1.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- diogo
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-04-
|
12
|
+
date: 2018-04-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fluentd
|