logstash-output-elasticsearch 3.0.2-java → 4.1.0-java
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 +16 -3
- data/Gemfile +1 -1
- data/lib/logstash/outputs/elasticsearch/common.rb +90 -58
- data/lib/logstash/outputs/elasticsearch/common_configs.rb +12 -32
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +63 -0
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +378 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +70 -64
- data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +15 -4
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +1 -1
- data/lib/logstash/outputs/elasticsearch.rb +27 -4
- data/logstash-output-elasticsearch.gemspec +3 -5
- data/spec/es_spec_helper.rb +1 -0
- data/spec/fixtures/5x_node_resp.json +2 -0
- data/spec/integration/outputs/create_spec.rb +2 -5
- data/spec/integration/outputs/index_spec.rb +1 -1
- data/spec/integration/outputs/parent_spec.rb +1 -3
- data/spec/integration/outputs/pipeline_spec.rb +1 -2
- data/spec/integration/outputs/retry_spec.rb +51 -49
- data/spec/integration/outputs/routing_spec.rb +1 -1
- data/spec/integration/outputs/secure_spec.rb +4 -8
- data/spec/integration/outputs/templates_spec.rb +12 -8
- data/spec/integration/outputs/update_spec.rb +13 -27
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +25 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +142 -0
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +8 -22
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +5 -6
- data/spec/unit/outputs/elasticsearch_spec.rb +33 -30
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +10 -6
- metadata +72 -87
- data/lib/logstash/outputs/elasticsearch/buffer.rb +0 -124
- data/spec/unit/buffer_spec.rb +0 -118
@@ -1,124 +0,0 @@
|
|
1
|
-
require 'concurrent'
|
2
|
-
java_import java.util.concurrent.locks.ReentrantLock
|
3
|
-
|
4
|
-
module LogStash; module Outputs; class ElasticSearch
|
5
|
-
class Buffer
|
6
|
-
def initialize(logger, max_size, flush_interval, &block)
|
7
|
-
@logger = logger
|
8
|
-
# You need to aquire this for anything modifying state generally
|
9
|
-
@operations_mutex = Mutex.new
|
10
|
-
@operations_lock = java.util.concurrent.locks.ReentrantLock.new
|
11
|
-
|
12
|
-
@stopping = Concurrent::AtomicBoolean.new(false)
|
13
|
-
@max_size = max_size
|
14
|
-
@submit_proc = block
|
15
|
-
|
16
|
-
@buffer = []
|
17
|
-
|
18
|
-
@last_flush = Time.now
|
19
|
-
@flush_interval = flush_interval
|
20
|
-
@flush_thread = spawn_interval_flusher
|
21
|
-
end
|
22
|
-
|
23
|
-
def push(item)
|
24
|
-
synchronize do |buffer|
|
25
|
-
push_unsafe(item)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
alias_method :<<, :push
|
29
|
-
|
30
|
-
# Push multiple items onto the buffer in a single operation
|
31
|
-
def push_multi(items)
|
32
|
-
raise ArgumentError, "push multi takes an array!, not an #{items.class}!" unless items.is_a?(Array)
|
33
|
-
synchronize do |buffer|
|
34
|
-
items.each {|item| push_unsafe(item) }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def flush
|
39
|
-
synchronize { flush_unsafe }
|
40
|
-
end
|
41
|
-
|
42
|
-
def stop(do_flush=true,wait_complete=true)
|
43
|
-
return if stopping?
|
44
|
-
@stopping.make_true
|
45
|
-
|
46
|
-
# No need to acquire a lock in this case
|
47
|
-
return if !do_flush && !wait_complete
|
48
|
-
|
49
|
-
synchronize do
|
50
|
-
flush_unsafe if do_flush
|
51
|
-
@flush_thread.join if wait_complete
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def contents
|
56
|
-
synchronize {|buffer| buffer}
|
57
|
-
end
|
58
|
-
|
59
|
-
# For externally operating on the buffer contents
|
60
|
-
# this takes a block and will yield the internal buffer and executes
|
61
|
-
# the block in a synchronized block from the internal mutex
|
62
|
-
def synchronize
|
63
|
-
@operations_mutex.synchronize { yield(@buffer) }
|
64
|
-
end
|
65
|
-
|
66
|
-
# These methods are private for various reasons, chief among them threadsafety!
|
67
|
-
# Many require the @operations_mutex to be locked to be safe
|
68
|
-
private
|
69
|
-
|
70
|
-
def push_unsafe(item)
|
71
|
-
@buffer << item
|
72
|
-
if @buffer.size >= @max_size
|
73
|
-
flush_unsafe
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def spawn_interval_flusher
|
78
|
-
Thread.new do
|
79
|
-
loop do
|
80
|
-
sleep 0.2
|
81
|
-
break if stopping?
|
82
|
-
synchronize { interval_flush }
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def interval_flush
|
88
|
-
if last_flush_seconds_ago >= @flush_interval
|
89
|
-
begin
|
90
|
-
@logger.debug? && @logger.debug("Flushing buffer at interval",
|
91
|
-
:instance => self.inspect,
|
92
|
-
:interval => @flush_interval)
|
93
|
-
flush_unsafe
|
94
|
-
rescue StandardError => e
|
95
|
-
@logger.warn("Error flushing buffer at interval!",
|
96
|
-
:instance => self.inspect,
|
97
|
-
:message => e.message,
|
98
|
-
:class => e.class.name,
|
99
|
-
:backtrace => e.backtrace
|
100
|
-
)
|
101
|
-
rescue Exception => e
|
102
|
-
@logger.warn("Exception flushing buffer at interval!", :error => e.message, :class => e.class.name)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def flush_unsafe
|
108
|
-
if @buffer.size > 0
|
109
|
-
@submit_proc.call(@buffer)
|
110
|
-
@buffer.clear
|
111
|
-
end
|
112
|
-
|
113
|
-
@last_flush = Time.now # This must always be set to ensure correct timer behavior
|
114
|
-
end
|
115
|
-
|
116
|
-
def last_flush_seconds_ago
|
117
|
-
Time.now - @last_flush
|
118
|
-
end
|
119
|
-
|
120
|
-
def stopping?
|
121
|
-
@stopping.true?
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end end end
|
data/spec/unit/buffer_spec.rb
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
require "logstash/outputs/elasticsearch"
|
2
|
-
require "logstash/outputs/elasticsearch/buffer"
|
3
|
-
|
4
|
-
describe LogStash::Outputs::ElasticSearch::Buffer do
|
5
|
-
class OperationTarget # Used to track buffer flushesn
|
6
|
-
attr_reader :buffer, :buffer_history, :receive_count
|
7
|
-
def initialize
|
8
|
-
@buffer = nil
|
9
|
-
@buffer_history = []
|
10
|
-
@receive_count = 0
|
11
|
-
end
|
12
|
-
|
13
|
-
def receive(buffer)
|
14
|
-
@receive_count += 1
|
15
|
-
@buffer_history << buffer.clone
|
16
|
-
@buffer = buffer
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
let(:logger) { Cabin::Channel.get }
|
21
|
-
let(:max_size) { 10 }
|
22
|
-
let(:flush_interval) { 2 }
|
23
|
-
# Used to track flush count
|
24
|
-
let(:operation_target) { OperationTarget.new() }
|
25
|
-
let(:operation) { proc {|buffer| operation_target.receive(buffer) } }
|
26
|
-
subject(:buffer){ LogStash::Outputs::ElasticSearch::Buffer.new(logger, max_size, flush_interval, &operation) }
|
27
|
-
|
28
|
-
after(:each) do
|
29
|
-
buffer.stop(do_flush=false)
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should initialize cleanly" do
|
33
|
-
expect(buffer).to be_a(LogStash::Outputs::ElasticSearch::Buffer)
|
34
|
-
end
|
35
|
-
|
36
|
-
shared_examples("a buffer with two items inside") do
|
37
|
-
it "should add a pushed item to the buffer" do
|
38
|
-
buffer.synchronize do |data|
|
39
|
-
expect(data).to include(item1)
|
40
|
-
expect(data).to include(item2)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "interval flushing" do
|
45
|
-
before do
|
46
|
-
sleep flush_interval + 1
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should flush the buffer after the interval has passed" do
|
50
|
-
expect(operation_target.receive_count).to eql(1)
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should clear the buffer after a successful flush" do
|
54
|
-
expect(operation_target.buffer).to eql([])
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "interval flushing a stopped buffer" do
|
59
|
-
before do
|
60
|
-
buffer.stop(do_flush=false)
|
61
|
-
sleep flush_interval + 1
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should not flush if the buffer is stopped" do
|
65
|
-
expect(operation_target.receive_count).to eql(0)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "with a buffer push" do
|
71
|
-
let(:item1) { "foo" }
|
72
|
-
let(:item2) { "bar" }
|
73
|
-
|
74
|
-
describe "a buffer with two items pushed to it separately" do
|
75
|
-
before do
|
76
|
-
buffer << item1
|
77
|
-
buffer << item2
|
78
|
-
end
|
79
|
-
|
80
|
-
include_examples("a buffer with two items inside")
|
81
|
-
end
|
82
|
-
|
83
|
-
describe "a buffer with two items pushed to it in one operation" do
|
84
|
-
before do
|
85
|
-
buffer.push_multi([item1, item2])
|
86
|
-
end
|
87
|
-
|
88
|
-
include_examples("a buffer with two items inside")
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe "with an empty buffer" do
|
93
|
-
it "should not perform an operation if the buffer is empty" do
|
94
|
-
buffer.flush
|
95
|
-
expect(operation_target.receive_count).to eql(0)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
describe "flushing with an operation that raises an error" do
|
100
|
-
class TestError < StandardError; end
|
101
|
-
let(:operation) { proc {|buffer| raise TestError, "A test" } }
|
102
|
-
let(:item) { double("item") }
|
103
|
-
|
104
|
-
before do
|
105
|
-
buffer << item
|
106
|
-
end
|
107
|
-
|
108
|
-
it "should raise an exception" do
|
109
|
-
expect { buffer.flush }.to raise_error(TestError)
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should not clear the buffer" do
|
113
|
-
expect do
|
114
|
-
buffer.flush rescue TestError
|
115
|
-
end.not_to change(buffer, :contents)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|