fluent-plugin-elasticsearch 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +3 -0
- data/fluent-plugin-elasticsearch.gemspec +1 -1
- data/lib/fluent/plugin/elasticsearch_constants.rb +13 -0
- data/lib/fluent/plugin/elasticsearch_error_handler.rb +96 -0
- data/lib/fluent/plugin/out_elasticsearch.rb +7 -8
- data/test/plugin/test_out_elasticsearch.rb +231 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16f9f3e664e714be9d1e7fee4b3f8a1683ec9728
|
4
|
+
data.tar.gz: beb9fa49cb58739036a3f2c1cda6ee936fbd873d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8527ebae2dbdb312cc6ed32af668077f9560b74db612a4f5d381f758e4e9cb4aa6230a6859a4a72c3f2b944b1fbf07292a49804cd4648a81392259938f133bab
|
7
|
+
data.tar.gz: 887830c553b5ed0350bf64aba4f38d24c28c557fad5493c3ae5f350049269737645e93addfac89b0c252898d07cc127707a9d35f23470ea45cd35f5df48839e0
|
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 = '2.0
|
6
|
+
s.version = '2.1.0'
|
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}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fluent
|
2
|
+
module Plugin
|
3
|
+
module ElasticsearchConstants
|
4
|
+
BODY_DELIMITER = "\n".freeze
|
5
|
+
UPDATE_OP = "update".freeze
|
6
|
+
UPSERT_OP = "upsert".freeze
|
7
|
+
CREATE_OP = "create".freeze
|
8
|
+
INDEX_OP = "index".freeze
|
9
|
+
ID_FIELD = "_id".freeze
|
10
|
+
TIMESTAMP_FIELD = "@timestamp".freeze
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require_relative 'elasticsearch_constants'
|
2
|
+
|
3
|
+
class Fluent::Plugin::ElasticsearchErrorHandler
|
4
|
+
include Fluent::Plugin::ElasticsearchConstants
|
5
|
+
|
6
|
+
attr_accessor :records, :bulk_message_count
|
7
|
+
class BulkIndexQueueFull < StandardError; end
|
8
|
+
class ElasticsearchOutOfMemory < StandardError; end
|
9
|
+
class ElasticsearchVersionMismatch < StandardError; end
|
10
|
+
class UnrecognizedElasticsearchError < StandardError; end
|
11
|
+
class ElasticsearchError < StandardError; end
|
12
|
+
def initialize(plugin, records = 0, bulk_message_count = 0)
|
13
|
+
@plugin = plugin
|
14
|
+
@records = records
|
15
|
+
@bulk_message_count = bulk_message_count
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle_error(response)
|
19
|
+
errors = Hash.new(0)
|
20
|
+
errors_bad_resp = 0
|
21
|
+
errors_unrecognized = 0
|
22
|
+
successes = 0
|
23
|
+
duplicates = 0
|
24
|
+
bad_arguments = 0
|
25
|
+
response['items'].each do |item|
|
26
|
+
if item.has_key?(@plugin.write_operation)
|
27
|
+
write_operation = @plugin.write_operation
|
28
|
+
elsif INDEX_OP == @plugin.write_operation && item.has_key?(CREATE_OP)
|
29
|
+
write_operation = CREATE_OP
|
30
|
+
else
|
31
|
+
# When we don't have an expected ops field, something changed in the API
|
32
|
+
# expected return values (ES 2.x)
|
33
|
+
errors_bad_resp += 1
|
34
|
+
next
|
35
|
+
end
|
36
|
+
if item[write_operation].has_key?('status')
|
37
|
+
status = item[write_operation]['status']
|
38
|
+
else
|
39
|
+
# When we don't have a status field, something changed in the API
|
40
|
+
# expected return values (ES 2.x)
|
41
|
+
errors_bad_resp += 1
|
42
|
+
next
|
43
|
+
end
|
44
|
+
case
|
45
|
+
when CREATE_OP == write_operation && 409 == status
|
46
|
+
duplicates += 1
|
47
|
+
when 400 == status
|
48
|
+
bad_arguments += 1
|
49
|
+
@plugin.log.debug "Elasticsearch rejected document: #{item}"
|
50
|
+
when [429, 500].include?(status)
|
51
|
+
if item[write_operation].has_key?('error') && item[write_operation]['error'].has_key?('type')
|
52
|
+
type = item[write_operation]['error']['type']
|
53
|
+
else
|
54
|
+
# When we don't have a type field, something changed in the API
|
55
|
+
# expected return values (ES 2.x)
|
56
|
+
errors_bad_resp += 1
|
57
|
+
next
|
58
|
+
end
|
59
|
+
errors[type] += 1
|
60
|
+
when [200, 201].include?(status)
|
61
|
+
successes += 1
|
62
|
+
else
|
63
|
+
errors_unrecognized += 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
if errors_bad_resp > 0
|
67
|
+
msg = "Unable to parse error response from Elasticsearch, likely an API version mismatch #{response}"
|
68
|
+
@plugin.log.error msg
|
69
|
+
raise ElasticsearchVersionMismatch, msg
|
70
|
+
end
|
71
|
+
if bad_arguments > 0
|
72
|
+
@plugin.log.warn "Elasticsearch rejected #{bad_arguments} documents due to invalid field arguments"
|
73
|
+
end
|
74
|
+
if duplicates > 0
|
75
|
+
@plugin.log.info "Encountered #{duplicates} duplicate(s) of #{successes} indexing chunk, ignoring"
|
76
|
+
end
|
77
|
+
msg = "Indexed (op = #{@plugin.write_operation}) #{successes} successfully, #{duplicates} duplicate(s), #{bad_arguments} bad argument(s), #{errors_unrecognized} unrecognized error(s)"
|
78
|
+
errors.each_key do |key|
|
79
|
+
msg << ", #{errors[key]} #{key} error(s)"
|
80
|
+
end
|
81
|
+
@plugin.log.debug msg
|
82
|
+
if errors_unrecognized > 0
|
83
|
+
raise UnrecognizedElasticsearchError, "Unrecognized elasticsearch errors returned, retrying #{response}"
|
84
|
+
end
|
85
|
+
errors.each_key do |key|
|
86
|
+
case key
|
87
|
+
when 'out_of_memory_error'
|
88
|
+
raise ElasticsearchOutOfMemory, "Elasticsearch has exhausted its heap, retrying"
|
89
|
+
when 'es_rejected_execution_exception'
|
90
|
+
raise BulkIndexQueueFull, "Bulk index queue is full, retrying"
|
91
|
+
else
|
92
|
+
raise ElasticsearchError, "Elasticsearch errors returned, retrying #{response}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -10,6 +10,8 @@ rescue LoadError
|
|
10
10
|
end
|
11
11
|
|
12
12
|
require 'fluent/plugin/output'
|
13
|
+
require_relative 'elasticsearch_constants'
|
14
|
+
require_relative 'elasticsearch_error_handler'
|
13
15
|
require_relative 'elasticsearch_index_template'
|
14
16
|
require_relative 'generate_hash_id_support'
|
15
17
|
|
@@ -81,6 +83,7 @@ module Fluent::Plugin
|
|
81
83
|
|
82
84
|
include Fluent::ElasticsearchIndexTemplate
|
83
85
|
include Fluent::Plugin::GenerateHashIdSupport
|
86
|
+
include Fluent::Plugin::ElasticsearchConstants
|
84
87
|
|
85
88
|
def initialize
|
86
89
|
super
|
@@ -251,14 +254,6 @@ module Fluent::Plugin
|
|
251
254
|
end.join(', ')
|
252
255
|
end
|
253
256
|
|
254
|
-
BODY_DELIMITER = "\n".freeze
|
255
|
-
UPDATE_OP = "update".freeze
|
256
|
-
UPSERT_OP = "upsert".freeze
|
257
|
-
CREATE_OP = "create".freeze
|
258
|
-
INDEX_OP = "index".freeze
|
259
|
-
ID_FIELD = "_id".freeze
|
260
|
-
TIMESTAMP_FIELD = "@timestamp".freeze
|
261
|
-
|
262
257
|
def append_record_to_messages(op, meta, header, record, msgs)
|
263
258
|
case op
|
264
259
|
when UPDATE_OP, UPSERT_OP
|
@@ -334,8 +329,10 @@ module Fluent::Plugin
|
|
334
329
|
|
335
330
|
tag = chunk.metadata.tag
|
336
331
|
logstash_prefix, index_name = expand_placeholders(chunk.metadata)
|
332
|
+
@error = Fluent::Plugin::ElasticsearchErrorHandler.new(self)
|
337
333
|
|
338
334
|
chunk.msgpack_each do |time, record|
|
335
|
+
@error.records += 1
|
339
336
|
next unless record.is_a? Hash
|
340
337
|
|
341
338
|
if @flatten_hashes
|
@@ -402,6 +399,7 @@ module Fluent::Plugin
|
|
402
399
|
end
|
403
400
|
|
404
401
|
append_record_to_messages(@write_operation, meta, header, record, bulk_message)
|
402
|
+
@error.bulk_message_count += 1
|
405
403
|
end
|
406
404
|
|
407
405
|
send_bulk(bulk_message) unless bulk_message.empty?
|
@@ -420,6 +418,7 @@ module Fluent::Plugin
|
|
420
418
|
begin
|
421
419
|
response = client.bulk body: data
|
422
420
|
if response['errors']
|
421
|
+
@error.handle_error(response)
|
423
422
|
log.error "Could not push log to Elasticsearch: #{response}"
|
424
423
|
end
|
425
424
|
rescue *client.transport.host_unreachable_exceptions => e
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'date'
|
3
3
|
require 'fluent/test/helpers'
|
4
|
+
require 'json'
|
4
5
|
require 'fluent/test/driver/output'
|
5
6
|
require 'flexmock/test_unit'
|
6
7
|
|
@@ -59,6 +60,130 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
63
|
+
def make_response_body(req, error_el = nil, error_status = nil, error = nil)
|
64
|
+
req_index_cmds = req.body.split("\n").map { |r| JSON.parse(r) }
|
65
|
+
items = []
|
66
|
+
count = 0
|
67
|
+
ids = 1
|
68
|
+
op = nil
|
69
|
+
index = nil
|
70
|
+
type = nil
|
71
|
+
id = nil
|
72
|
+
req_index_cmds.each do |cmd|
|
73
|
+
if count.even?
|
74
|
+
op = cmd.keys[0]
|
75
|
+
index = cmd[op]['_index']
|
76
|
+
type = cmd[op]['_type']
|
77
|
+
if cmd[op].has_key?('_id')
|
78
|
+
id = cmd[op]['_id']
|
79
|
+
else
|
80
|
+
# Note: this appears to be an undocumented feature of Elasticsearch
|
81
|
+
# https://www.elastic.co/guide/en/elasticsearch/reference/2.4/docs-bulk.html
|
82
|
+
# When you submit an "index" write_operation, with no "_id" field in the
|
83
|
+
# metadata header, Elasticsearch will turn this into a "create"
|
84
|
+
# operation in the response.
|
85
|
+
if "index" == op
|
86
|
+
op = "create"
|
87
|
+
end
|
88
|
+
id = ids
|
89
|
+
ids += 1
|
90
|
+
end
|
91
|
+
else
|
92
|
+
item = {
|
93
|
+
op => {
|
94
|
+
'_index' => index, '_type' => type, '_id' => id, '_version' => 1,
|
95
|
+
'_shards' => { 'total' => 1, 'successful' => 1, 'failed' => 0 },
|
96
|
+
'status' => op == 'create' ? 201 : 200
|
97
|
+
}
|
98
|
+
}
|
99
|
+
items.push(item)
|
100
|
+
end
|
101
|
+
count += 1
|
102
|
+
end
|
103
|
+
if !error_el.nil? && !error_status.nil? && !error.nil?
|
104
|
+
op = items[error_el].keys[0]
|
105
|
+
items[error_el][op].delete('_version')
|
106
|
+
items[error_el][op].delete('_shards')
|
107
|
+
items[error_el][op]['error'] = error
|
108
|
+
items[error_el][op]['status'] = error_status
|
109
|
+
errors = true
|
110
|
+
else
|
111
|
+
errors = false
|
112
|
+
end
|
113
|
+
@index_cmds = items
|
114
|
+
body = { 'took' => 6, 'errors' => errors, 'items' => items }
|
115
|
+
return body.to_json
|
116
|
+
end
|
117
|
+
|
118
|
+
def stub_elastic_bad_argument(url="http://localhost:9200/_bulk")
|
119
|
+
error = {
|
120
|
+
"type" => "mapper_parsing_exception",
|
121
|
+
"reason" => "failed to parse [...]",
|
122
|
+
"caused_by" => {
|
123
|
+
"type" => "illegal_argument_exception",
|
124
|
+
"reason" => "Invalid format: \"...\""
|
125
|
+
}
|
126
|
+
}
|
127
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 400, error), :headers => { 'Content-Type' => 'json' } } })
|
128
|
+
end
|
129
|
+
|
130
|
+
def stub_elastic_bulk_error(url="http://localhost:9200/_bulk")
|
131
|
+
error = {
|
132
|
+
"type" => "some-unrecognized-error",
|
133
|
+
"reason" => "some message printed here ...",
|
134
|
+
}
|
135
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 500, error), :headers => { 'Content-Type' => 'json' } } })
|
136
|
+
end
|
137
|
+
|
138
|
+
def stub_elastic_bulk_rejected(url="http://localhost:9200/_bulk")
|
139
|
+
error = {
|
140
|
+
"type" => "es_rejected_execution_exception",
|
141
|
+
"reason" => "rejected execution of org.elasticsearch.transport.TransportService$4@1a34d37a on EsThreadPoolExecutor[bulk, queue capacity = 50, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@312a2162[Running, pool size = 32, active threads = 32, queued tasks = 50, completed tasks = 327053]]"
|
142
|
+
}
|
143
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 429, error), :headers => { 'Content-Type' => 'json' } } })
|
144
|
+
end
|
145
|
+
|
146
|
+
def stub_elastic_out_of_memory(url="http://localhost:9200/_bulk")
|
147
|
+
error = {
|
148
|
+
"type" => "out_of_memory_error",
|
149
|
+
"reason" => "Java heap space"
|
150
|
+
}
|
151
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 500, error), :headers => { 'Content-Type' => 'json' } } })
|
152
|
+
end
|
153
|
+
|
154
|
+
def stub_elastic_unrecognized_error(url="http://localhost:9200/_bulk")
|
155
|
+
error = {
|
156
|
+
"type" => "some-other-type",
|
157
|
+
"reason" => "some-other-reason"
|
158
|
+
}
|
159
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 504, error), :headers => { 'Content-Type' => 'json' } } })
|
160
|
+
end
|
161
|
+
|
162
|
+
def stub_elastic_version_mismatch(url="http://localhost:9200/_bulk")
|
163
|
+
error = {
|
164
|
+
"category" => "some-other-type",
|
165
|
+
"reason" => "some-other-reason"
|
166
|
+
}
|
167
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 1, 500, error), :headers => { 'Content-Type' => 'json' } } })
|
168
|
+
end
|
169
|
+
|
170
|
+
def stub_elastic_index_to_create(url="http://localhost:9200/_bulk")
|
171
|
+
error = {
|
172
|
+
"category" => "some-other-type",
|
173
|
+
"reason" => "some-other-reason",
|
174
|
+
"type" => "some-other-type"
|
175
|
+
}
|
176
|
+
stub_request(:post, url).to_return(lambda { |req| { :status => 200, :body => make_response_body(req, 0, 500, error), :headers => { 'Content-Type' => 'json' } } })
|
177
|
+
end
|
178
|
+
|
179
|
+
def stub_elastic_unexpected_response_op(url="http://localhost:9200/_bulk")
|
180
|
+
error = {
|
181
|
+
"category" => "some-other-type",
|
182
|
+
"reason" => "some-other-reason"
|
183
|
+
}
|
184
|
+
stub_request(:post, url).to_return(lambda { |req| bodystr = make_response_body(req, 0, 500, error); body = JSON.parse(bodystr); body['items'][0]['unknown'] = body['items'][0].delete('create'); { :status => 200, :body => body.to_json, :headers => { 'Content-Type' => 'json' } } })
|
185
|
+
end
|
186
|
+
|
62
187
|
def test_configure
|
63
188
|
config = %{
|
64
189
|
host logs.google.com
|
@@ -1394,6 +1519,112 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
1394
1519
|
assert_equal(connection_resets, 1)
|
1395
1520
|
end
|
1396
1521
|
|
1522
|
+
def test_bulk_bad_arguments
|
1523
|
+
driver = driver('@log_level debug')
|
1524
|
+
|
1525
|
+
stub_elastic_ping
|
1526
|
+
stub_elastic_bad_argument
|
1527
|
+
|
1528
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1529
|
+
driver.feed(sample_record)
|
1530
|
+
driver.feed(sample_record)
|
1531
|
+
driver.feed(sample_record)
|
1532
|
+
end
|
1533
|
+
|
1534
|
+
matches = driver.logs.grep /Elasticsearch rejected document:/
|
1535
|
+
assert_equal(1, matches.length, "Message 'Elasticsearch rejected document: ...' was not emitted")
|
1536
|
+
matches = driver.logs.grep /documents due to invalid field arguments/
|
1537
|
+
assert_equal(1, matches.length, "Message 'Elasticsearch rejected # documents due to invalid field arguments ...' was not emitted")
|
1538
|
+
end
|
1539
|
+
|
1540
|
+
def test_bulk_error
|
1541
|
+
stub_elastic_ping
|
1542
|
+
stub_elastic_bulk_error
|
1543
|
+
|
1544
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError) {
|
1545
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1546
|
+
driver.feed(sample_record)
|
1547
|
+
driver.feed(sample_record)
|
1548
|
+
driver.feed(sample_record)
|
1549
|
+
end
|
1550
|
+
}
|
1551
|
+
end
|
1552
|
+
|
1553
|
+
def test_bulk_error_version_mismatch
|
1554
|
+
stub_elastic_ping
|
1555
|
+
stub_elastic_version_mismatch
|
1556
|
+
|
1557
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchVersionMismatch) {
|
1558
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1559
|
+
driver.feed(sample_record)
|
1560
|
+
driver.feed(sample_record)
|
1561
|
+
driver.feed(sample_record)
|
1562
|
+
end
|
1563
|
+
}
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
def test_bulk_error_unrecognized_error
|
1567
|
+
stub_elastic_ping
|
1568
|
+
stub_elastic_unrecognized_error
|
1569
|
+
|
1570
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::UnrecognizedElasticsearchError) {
|
1571
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1572
|
+
driver.feed(sample_record)
|
1573
|
+
driver.feed(sample_record)
|
1574
|
+
driver.feed(sample_record)
|
1575
|
+
end
|
1576
|
+
}
|
1577
|
+
end
|
1578
|
+
|
1579
|
+
def test_bulk_error_out_of_memory
|
1580
|
+
stub_elastic_ping
|
1581
|
+
stub_elastic_out_of_memory
|
1582
|
+
|
1583
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchOutOfMemory) {
|
1584
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1585
|
+
driver.feed(sample_record)
|
1586
|
+
driver.feed(sample_record)
|
1587
|
+
driver.feed(sample_record)
|
1588
|
+
end
|
1589
|
+
}
|
1590
|
+
end
|
1591
|
+
|
1592
|
+
def test_bulk_error_queue_full
|
1593
|
+
stub_elastic_ping
|
1594
|
+
stub_elastic_bulk_rejected
|
1595
|
+
|
1596
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::BulkIndexQueueFull) {
|
1597
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1598
|
+
driver.feed(sample_record)
|
1599
|
+
driver.feed(sample_record)
|
1600
|
+
driver.feed(sample_record)
|
1601
|
+
end
|
1602
|
+
}
|
1603
|
+
end
|
1604
|
+
|
1605
|
+
def test_bulk_index_into_a_create
|
1606
|
+
stub_elastic_ping
|
1607
|
+
stub_elastic_index_to_create
|
1608
|
+
|
1609
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchError) {
|
1610
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1611
|
+
driver.feed(sample_record)
|
1612
|
+
end
|
1613
|
+
}
|
1614
|
+
assert(index_cmds[0].has_key?("create"))
|
1615
|
+
end
|
1616
|
+
|
1617
|
+
def test_bulk_unexpected_response_op
|
1618
|
+
stub_elastic_ping
|
1619
|
+
stub_elastic_unexpected_response_op
|
1620
|
+
|
1621
|
+
assert_raise(Fluent::Plugin::ElasticsearchErrorHandler::ElasticsearchVersionMismatch) {
|
1622
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1623
|
+
driver.feed(sample_record)
|
1624
|
+
end
|
1625
|
+
}
|
1626
|
+
end
|
1627
|
+
|
1397
1628
|
def test_update_should_not_write_if_theres_no_id
|
1398
1629
|
driver.configure("write_operation update\n")
|
1399
1630
|
stub_elastic_ping
|
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: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- diogo
|
@@ -143,6 +143,8 @@ files:
|
|
143
143
|
- README.md
|
144
144
|
- Rakefile
|
145
145
|
- fluent-plugin-elasticsearch.gemspec
|
146
|
+
- lib/fluent/plugin/elasticsearch_constants.rb
|
147
|
+
- lib/fluent/plugin/elasticsearch_error_handler.rb
|
146
148
|
- lib/fluent/plugin/elasticsearch_index_template.rb
|
147
149
|
- lib/fluent/plugin/generate_hash_id_support.rb
|
148
150
|
- lib/fluent/plugin/out_elasticsearch.rb
|