logstash-output-elasticsearch 0.2.8-java → 0.2.9-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,114 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ shared_examples "a routing indexer" do
4
+ let(:index) { 10.times.collect { rand(10).to_s }.join("") }
5
+ let(:type) { 10.times.collect { rand(10).to_s }.join("") }
6
+ let(:event_count) { 10000 + rand(500) }
7
+ let(:flush_size) { rand(200) + 1 }
8
+ let(:routing) { "not_implemented" }
9
+ let(:config) { "not_implemented" }
10
+
11
+ it "ships events" do
12
+ insist { routing } != "not_implemented"
13
+ insist { config } != "not_implemented"
14
+
15
+ pipeline = LogStash::Pipeline.new(config)
16
+ pipeline.run
17
+
18
+ index_url = "http://#{get_host()}:#{get_port('http')}/#{index}"
19
+
20
+ ftw = FTW::Agent.new
21
+ ftw.post!("#{index_url}/_refresh")
22
+
23
+ # Wait until all events are available.
24
+ Stud::try(10.times) do
25
+ data = ""
26
+ response = ftw.get!("#{index_url}/_count?q=*&routing=#{routing}")
27
+ response.read_body { |chunk| data << chunk }
28
+ result = LogStash::Json.load(data)
29
+ cur_count = result["count"]
30
+ insist { cur_count } == event_count
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "(http protocol) index events with static routing", :integration => true do
36
+ it_behaves_like 'a routing indexer' do
37
+ let(:routing) { "test" }
38
+ let(:config) {
39
+ <<-CONFIG
40
+ input {
41
+ generator {
42
+ message => "hello world"
43
+ count => #{event_count}
44
+ type => "#{type}"
45
+ }
46
+ }
47
+ output {
48
+ elasticsearch {
49
+ host => "#{get_host()}"
50
+ port => "#{get_port('http')}"
51
+ protocol => "http"
52
+ index => "#{index}"
53
+ flush_size => #{flush_size}
54
+ routing => "#{routing}"
55
+ }
56
+ }
57
+ CONFIG
58
+ }
59
+ end
60
+ end
61
+
62
+ describe "(http_protocol) index events with fieldref in routing value", :integration => true do
63
+ it_behaves_like 'a routing indexer' do
64
+ let(:routing) { "test" }
65
+ let(:config) {
66
+ <<-CONFIG
67
+ input {
68
+ generator {
69
+ message => "#{routing}"
70
+ count => #{event_count}
71
+ type => "#{type}"
72
+ }
73
+ }
74
+ output {
75
+ elasticsearch {
76
+ host => "#{get_host()}"
77
+ port => "#{get_port('http')}"
78
+ protocol => "http"
79
+ index => "#{index}"
80
+ flush_size => #{flush_size}
81
+ routing => "%{message}"
82
+ }
83
+ }
84
+ CONFIG
85
+ }
86
+ end
87
+ end
88
+
89
+ describe "(transport protocol) index events with fieldref in routing value", :integration => true do
90
+ it_behaves_like 'a routing indexer' do
91
+ let(:routing) { "test" }
92
+ let(:config) {
93
+ <<-CONFIG
94
+ input {
95
+ generator {
96
+ message => "#{routing}"
97
+ count => #{event_count}
98
+ type => "#{type}"
99
+ }
100
+ }
101
+ output {
102
+ elasticsearch {
103
+ host => "#{get_host()}"
104
+ port => "#{get_port('transport')}"
105
+ protocol => "transport"
106
+ index => "#{index}"
107
+ flush_size => #{flush_size}
108
+ routing => "%{message}"
109
+ }
110
+ }
111
+ CONFIG
112
+ }
113
+ end
114
+ end
@@ -0,0 +1,113 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "send messages to ElasticSearch using HTTPS", :elasticsearch_secure => true do
4
+ subject do
5
+ require "logstash/outputs/elasticsearch"
6
+ settings = {
7
+ "protocol" => "http",
8
+ "node_name" => "logstash",
9
+ "cluster" => "elasticsearch",
10
+ "host" => "node01",
11
+ "user" => "user",
12
+ "password" => "changeme",
13
+ "ssl" => true,
14
+ "cacert" => "/tmp/ca/certs/cacert.pem",
15
+ # or
16
+ #"truststore" => "/tmp/ca/truststore.jks",
17
+ #"truststore_password" => "testeteste"
18
+ }
19
+ next LogStash::Outputs::ElasticSearch.new(settings)
20
+ end
21
+
22
+ before :each do
23
+ subject.register
24
+ end
25
+
26
+ it "sends events to ES" do
27
+ expect {
28
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
29
+ subject.buffer_flush(:final => true)
30
+ }.to_not raise_error
31
+ end
32
+ end
33
+
34
+ describe "connect using HTTP Authentication", :elasticsearch_secure => true do
35
+ subject do
36
+ require "logstash/outputs/elasticsearch"
37
+ settings = {
38
+ "protocol" => "http",
39
+ "cluster" => "elasticsearch",
40
+ "host" => "node01",
41
+ "user" => "user",
42
+ "password" => "changeme",
43
+ }
44
+ next LogStash::Outputs::ElasticSearch.new(settings)
45
+ end
46
+
47
+ before :each do
48
+ subject.register
49
+ end
50
+
51
+ it "sends events to ES" do
52
+ expect {
53
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
54
+ subject.buffer_flush(:final => true)
55
+ }.to_not raise_error
56
+ end
57
+ end
58
+
59
+ describe "send messages to ElasticSearch using HTTPS", :elasticsearch_secure => true do
60
+ subject do
61
+ require "logstash/outputs/elasticsearch"
62
+ settings = {
63
+ "protocol" => "http",
64
+ "node_name" => "logstash",
65
+ "cluster" => "elasticsearch",
66
+ "host" => "node01",
67
+ "user" => "user",
68
+ "password" => "changeme",
69
+ "ssl" => true,
70
+ "cacert" => "/tmp/ca/certs/cacert.pem",
71
+ # or
72
+ #"truststore" => "/tmp/ca/truststore.jks",
73
+ #"truststore_password" => "testeteste"
74
+ }
75
+ next LogStash::Outputs::ElasticSearch.new(settings)
76
+ end
77
+
78
+ before :each do
79
+ subject.register
80
+ end
81
+
82
+ it "sends events to ES" do
83
+ expect {
84
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
85
+ subject.buffer_flush(:final => true)
86
+ }.to_not raise_error
87
+ end
88
+ end
89
+
90
+ describe "connect using HTTP Authentication", :elasticsearch_secure => true do
91
+ subject do
92
+ require "logstash/outputs/elasticsearch"
93
+ settings = {
94
+ "protocol" => "http",
95
+ "cluster" => "elasticsearch",
96
+ "host" => "node01",
97
+ "user" => "user",
98
+ "password" => "changeme",
99
+ }
100
+ next LogStash::Outputs::ElasticSearch.new(settings)
101
+ end
102
+
103
+ before :each do
104
+ subject.register
105
+ end
106
+
107
+ it "sends events to ES" do
108
+ expect {
109
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
110
+ subject.buffer_flush(:final => true)
111
+ }.to_not raise_error
112
+ end
113
+ end
@@ -0,0 +1,97 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "index template expected behavior", :integration => true do
4
+ ["transport", "http"].each do |protocol|
5
+ context "with protocol => #{protocol}" do
6
+
7
+ subject! do
8
+ require "logstash/outputs/elasticsearch"
9
+ settings = {
10
+ "manage_template" => true,
11
+ "template_overwrite" => true,
12
+ "protocol" => protocol,
13
+ "host" => "#{get_host()}",
14
+ "port" => "#{get_port(protocol)}"
15
+ }
16
+ next LogStash::Outputs::ElasticSearch.new(settings)
17
+ end
18
+
19
+ before :each do
20
+ # Delete all templates first.
21
+ require "elasticsearch"
22
+
23
+ # Clean ES of data before we start.
24
+ @es = get_client
25
+ @es.indices.delete_template(:name => "*")
26
+
27
+ # This can fail if there are no indexes, ignore failure.
28
+ @es.indices.delete(:index => "*") rescue nil
29
+
30
+ subject.register
31
+
32
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
33
+ subject.receive(LogStash::Event.new("somevalue" => 100))
34
+ subject.receive(LogStash::Event.new("somevalue" => 10))
35
+ subject.receive(LogStash::Event.new("somevalue" => 1))
36
+ subject.receive(LogStash::Event.new("country" => "us"))
37
+ subject.receive(LogStash::Event.new("country" => "at"))
38
+ subject.receive(LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] }))
39
+ subject.buffer_flush(:final => true)
40
+ @es.indices.refresh
41
+
42
+ # Wait or fail until everything's indexed.
43
+ Stud::try(20.times) do
44
+ r = @es.search
45
+ insist { r["hits"]["total"] } == 7
46
+ end
47
+ end
48
+
49
+ it "permits phrase searching on string fields" do
50
+ results = @es.search(:q => "message:\"sample message\"")
51
+ insist { results["hits"]["total"] } == 1
52
+ insist { results["hits"]["hits"][0]["_source"]["message"] } == "sample message here"
53
+ end
54
+
55
+ it "numbers dynamically map to a numeric type and permit range queries" do
56
+ results = @es.search(:q => "somevalue:[5 TO 105]")
57
+ insist { results["hits"]["total"] } == 2
58
+
59
+ values = results["hits"]["hits"].collect { |r| r["_source"]["somevalue"] }
60
+ insist { values }.include?(10)
61
+ insist { values }.include?(100)
62
+ reject { values }.include?(1)
63
+ end
64
+
65
+ it "does not create .raw field for the message field" do
66
+ results = @es.search(:q => "message.raw:\"sample message here\"")
67
+ insist { results["hits"]["total"] } == 0
68
+ end
69
+
70
+ it "creates .raw field from any string field which is not_analyzed" do
71
+ results = @es.search(:q => "country.raw:\"us\"")
72
+ insist { results["hits"]["total"] } == 1
73
+ insist { results["hits"]["hits"][0]["_source"]["country"] } == "us"
74
+
75
+ # partial or terms should not work.
76
+ results = @es.search(:q => "country.raw:\"u\"")
77
+ insist { results["hits"]["total"] } == 0
78
+ end
79
+
80
+ it "make [geoip][location] a geo_point" do
81
+ results = @es.search(:body => { "filter" => { "geo_distance" => { "distance" => "1000km", "geoip.location" => { "lat" => 0.5, "lon" => 0.5 } } } })
82
+ insist { results["hits"]["total"] } == 1
83
+ insist { results["hits"]["hits"][0]["_source"]["geoip"]["location"] } == [ 0.0, 0.0 ]
84
+ end
85
+
86
+ it "should index stopwords like 'at' " do
87
+ results = @es.search(:body => { "facets" => { "t" => { "terms" => { "field" => "country" } } } })["facets"]["t"]
88
+ terms = results["terms"].collect { |t| t["term"] }
89
+
90
+ insist { terms }.include?("us")
91
+
92
+ # 'at' is a stopword, make sure stopwords are not ignored.
93
+ insist { terms }.include?("at")
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,94 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "transport client create actions", :integration => true do
4
+ require "logstash/outputs/elasticsearch"
5
+ require "elasticsearch"
6
+
7
+ def get_es_output(action, id = nil)
8
+ settings = {
9
+ "manage_template" => true,
10
+ "index" => "logstash-create",
11
+ "template_overwrite" => true,
12
+ "protocol" => "transport",
13
+ "host" => get_host(),
14
+ "port" => get_port('transport'),
15
+ "action" => action
16
+ }
17
+ settings['document_id'] = id unless id.nil?
18
+ LogStash::Outputs::ElasticSearch.new(settings)
19
+ end
20
+
21
+ before :each do
22
+ @es = get_client
23
+ # Delete all templates first.
24
+ # Clean ES of data before we start.
25
+ @es.indices.delete_template(:name => "*")
26
+ # This can fail if there are no indexes, ignore failure.
27
+ @es.indices.delete(:index => "*") rescue nil
28
+ end
29
+
30
+ context "when action => create" do
31
+ it "should create new documents with or without id" do
32
+ subject = get_es_output("create", "id123")
33
+ subject.register
34
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
35
+ subject.buffer_flush(:final => true)
36
+ @es.indices.refresh
37
+ # Wait or fail until everything's indexed.
38
+ Stud::try(3.times) do
39
+ r = @es.search
40
+ insist { r["hits"]["total"] } == 1
41
+ end
42
+ end
43
+
44
+ it "should create new documents without id" do
45
+ subject = get_es_output("create")
46
+ subject.register
47
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
48
+ subject.buffer_flush(:final => true)
49
+ @es.indices.refresh
50
+ # Wait or fail until everything's indexed.
51
+ Stud::try(3.times) do
52
+ r = @es.search
53
+ insist { r["hits"]["total"] } == 1
54
+ end
55
+ end
56
+ end
57
+
58
+ context "when action => create_unless_exists" do
59
+ it "should create new documents when specific id is specified" do
60
+ subject = get_es_output("create_unless_exists", "id123")
61
+ subject.register
62
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
63
+ subject.buffer_flush(:final => true)
64
+ @es.indices.refresh
65
+ # Wait or fail until everything's indexed.
66
+ Stud::try(3.times) do
67
+ r = @es.search
68
+ insist { r["hits"]["total"] } == 1
69
+ end
70
+ end
71
+
72
+ it "should fail to create a document when no id is specified" do
73
+ event = LogStash::Event.new("somevalue" => 100, "@timestamp" => "2014-11-17T20:37:17.223Z", "@metadata" => {"retry_count" => 0})
74
+ action = ["create_unless_exists", {:_id=>nil, :_index=>"logstash-2014.11.17", :_type=>"logs"}, event]
75
+ subject = get_es_output(action[0])
76
+ subject.register
77
+ expect { subject.flush([action]) }.to raise_error
78
+ end
79
+
80
+ it "should unsuccesfully submit two records with the same document id" do
81
+ subject = get_es_output("create_unless_exists", "id123")
82
+ subject.register
83
+ subject.receive(LogStash::Event.new("message" => "sample message here"))
84
+ subject.receive(LogStash::Event.new("message" => "sample message here")) # 400 status failure (same id)
85
+ subject.buffer_flush(:final => true)
86
+ @es.indices.refresh
87
+ # Wait or fail until everything's indexed.
88
+ Stud::try(3.times) do
89
+ r = @es.search
90
+ insist { r["hits"]["total"] } == 1
91
+ end
92
+ end
93
+ end
94
+ end
@@ -49,4 +49,3 @@ describe LogStash::Outputs::Elasticsearch::Protocols::HTTPClient do
49
49
  end
