logstash-output-sumologic 1.1.4 → 1.1.9

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,189 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "logstash/outputs/sumologic"
4
+
5
+ describe LogStash::Outputs::SumoLogic::Piler do
6
+
7
+ before :each do
8
+ piler.start()
9
+ end
10
+
11
+ after :each do
12
+ queue.drain()
13
+ piler.stop()
14
+ end
15
+
16
+ context "working in pile mode if interval > 0 && pile_max > 0" do
17
+ let(:config) { {"queue_max" => 10, "interval" => 10, "pile_max" => 100 } }
18
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
19
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, config) }
20
+ let(:piler) { LogStash::Outputs::SumoLogic::Piler.new(queue, stats, config) }
21
+ specify {
22
+ expect(piler.is_pile).to be true
23
+ }
24
+ end # context
25
+
26
+ context "working in non-pile mode if interval <= 0" do
27
+ let(:config) { {"queue_max" => 10, "interval" => 0, "pile_max" => 100 } }
28
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
29
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, config) }
30
+ let(:piler) { LogStash::Outputs::SumoLogic::Piler.new(queue, stats, config) }
31
+ specify {
32
+ expect(piler.is_pile).to be false
33
+ }
34
+ end # context
35
+
36
+ context "working in non-pile mode if pile_max <= 0" do
37
+ let(:config) { {"queue_max" => 10, "interval" => 10, "pile_max" => 0 } }
38
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
39
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, config) }
40
+ let(:piler) { LogStash::Outputs::SumoLogic::Piler.new(queue, stats, config) }
41
+ specify {
42
+ expect(piler.is_pile).to be false
43
+ }
44
+ end # context
45
+
46
+ context "in non-pile mode" do
47
+
48
+ let(:config) { {"queue_max" => 10, "interval" => 0, "pile_max" => 100 } }
49
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
50
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, config) }
51
+ let(:piler) { LogStash::Outputs::SumoLogic::Piler.new(queue, stats, config) }
52
+
53
+ it "enque immediately after input" do
54
+ expect(stats.current_pile_items.value).to be 0
55
+ expect(stats.current_queue_items.value).to be 0
56
+ piler.input("This is a log line")
57
+ expect(stats.current_pile_items.value).to be 0
58
+ expect(stats.current_queue_items.value).to be 1
59
+ expect(stats.current_queue_bytes.value).to be 18
60
+ end
61
+
62
+ it "deque correctly" do
63
+ expect(stats.current_queue_items.value).to be 0
64
+ expect(stats.total_enque_times.value).to be 0
65
+ piler.input("This is a log line")
66
+ expect(stats.total_enque_times.value).to be 1
67
+ expect(stats.current_queue_items.value).to be 1
68
+ expect(stats.current_queue_bytes.value).to be 18
69
+ expect(stats.total_deque_times.value).to be 0
70
+ expect(queue.deq()).to eq "This is a log line"
71
+ expect(stats.current_queue_items.value).to be 0
72
+ expect(stats.current_queue_bytes.value).to be 0
73
+ expect(stats.total_deque_times.value).to be 1
74
+ end
75
+
76
+ end # context
77
+
78
+ context "in pile mode" do
79
+
80
+ let(:config) { {"queue_max" => 10, "interval" => 5, "pile_max" => 25 } }
81
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
82
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, config) }
83
+ let(:piler) { LogStash::Outputs::SumoLogic::Piler.new(queue, stats, config) }
84
+
85
+ it "wait in pile before size reach pile_max" do
86
+ expect(stats.current_pile_items.value).to be 0
87
+ expect(stats.current_pile_bytes.value).to be 0
88
+ expect(stats.current_queue_items.value).to be 0
89
+ piler.input("1234567890")
90
+ expect(stats.current_pile_items.value).to be 1
91
+ expect(stats.current_pile_bytes.value).to be 10
92
+ expect(stats.current_queue_items.value).to be 0
93
+ piler.input("1234567890")
94
+ expect(stats.current_pile_items.value).to be 2
95
+ expect(stats.current_pile_bytes.value).to be 20
96
+ expect(stats.current_queue_items.value).to be 0
97
+ end
98
+
99
+ it "enqueue content from pile when reach pile_max" do
100
+ expect(stats.current_pile_items.value).to be 0
101
+ expect(stats.current_pile_bytes.value).to be 0
102
+ expect(stats.current_queue_items.value).to be 0
103
+ piler.input("1234567890")
104
+ piler.input("1234567890")
105
+ expect(stats.current_queue_items.value).to be 0
106
+ piler.input("1234567890")
107
+ expect(stats.current_pile_items.value).to be 1
108
+ expect(stats.current_pile_bytes.value).to be 10
109
+ expect(stats.current_queue_items.value).to be 1
110
+ expect(stats.current_queue_bytes.value).to be 21
111
+ end
112
+
113
+ it "enqueue content from pile when reach interval" do
114
+ expect(stats.current_pile_items.value).to be 0
115
+ expect(stats.current_pile_bytes.value).to be 0
116
+ piler.input("1234567890")
117
+ piler.input("1234567890")
118
+ expect(stats.current_queue_items.value).to be 0
119
+ sleep(8)
120
+ expect(stats.current_pile_items.value).to be 0
121
+ expect(stats.current_pile_bytes.value).to be 0
122
+ expect(stats.current_queue_items.value).to be 1
123
+ expect(stats.current_queue_bytes.value).to be 21
124
+ end
125
+
126
+ end # context
127
+
128
+ context "pile to message queue" do
129
+
130
+ let(:config) { {"queue_max" => 5, "interval" => 500, "pile_max" => 5} }
131
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
132
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, config) }
133
+ let(:piler) { LogStash::Outputs::SumoLogic::Piler.new(queue, stats, config) }
134
+
135
+ it "enqueue payloads from pile before reach queue_max" do
136
+ expect(stats.current_queue_items.value).to be 0
137
+ piler.input("1234567890")
138
+ expect(stats.current_queue_items.value).to be 0
139
+ expect(stats.current_queue_bytes.value).to be 0
140
+ piler.input("2234567890")
141
+ expect(stats.current_queue_items.value).to be 1
142
+ expect(stats.current_queue_bytes.value).to be 10
143
+ piler.input("3234567890")
144
+ expect(stats.current_queue_items.value).to be 2
145
+ expect(stats.current_queue_bytes.value).to be 20
146
+ end
147
+
148
+ it "block input thread if queue is full" do
149
+ input_t = Thread.new {
150
+ for i in 0..9 do
151
+ piler.input("#{i}234567890")
152
+ end
153
+ }
154
+ sleep(3)
155
+ expect(stats.current_queue_items.value).to be 5
156
+ expect(stats.current_queue_bytes.value).to be 50
157
+ queue.drain()
158
+ piler.stop()
159
+ input_t.join
160
+ expect(stats.total_deque_times.value).to be 5
161
+ expect(stats.total_deque_bytes.value).to be 50
162
+ end
163
+
164
+ it "resume input thread if queue is drained" do
165
+ input_t = Thread.new {
166
+ for i in 0..9 do
167
+ piler.input("#{i}234567890")
168
+ end
169
+ }
170
+ sleep(3)
171
+ expect(stats.total_deque_times.value).to be 0
172
+ expect(stats.total_enque_times.value).to be 5
173
+ queue.deq()
174
+ sleep(1)
175
+ expect(stats.total_deque_times.value).to be 1
176
+ expect(stats.total_enque_times.value).to be 6
177
+ queue.deq()
178
+ sleep(1)
179
+ expect(stats.total_deque_times.value).to be 2
180
+ expect(stats.total_enque_times.value).to be 7
181
+ queue.drain()
182
+ piler.stop()
183
+ input_t.join
184
+ end
185
+
186
+ end # context
187
+
188
+ end # describe
189
+
@@ -0,0 +1,188 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
3
+ require "rspec/eventually"
4
+ require "logstash/outputs/sumologic"
5
+
6
+ require_relative "../../test_server.rb"
7
+
8
+ describe LogStash::Outputs::SumoLogic::Sender do
9
+
10
+ before :all do
11
+ @@server = TestServer.new()
12
+ @@server.start()
13
+ end
14
+
15
+ before :each do
16
+ @@server.response = TestServer::RESPONSE_200
17
+ @@server.drain()
18
+ end
19
+
20
+ after :all do
21
+ @@server.stop()
22
+ end
23
+
24
+ context "connect()" do
25
+ let(:stats) { LogStash::Outputs::SumoLogic::Statistics.new() }
26
+ let(:queue) { LogStash::Outputs::SumoLogic::MessageQueue.new(stats, "queue_max" => 10) }
27
+ let(:sender) { LogStash::Outputs::SumoLogic::Sender.new(false, queue, stats, "url" => "http://localhost:#{TestServer::PORT}") }
28
+
29
+ it "should return true if sever response 200" do
30
+ expect(sender.connect()).to be true
31
+ result = @@server.drain()
32
+ expect(result.size).to eq(1)
33
+ end
34
+
35
+ it "should return false if sever response 429" do
36
+ @@server.response = TestServer::RESPONSE_429
37
+ expect(sender.connect()).to be false
38
+ result = @@server.drain()
39
+ expect(result.size).to eq(1)
40
+ end
41
+
42
+ it "should return false if sever cannot reach" do
43
+ sender = LogStash::Outputs::SumoLogic::Sender.new(false, queue, stats, "url" => "http://localhost:#{TestServer::PORT + 1}")
44
+ expect(sender.connect()).to be false
45
+ result = @@server.drain()
46
+ expect(result.size).to eq(0)
47
+ end
48
+
49
+ end # context
50
+
51
+ context "single sender" do
52
+ let(:plugin) { LogStash::Outputs::SumoLogic.new("url" => "http://localhost:#{TestServer::PORT}", "sender_max" => 1, "sleep_before_requeue" => 1, "request_timeout" => 3) }
53
+ let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
54
+
55
+ it "should send message correctly" do
56
+ plugin.register
57
+ plugin.receive(event)
58
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(1)).pause_for(1)
59
+ expect { plugin.stats.total_response("200") }.to eventually(eq(1)).pause_for(1)
60
+ result = @@server.drain()
61
+ expect(result.size).to eq(2)
62
+ plugin.receive(event)
63
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(2)).pause_for(1)
64
+ expect { plugin.stats.total_response("200") }.to eventually(eq(2)).pause_for(1)
65
+ result = @@server.drain()
66
+ expect(result.size).to eq(1)
67
+ end
68
+
69
+ it "should re-enque the message if got 429" do
70
+ plugin.register
71
+ plugin.receive(event)
72
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(1)).pause_for(1)
73
+ expect { plugin.stats.total_response("200") }.to eventually(eq(1)).pause_for(1)
74
+ result = @@server.drain()
75
+ expect(result.size).to eq(2)
76
+ @@server.response = TestServer::RESPONSE_429
77
+ plugin.receive(event)
78
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 1).within(10).pause_for(1)
79
+ expect { plugin.stats.total_response("429") }.to eventually(be > 1).within(10).pause_for(1)
80
+ result = @@server.drain()
81
+ expect(result.size).to be > 0
82
+ @@server.response = TestServer::RESPONSE_200
83
+ expect { plugin.stats.total_response("200") }.to eventually(be > 1).within(10).pause_for(1)
84
+ result = @@server.drain()
85
+ expect(result.size).to be > 0
86
+ end
87
+
88
+ it "should re-enque the message if network failed" do
89
+ plugin.register
90
+ plugin.receive(event)
91
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(1)).pause_for(1)
92
+ expect { plugin.stats.total_response("200") }.to eventually(eq(1)).pause_for(1)
93
+ result = @@server.drain()
94
+ expect(result.size).to eq(2)
95
+ @@server.stop()
96
+ plugin.receive(event)
97
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 1).within(10).pause_for(1)
98
+ expect { plugin.stats.total_response("failure") }.to eventually(be > 1).within(25).pause_for(1)
99
+ result = @@server.drain()
100
+ @@server.start()
101
+ @@server.response = TestServer::RESPONSE_200
102
+ expect { plugin.stats.total_response("200") }.to eventually(be > 1).within(10).pause_for(1)
103
+ result = @@server.drain()
104
+ expect(result.size).to be > 0
105
+ end
106
+
107
+ end # context
108
+
109
+ context "multiple senders" do
110
+ let(:plugin) { LogStash::Outputs::SumoLogic.new("url" => "http://localhost:#{TestServer::PORT}", "sender_max" => 10, "sleep_before_requeue" => 1, "request_timeout" => 3) }
111
+ let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
112
+
113
+ it "should send message correctly" do
114
+ plugin.register
115
+ plugin.receive(event)
116
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(1)).pause_for(1)
117
+ expect { plugin.stats.total_response("200") }.to eventually(eq(1)).pause_for(1)
118
+ result = @@server.drain()
119
+ expect(result.size).to eq(2)
120
+ plugin.receive(event)
121
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(2)).pause_for(1)
122
+ expect { plugin.stats.total_response("200") }.to eventually(eq(2)).pause_for(1)
123
+ result = @@server.drain()
124
+ expect(result.size).to eq(1)
125
+ end
126
+
127
+ it "should re-enque the message if got 429" do
128
+ plugin.register
129
+ plugin.receive(event)
130
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(1)).pause_for(1)
131
+ expect { plugin.stats.total_response("200") }.to eventually(eq(1)).pause_for(1)
132
+ result = @@server.drain()
133
+ expect(result.size).to eq(2)
134
+ @@server.response = TestServer::RESPONSE_429
135
+ plugin.receive(event)
136
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 1).within(10).pause_for(1)
137
+ expect { plugin.stats.total_response("429") }.to eventually(be > 1).within(10).pause_for(1)
138
+ result = @@server.drain()
139
+ expect(result.size).to be > 0
140
+ @@server.response = TestServer::RESPONSE_200
141
+ expect { plugin.stats.total_response("200") }.to eventually(be > 1).within(10).pause_for(1)
142
+ result = @@server.drain()
143
+ expect(result.size).to be > 0
144
+ end
145
+
146
+ it "should re-enque the message if network failed" do
147
+ plugin.register
148
+ plugin.receive(event)
149
+ expect { plugin.stats.total_output_requests.value }.to eventually(eq(1)).pause_for(1)
150
+ expect { plugin.stats.total_response("200") }.to eventually(eq(1)).pause_for(1)
151
+ result = @@server.drain()
152
+ expect(result.size).to eq(2)
153
+ @@server.stop()
154
+ plugin.receive(event)
155
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 1).within(10).pause_for(1)
156
+ expect { plugin.stats.total_response("failure") }.to eventually(be > 1).within(25).pause_for(1)
157
+ result = @@server.drain()
158
+ @@server.start()
159
+ @@server.response = TestServer::RESPONSE_200
160
+ expect { plugin.stats.total_response("200") }.to eventually(be > 1).within(10).pause_for(1)
161
+ result = @@server.drain()
162
+ expect(result.size).to be > 0
163
+ end
164
+
165
+ it "should reuse tokens" do
166
+ plugin.register
167
+ 30.times { plugin.receive(event) }
168
+ expect { plugin.stats.total_response("200") }.to eventually(eq 30).within(100).pause_for(1)
169
+ end
170
+
171
+ end # context
172
+
173
+ context "close()" do
174
+
175
+ let(:plugin) { LogStash::Outputs::SumoLogic.new("url" => "http://localhost:#{TestServer::PORT}", "sender_max" => 10) }
176
+ let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
177
+
178
+ it "should drain out messages" do
179
+ plugin.register
180
+ 30.times { plugin.receive(event) }
181
+ plugin.close
182
+ expect(plugin.stats.total_response("200")).to eq 30
183
+ end
184
+
185
+ end # context
186
+
187
+ end # describe
188
+
@@ -1,406 +1,230 @@
1
-
2
1
  # encoding: utf-8
