logstash-output-elasticsearch 0.2.8-java → 0.2.9-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.
@@ -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