50
50
  end
51
51
  end
52
-
@@ -0,0 +1,157 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "outputs/elasticsearch" do
4
+ context "registration" do
5
+ it "should register" do
6
+ output = LogStash::Plugin.lookup("output", "elasticsearch").new("embedded" => "false", "protocol" => "transport", "manage_template" => "false")
7
+ # register will try to load jars and raise if it cannot find jars
8
+ expect {output.register}.to_not raise_error
9
+ end
10
+
11
+ it "should fail to register when protocol => http, action => create_unless_exists" do
12
+ output = LogStash::Plugin.lookup("output", "elasticsearch").new("protocol" => "http", "action" => "create_unless_exists")
13
+ expect {output.register}.to raise_error
14
+ end
15
+ end
16
+
17
+ describe "Authentication option" do
18
+ ["node", "transport"].each do |protocol|
19
+ context "with protocol => #{protocol}" do
20
+ subject do
21
+ require "logstash/outputs/elasticsearch"
22
+ settings = {
23
+ "protocol" => protocol,
24
+ "node_name" => "logstash",
25
+ "cluster" => "elasticsearch",
26
+ "host" => "node01",
27
+ "user" => "test",
28
+ "password" => "test"
29
+ }
30
+ next LogStash::Outputs::ElasticSearch.new(settings)
31
+ end
32
+
33
+ it "should fail in register" do
34
+ expect {subject.register}.to raise_error
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "http client create" do
41
+ require "logstash/outputs/elasticsearch"
42
+ require "elasticsearch"
43
+
44
+ let(:options) {
45
+ {
46
+ "protocol" => "http",
47
+ "index" => "my-index",
48
+ "host" => "localhost",
49
+ "path" => "some-path"
50
+ }
51
+ }
52
+
53
+ let(:eso) {LogStash::Outputs::ElasticSearch.new(options)}
54
+
55
+ let(:manticore_host) {
56
+ eso.client.first.send(:client).transport.options[:host].first
57
+ }
58
+
59
+ around(:each) do |block|
60
+ thread = eso.register
61
+ block.call()
62
+ thread.kill()
63
+ end
64
+
65
+ describe "with path" do
66
+ it "should properly create a URI with the path" do
67
+ expect(eso.path).to eql(options["path"])
68
+ end
69
+
70
+
71
+ it "should properly set the path on the HTTP client adding slashes" do
72
+ expect(manticore_host).to include("/" + options["path"] + "/")
73
+ end
74
+
75
+ context "with extra slashes" do
76
+ let(:path) { "/slashed-path/ "}
77
+ let(:eso) {
78
+ LogStash::Outputs::ElasticSearch.new(options.merge("path" => "/some-path/"))
79
+ }
80
+
81
+ it "should properly set the path on the HTTP client without adding slashes" do
82
+ expect(manticore_host).to include(options["path"])
83
+ end
84
+ end
85
+
86
+
87
+ end
88
+ end
89
+
90
+ describe "transport protocol" do
91
+ context "host not configured" do
92
+ subject do
93
+ require "logstash/outputs/elasticsearch"
94
+ settings = {
95
+ "protocol" => "transport",
96
+ "node_name" => "mynode"
97
+ }
98
+ next LogStash::Outputs::ElasticSearch.new(settings)
99
+ end
100
+
101
+ it "should set host to localhost" do
102
+ expect(LogStash::Outputs::Elasticsearch::Protocols::TransportClient).to receive(:new).with({
103
+ :host => "localhost",
104
+ :port => "9300-9305",
105
+ :protocol => "transport",
106
+ :client_settings => {
107
+ "client.transport.sniff" => false,
108
+ "node.name" => "mynode"
109
+ }
110
+ })
111
+ subject.register
112
+ end
113
+ end
114
+
115
+ context "sniffing => true" do
116
+ subject do
117
+ require "logstash/outputs/elasticsearch"
118
+ settings = {
119
+ "host" => "node01",
120
+ "protocol" => "transport",
121
+ "sniffing" => true
122
+ }
123
+ next LogStash::Outputs::ElasticSearch.new(settings)
124
+ end
125
+
126
+ it "should set the sniffing property to true" do
127
+ expect_any_instance_of(LogStash::Outputs::Elasticsearch::Protocols::TransportClient).to receive(:client).and_return(nil)
128
+ subject.register
129
+ client = subject.instance_eval("@current_client")
130
+ settings = client.instance_eval("@settings")
131
+
132
+ expect(settings.build.getAsMap["client.transport.sniff"]).to eq("true")
133
+ end
134
+ end
135
+
136
+ context "sniffing => false" do
137
+ subject do
138
+ require "logstash/outputs/elasticsearch"
139
+ settings = {
140
+ "host" => "node01",
141
+ "protocol" => "transport",
142
+ "sniffing" => false
143
+ }
144
+ next LogStash::Outputs::ElasticSearch.new(settings)
145
+ end
146
+
147
+ it "should set the sniffing property to true" do
148
+ expect_any_instance_of(LogStash::Outputs::Elasticsearch::Protocols::TransportClient).to receive(:client).and_return(nil)
149
+ subject.register
150
+ client = subject.instance_eval("@current_client")
151
+ settings = client.instance_eval("@settings")
152
+
153
+ expect(settings.build.getAsMap["client.transport.sniff"]).to eq("false")
154
+ end
155
+ end
156
+ end
157
+ end