3
2
  require "logstash/devutils/rspec/spec_helper"
3
+ require "rspec/eventually"
4
4
  require "logstash/outputs/sumologic"
5
- require "logstash/event"
6
-
7
- require_relative '../spec_helper'
8
5
 
9
- describe LogStash::Outputs::SumoLogic do
6
+ describe LogStash::Outputs::SumoLogic, :unless => (ENV["sumo_url"].to_s.empty?) do
10
7
 
11
- let(:server) { subject.server }
12
-
13
8
  before :each do
14
- subject.register
15
- subject.receive(event)
16
- end
17
-
18
- # For log
19
- context "log sent in default format" do
20
-
21
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234") }
22
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
23
-
24
- it "generate one element" do
25
- expect(server.size).to eq(1)
26
- end
27
-
28
- it "include all content" do
29
- expect(server.pop).to include("myHost Hello world")
30
- end
31
-
32
- end
33
-
34
- context "log sent as @json" do
35
-
36
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "format" => "%{@json}") }
37
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
38
-
39
- it "generate one element" do
40
- expect(server.size).to eq(1)
41
- end
42
-
43
- it "include all content" do
44
- received = server.pop
45
- expect(received).to include("\"host\":\"myHost\"")
46
- expect(received).to include("\"message\":\"Hello world\"")
47
- end
48
-
49
- end
50
-
51
- context "log sent in customized format" do
52
-
53
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "format" => "%{foo} %{bar}" ) }
54
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
55
-
56
- it "generate one element" do
57
- expect(server.size).to eq(1)
58
- end
59
-
60
- it "include all content" do
61
- expect(server.pop).to eq("fancy 24")
62
- end
63
-
64
- end
65
-
66
- context "log sent with customized json_mapping" do
67
-
68
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
69
- "format" => "%{host} %{@json}",
70
- "json_mapping" => { "foo" => "%{foo}", "bar" => "%{bar}", "%{foo}" => "%{bar}" } ) }
71
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
72
-
73
- it "generate one element" do
74
- expect(server.size).to eq(1)
75
- end
76
-
77
- it "include all content" do
78
- expect(server.pop).to eq("myHost {\"foo\":\"fancy\",\"bar\":\"24\",\"fancy\":\"24\"}")
79
- end
80
-
81
- end
82
-
83
- # For headers
84
- context "check default headers" do
85
-
86
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234") }
87
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
88
-
89
- it "check header" do
90
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain"})
91
- end
92
-
93
- end
94
-
95
- context "override source_category" do
96
-
97
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "source_category" => "my source category") }
98
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
99
-
100
- it "check header" do
101
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip,
102
- "X-Sumo-Client"=>"logstash-output-sumologic",
103
- "Content-Type"=>"text/plain",
104
- "X-Sumo-Category"=>"my source category"})
105
- end
106
-
107
- end
108
-
109
- context "override source_name" do
110
-
111
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "source_name" => "my source name") }
112
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
113
-
114
- it "check header" do
115
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip,
116
- "X-Sumo-Client"=>"logstash-output-sumologic",
117
- "Content-Type"=>"text/plain",
118
- "X-Sumo-Name"=>"my source name"})
119
- end
120
-
121
- end
122
-
123
- context "override source_host" do
124
-
125
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "source_host" => "my source host") }
126
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
127
-
128
- it "check header" do
129
- expect(server.header).to eq({"X-Sumo-Host"=>"my source host", "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain"})
130
- end
131
-
132
- end
133
-
134
- context "with extra_headers" do
135
-
136
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "extra_headers" => {"foo" => "bar"}) }
137
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
138
-
139
- it "check header" do
140
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain", "foo"=>"bar"})
141
- end
142
-
143
- end
144
-
145
- context "with compress" do
146
-
147
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "compress" => true) }
148
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
149
-
150
- it "check header" do
151
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip,
152
- "X-Sumo-Client"=>"logstash-output-sumologic",
153
- "Content-Type"=>"text/plain",
154
- "Content-Encoding"=>"deflate"})
155
- end
156
-
157
- end
158
-
159
- context "with gzip" do
160
-
161
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "compress" => true, "compress_encoding"=>"gzip") }
162
- let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
163
-
164
- it "check header" do
165
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip,
166
- "X-Sumo-Client"=>"logstash-output-sumologic",
167
- "Content-Type"=>"text/plain",
168
- "Content-Encoding"=>"gzip"})
169
- end
170
-
171
- end
172
-
173
- # For metrics
174
- context "with metrics sent in graphite" do
175
-
176
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
177
- "metrics" => { "hurray.%{foo}" => "%{bar}"},
178
- "metrics_format" => "graphite") }
179
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
180
-
181
- it "generate one element" do
182
- expect(server.size).to eq(1)
183
- end
184
-
185
- it "check header" do
186
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip,
187
- "X-Sumo-Client"=>"logstash-output-sumologic",
188
- "Content-Type"=>"application/vnd.sumologic.graphite"})
189
- end
190
-
191
- it "include all content" do
192
- expect(server.pop).to match(/^hurray.fancy 24 \d{10,}$/)
193
- end
194
-
195
- end
196
-
197
- context "with metrics sent in carbon2" do
198
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "hurray.%{foo}" => "%{bar}" }) }
199
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
200
-
201
- it "generate one element" do
202
- expect(server.size).to eq(1)
203
- end
204
-
205
- it "check header" do
206
- expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip,
207
- "X-Sumo-Client"=>"logstash-output-sumologic",
208
- "Content-Type"=>"application/vnd.sumologic.carbon2"})
209
- end
210
-
211
- it "include all content" do
212
- expect(server.pop).to match(/^metric=hurray.fancy 24 \d{10,}$/)
213
- end
214
- end
215
-
216
- context "with metrics_name override" do
217
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
218
- "metrics" => { "hurray.%{foo}" => "%{bar}" },
219
- "metrics_name" => "mynamespace.*") }
220
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
221
-
222
- it "include all content" do
223
- expect(server.pop).to match(/^metric=mynamespace.hurray.fancy 24 \d{10,}$/)
224
- end
225
- end
226
-
227
- context "with intrinsic_tags override" do
228
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
229
- "metrics" => { "bar" => "%{bar}" },
230
- "intrinsic_tags" => {"host"=>"%{host}"}) }
231
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
232
-
233
- it "include all content" do
234
- expect(server.pop).to match(/^host=myHost metric=bar 24 \d{10,}$/)
235
- end
236
- end
237
-
238
- context "with meta_tags override" do
239
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
240
- "metrics" => { "bar" => "%{bar}" },
241
- "intrinsic_tags" => {"host"=>"%{host}"},
242
- "meta_tags" => {"foo" => "%{foo}"}) }
243
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
244
-
245
- it "include all content" do
246
- expect(server.pop).to match(/^host=myHost metric=bar foo=fancy 24 \d{10,}$/)
247
- end
248
- end
249
-
250
- context "with multiple metrics mapping" do
251
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
252
- "metrics" => { "cpu1" => "%{cpu1}", "cpu2" => "%{cpu2}" },
253
- "intrinsic_tags" => {"host"=>"%{host}"},
254
- "meta_tags" => {"foo" => "%{foo}"}) }
255
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "cpu1" => 0.24, "cpu2" => 0.11) }
256
-
257
- it "include content" do
258
- sorted = server.all_sorted
259
- expect(sorted.pop).to match(/^host=myHost metric=cpu1 foo=fancy 0\.24 \d{10,}$/)
260
- expect(sorted.pop).to match(/^host=myHost metric=cpu2 foo=fancy 0\.11 \d{10,}$/)
261
- end
262
- end
263
-
264
- context "metrics with non-number value should be dropped (carbon2)" do
265
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
266
- "metrics" => { "cpu1" => "%{cpu1}", "cpu2" => "%{cpu2}", "cpu3" => "%{cpu3}" },
267
- "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}) }
268
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "cpu1" => 0.24, "cpu2" => "abc", "cpu3" => 0.11) }
269
-
270
- it "include content" do
271
- sorted = server.all_sorted
272
- expect(sorted.pop).to match(/^host=myHost metric=cpu1 foo=fancy 0\.24 \d{10,}$/)
273
- expect(sorted.pop).to match(/^host=myHost metric=cpu3 foo=fancy 0\.11 \d{10,}$/)
274
- expect(sorted.empty?).to eq(true)
275
- end
276
- end
277
-
278
- context "metrics with non-number value should be dropped (graphite)" do
279
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
280
- "metrics" => { "cpu1" => "%{cpu1}", "cpu2" => "%{cpu2}", "cpu3" => "%{cpu3}" },
281
- "metrics_format" => "graphite") }
282
- let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "cpu1" => 0.24, "cpu2" => "abc", "cpu3" => 0.11) }
283
-
284
- it "include content" do
285
- sorted = server.all_sorted
286
- expect(sorted.pop).to match(/^cpu1 0\.24 \d{10,}$/)
287
- expect(sorted.pop).to match(/^cpu3 0\.11 \d{10,}$/)
288
- expect(sorted.empty?).to eq(true)
289
- end
290
- end
291
-
292
- context "fields_as_metrics (carbon2)" do
293
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
294
- "fields_as_metrics" => true,
295
- "intrinsic_tags" => {"host"=>"%{host}"},
296
- "meta_tags" => {"foo" => "%{foo}"}) }
297
- let(:event) { LogStash::Event.new(
298
- "host" => "myHost",
299
- "foo" => "fancy",
300
- "cpu" => [0.24, 0.11, 0.75, 0.28],
301
- "storageRW" => 51,
302
- "bar" => "blahblah",
303
- "blkio" => {
304
- "write_ps" => 5,
305
- "read_ps" => 2,
306
- "total_ps" => 0
307
- })}
308
-
309
- it "include content" do
310
- sorted = server.all_sorted
311
- expect(sorted.pop).to match(/^host=myHost metric=blkio\.read_ps foo=fancy 2 \d{10,}$/)
312
- expect(sorted.pop).to match(/^host=myHost metric=blkio\.total_ps foo=fancy 0 \d{10,}$/)
313
- expect(sorted.pop).to match(/^host=myHost metric=blkio\.write_ps foo=fancy 5 \d{10,}$/)
314
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.0 foo=fancy 0\.24 \d{10,}$/)
315
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.1 foo=fancy 0\.11 \d{10,}$/)
316
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.2 foo=fancy 0\.75 \d{10,}$/)
317
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.3 foo=fancy 0\.28 \d{10,}$/)
318
- expect(sorted.pop).to match(/^host=myHost metric=storageRW foo=fancy 51 \d{10,}$/)
319
- expect(sorted.empty?).to eq(true)
320
- end
321
- end
322
-
323
- context "fields_as_metrics (graphite)" do
324
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "fields_as_metrics" => true, "metrics_format" => "graphite") }
325
- let(:event) { LogStash::Event.new(
326
- "host" => "myHost",
327
- "foo" => "fancy",
328
- "cpu" => [0.24, 0.11, 0.75, 0.28],
329
- "storageRW" => 51,
330
- "bar" => "blahblah",
331
- "blkio" => {
332
- "write_ps" => 0,
333
- "read_ps" => 0,
334
- "total_ps" => 0
335
- })}
336
-
337
- it "include content" do
338
- sorted = server.all_sorted
339
- expect(sorted.pop).to match(/^blkio\.read_ps 0 \d{10,}$/)
340
- expect(sorted.pop).to match(/^blkio\.total_ps 0 \d{10,}$/)
341
- expect(sorted.pop).to match(/^blkio\.write_ps 0 \d{10,}$/)
342
- expect(sorted.pop).to match(/^cpu\.0 0\.24 \d{10,}$/)
343
- expect(sorted.pop).to match(/^cpu\.1 0\.11 \d{10,}$/)
344
- expect(sorted.pop).to match(/^cpu\.2 0\.75 \d{10,}$/)
345
- expect(sorted.pop).to match(/^cpu\.3 0\.28 \d{10,}$/)
346
- expect(sorted.pop).to match(/^storageRW 51 \d{10,}$/)
347
- end
348
- end
349
-
350
- context "fields_include is honored when fields_as_metrics (carbon2)" do
351
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
352
- "fields_as_metrics" => true,
353
- "intrinsic_tags" => {"host"=>"%{host}"},
354
- "meta_tags" => {"foo" => "%{foo}"},
355
- "fields_include" => ["cpu*"]) }
356
- let(:event) { LogStash::Event.new(
357
- "host" => "myHost",
358
- "foo" => "fancy",
359
- "cpu" => [0.24, 0.11, 0.75, 0.28],
360
- "storageRW" => 51,
361
- "bar" => "blahblah",
362
- "blkio" => {
363
- "write_ps" => 5,
364
- "read_ps" => 2,
365
- "total_ps" => 0
366
- })}
367
-
368
- it "include content" do
369
- sorted = server.all_sorted
370
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.0 foo=fancy 0\.24 \d{10,}$/)
371
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.1 foo=fancy 0\.11 \d{10,}$/)
372
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.2 foo=fancy 0\.75 \d{10,}$/)
373
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.3 foo=fancy 0\.28 \d{10,}$/)
374
- expect(sorted.empty?).to eq(true)
375
- end
376
- end
377
-
378
- context "fields_exclude is honored when fields_as_metrics (carbon2)" do
379
- subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234",
380
- "fields_as_metrics" => true,
381
- "intrinsic_tags" => {"host"=>"%{host}"},
382
- "meta_tags" => {"foo" => "%{foo}"},
383
- "fields_include" => ["cpu*"],
384
- "fields_exclude" => [".*1"]) }
385
- let(:event) { LogStash::Event.new(
386
- "host" => "myHost",
387
- "foo" => "fancy",
388
- "cpu" => [0.24, 0.11, 0.75, 0.28],
389
- "storageRW" => 51,
390
- "bar" => "blahblah",
391
- "blkio" => {
392
- "write_ps" => 5,
393
- "read_ps" => 2,
394
- "total_ps" => 0
395
- })}
396
-
397
- it "include content" do
398
- sorted = server.all_sorted
399
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.0 foo=fancy 0\.24 \d{10,}$/)
400
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.2 foo=fancy 0\.75 \d{10,}$/)
401
- expect(sorted.pop).to match(/^host=myHost metric=cpu\.3 foo=fancy 0\.28 \d{10,}$/)
402
- expect(sorted.empty?).to eq(true)
403
- end
404
- end
405
-
406
- end
9
+ plugin.register()
10
+ end
11
+
12
+ after :each do
13
+ plugin.close()
14
+ end
15
+
16
+ context "no pile" do
17
+ context "single sender" do
18
+ context "send log in json" do
19
+ let(:plugin) {
20
+ LogStash::Outputs::SumoLogic.new(
21
+ "url" => ENV["sumo_url"],
22
+ "sender_max" => 1,
23
+ "format" => "%{@json}")
24
+ }
25
+ specify {
26
+ event = LogStash::Event.new("host" => "myHost", "message" => "Hello world")
27
+ plugin.receive(event)
28
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
29
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
30
+ }
31
+ end
32
+ context "send fields as metrics" do
33
+ let(:plugin) {
34
+ LogStash::Outputs::SumoLogic.new(
35
+ "url" => ENV["sumo_url"],
36
+ "sender_max" => 1,
37
+ "fields_as_metrics" => true,
38
+ "intrinsic_tags" => {
39
+ "host"=>"%{host}"
40
+ },
41
+ "meta_tags" => {
42
+ "foo" => "%{foo}"
43
+ })
44
+ }
45
+
46
+ specify {
47
+ event = LogStash::Event.new(
48
+ "host" => "myHost",
49
+ "foo" => "fancy",
50
+ "cpu" => [0.24, 0.11, 0.75, 0.28],
51
+ "storageRW" => 51,
52
+ "bar" => "blahblah",
53
+ "blkio" => {
54
+ "write_ps" => 5,
55
+ "read_ps" => 2,
56
+ "total_ps" => 0
57
+ })
58
+
59
+ plugin.receive(event)
60
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
61
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
62
+ }
63
+ end
64
+ end
65
+ context "multiple senders" do
66
+ context "send log in json" do
67
+ let(:plugin) {
68
+ LogStash::Outputs::SumoLogic.new(
69
+ "url" => ENV["sumo_url"],
70
+ "sender_max" => 5,
71
+ "format" => "%{@json}")
72
+ }
73
+
74
+ specify {
75
+ 5.times { |t|
76
+ event = LogStash::Event.new("host" => "myHost", "message" => "Hello world - #{t}")
77
+ plugin.receive(event)
78
+ }
79
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
80
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
81
+ }
82
+ end
83
+
84
+ context "send multiple log in json" do
85
+ let(:plugin) {
86
+ LogStash::Outputs::SumoLogic.new(
87
+ "url" => ENV["sumo_url"],
88
+ "sender_max" => 5,
89
+ "format" => "%{@json}"
90
+ )
91
+ }
92
+
93
+ specify {
94
+ 5.times { |t|
95
+ events = 10.times.map { |r|
96
+ LogStash::Event.new("host" => "myHost", "message" => "Hello world - #{t} - #{r}")
97
+ }
98
+ plugin.multi_receive(events)
99
+ }
100
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
101
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
102
+ }
103
+ end
104
+ end
105
+ end
106
+ context "has pile" do
107
+ context "single sender" do
108
+ context "send log in json" do
109
+ let(:plugin) {
110
+ LogStash::Outputs::SumoLogic.new(
111
+ "url" => ENV["sumo_url"],
112
+ "sender_max" => 1,
113
+ "interval" => 3,
114
+ "format" => "%{@json}")
115
+ }
116
+
117
+ specify {
118
+ 5.times { |t|
119
+ event = LogStash::Event.new("host" => "myHost", "message" => "Hello world - #{t}")
120
+ plugin.receive(event)
121
+ }
122
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
123
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
124
+ }
125
+ end
126
+
127
+ context "send multiple log in json" do
128
+ let(:plugin) {
129
+ LogStash::Outputs::SumoLogic.new(
130
+ "url" => ENV["sumo_url"],
131
+ "sender_max" => 1,
132
+ "interval" => 3,
133
+ "format" => "%{@json}"
134
+ )
135
+ }
136
+
137
+ specify {
138
+ 5.times { |t|
139
+ events = 10.times.map { |r|
140
+ LogStash::Event.new("host" => "myHost", "message" => "Hello world - #{t} - #{r}")
141
+ }
142
+ plugin.multi_receive(events)
143
+ }
144
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
145
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
146
+ }
147
+ end
148
+ end
149
+ context "multi senders" do
150
+ context "send log in json" do
151
+
152
+ let(:plugin) {
153
+ LogStash::Outputs::SumoLogic.new(
154
+ "url" => ENV["sumo_url"],
155
+ "sender_max" => 5,
156
+ "interval" => 3,
157
+ "format" => "%{@json}")
158
+ }
159
+
160
+ specify {
161
+ 5.times { |t|
162
+ event = LogStash::Event.new("host" => "myHost", "message" => "Hello world - #{t}")
163
+ plugin.receive(event)
164
+ }
165
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
166
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
167
+ }
168
+ end
169
+ context "send multiple log in json" do
170
+ let(:plugin) {
171
+ LogStash::Outputs::SumoLogic.new(
172
+ "url" => ENV["sumo_url"],
173
+ "sender_max" => 5,
174
+ "interval" => 3,
175
+ "format" => "%{@json}"
176
+ )
177
+ }
178
+
179
+ specify {
180
+ 5.times { |t|
181
+ events = 10.times.map { |r|
182
+ LogStash::Event.new("host" => "myHost", "message" => "Hello world - #{t} - #{r}")
183
+ }
184
+ plugin.multi_receive(events)
185
+ }
186
+ expect { plugin.stats.total_output_requests.value }.to eventually(be > 0).within(10).pause_for(1)
187
+ expect { plugin.stats.total_response("200") }.to eventually(be > 0).within(10).pause_for(1)
188
+ }
189
+ end
190
+ end
191
+ end
192
+
193
+ @@map = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
194
+ def get_line(length)
195
+ length.times.map { @@map[rand(@@map.length)] }.join
196
+ end
197
+
198
+ context "throughput baseline" do
199
+ let(:plugin) {
200
+ LogStash::Outputs::SumoLogic.new(
201
+ "url" => ENV["sumo_url"],
202
+ "source_category" => "logstash_ci_baseline",
203
+ "sender_max" => 100,
204
+ "interval" => 30,
205
+ "format" => "%{@timestamp} %{message}",
206
+ "compress" => true,
207
+ "compress_encoding" => "gzip",
208
+ "stats_enabled" => true,
209
+ "stats_interval" => 1
210
+ )
211
+ }
212
+
213
+ log_length = 5000 + rand(1000)
214
+ log_count = 50000 + rand(10000)
215
+
216
+ specify {
217
+ log_count.times { |t|
218
+ event = LogStash::Event.new("message" => "#{t} - #{get_line(log_length)}")
219
+ plugin.receive(event)
220
+ }
221
+ expect { plugin.stats.total_log_lines.value }.to eventually(be >= log_count).within(60).pause_for(1)
222
+ bytes = plugin.stats.total_output_bytes.value
223
+ spend = (Time.now - plugin.stats.initialize_time) * 1000
224
+ rate = bytes / spend * 1000
225
+ puts "Sent #{plugin.stats.total_log_lines.value} log lines with #{bytes} bytes in #{'%.2f' % spend} ms, rate #{'%.2f' % (rate/1024/1024) } MB/s."
226
+ expect(rate).to be > 2_000_000
227
+ }
228
+ end
229
+
230
+ end # describe