logstash-output-sumologic 1.2.0 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -1
- data/DEVELOPER.md +19 -3
- data/LICENSE +191 -13
- data/README.md +10 -6
- data/lib/logstash/outputs/sumologic.rb +11 -22
- data/lib/logstash/outputs/sumologic/batch.rb +13 -0
- data/lib/logstash/outputs/sumologic/common.rb +34 -7
- data/lib/logstash/outputs/sumologic/compressor.rb +3 -3
- data/lib/logstash/outputs/sumologic/header_builder.rb +19 -33
- data/lib/logstash/outputs/sumologic/message_queue.rb +33 -14
- data/lib/logstash/outputs/sumologic/monitor.rb +14 -9
- data/lib/logstash/outputs/sumologic/payload_builder.rb +11 -7
- data/lib/logstash/outputs/sumologic/piler.rb +40 -38
- data/lib/logstash/outputs/sumologic/sender.rb +63 -60
- data/lib/logstash/outputs/sumologic/statistics.rb +7 -31
- data/logstash-output-sumologic.gemspec +3 -3
- data/spec/outputs/sumologic/header_builder_spec.rb +134 -1
- data/spec/outputs/sumologic/message_queue_spec.rb +13 -11
- data/spec/outputs/sumologic/payload_builder_spec.rb +2 -3
- data/spec/outputs/sumologic/piler_spec.rb +67 -102
- data/spec/outputs/sumologic_spec.rb +10 -0
- metadata +15 -9
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "stringio"
|
3
|
-
require "zlib"
|
4
|
-
require "logstash/outputs/sumologic/common"
|
5
2
|
|
6
3
|
module LogStash; module Outputs; class SumoLogic;
|
7
4
|
class Compressor
|
8
5
|
|
6
|
+
require "stringio"
|
7
|
+
require "zlib"
|
8
|
+
require "logstash/outputs/sumologic/common"
|
9
9
|
include LogStash::Outputs::SumoLogic::Common
|
10
10
|
|
11
11
|
def initialize(config)
|
@@ -1,31 +1,17 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "socket"
|
3
|
-
require "logstash/outputs/sumologic/common"
|
4
2
|
|
5
3
|
module LogStash; module Outputs; class SumoLogic;
|
6
4
|
class HeaderBuilder
|
7
5
|
|
6
|
+
require "socket"
|
7
|
+
require "logstash/outputs/sumologic/common"
|
8
8
|
include LogStash::Outputs::SumoLogic::Common
|
9
9
|
|
10
|
-
CONTENT_TYPE = "Content-Type"
|
11
|
-
CONTENT_TYPE_LOG = "text/plain"
|
12
|
-
CONTENT_TYPE_GRAPHITE = "application/vnd.sumologic.graphite"
|
13
|
-
CONTENT_TYPE_CARBON2 = "application/vnd.sumologic.carbon2"
|
14
|
-
CONTENT_ENCODING = "Content-Encoding"
|
15
|
-
|
16
|
-
CATEGORY_HEADER = "X-Sumo-Category"
|
17
|
-
CATEGORY_HEADER_DEFAULT = "Logstash"
|
18
|
-
HOST_HEADER = "X-Sumo-Host"
|
19
|
-
NAME_HEADER = "X-Sumo-Name"
|
20
|
-
NAME_HEADER_DEFAULT = "logstash-output-sumologic"
|
21
|
-
|
22
|
-
CLIENT_HEADER = "X-Sumo-Client"
|
23
|
-
CLIENT_HEADER_VALUE = "logstash-output-sumologic"
|
24
|
-
|
25
10
|
def initialize(config)
|
26
11
|
|
27
12
|
@extra_headers = config["extra_headers"] ||= {}
|
28
13
|
@source_category = config["source_category"] ||= CATEGORY_HEADER_DEFAULT
|
14
|
+
@stats_category = config["stats_category"] ||= CATEGORY_HEADER_DEFAULT_STATS
|
29
15
|
@source_host = config["source_host"] ||= Socket.gethostname
|
30
16
|
@source_name = config["source_name"] ||= NAME_HEADER_DEFAULT
|
31
17
|
@metrics = config["metrics"]
|
@@ -36,31 +22,31 @@ module LogStash; module Outputs; class SumoLogic;
|
|
36
22
|
|
37
23
|
end # def initialize
|
38
24
|
|
39
|
-
def build()
|
40
|
-
headers =
|
41
|
-
headers
|
25
|
+
def build(event)
|
26
|
+
headers = Hash.new
|
27
|
+
headers.merge!(@extra_headers)
|
28
|
+
headers[CLIENT_HEADER] = CLIENT_HEADER_VALUE
|
29
|
+
headers[CATEGORY_HEADER] = event.sprintf(@source_category) unless blank?(@source_category)
|
30
|
+
headers[HOST_HEADER] = event.sprintf(@source_host) unless blank?(@source_host)
|
31
|
+
headers[NAME_HEADER] = event.sprintf(@source_name) unless blank?(@source_name)
|
42
32
|
append_content_header(headers)
|
33
|
+
append_compress_header(headers)
|
43
34
|
headers
|
44
35
|
end # def build
|
45
36
|
|
46
37
|
def build_stats()
|
47
|
-
headers =
|
48
|
-
headers[CATEGORY_HEADER] = "#{@source_category}.stats"
|
49
|
-
headers[CONTENT_TYPE] = CONTENT_TYPE_CARBON2
|
50
|
-
headers
|
51
|
-
end # def build_stats
|
52
|
-
|
53
|
-
private
|
54
|
-
def build_common()
|
55
|
-
headers = Hash.new()
|
38
|
+
headers = Hash.new
|
56
39
|
headers.merge!(@extra_headers)
|
57
40
|
headers[CLIENT_HEADER] = CLIENT_HEADER_VALUE
|
58
|
-
headers[
|
59
|
-
headers[
|
41
|
+
headers[CATEGORY_HEADER] = @stats_category
|
42
|
+
headers[HOST_HEADER] = Socket.gethostname
|
43
|
+
headers[NAME_HEADER] = NAME_HEADER_DEFAULT
|
44
|
+
headers[CONTENT_TYPE] = CONTENT_TYPE_CARBON2
|
60
45
|
append_compress_header(headers)
|
61
46
|
headers
|
62
|
-
end #
|
47
|
+
end # def build_stats
|
63
48
|
|
49
|
+
private
|
64
50
|
def append_content_header(headers)
|
65
51
|
contentType = CONTENT_TYPE_LOG
|
66
52
|
if @metrics || @fields_as_metrics
|
@@ -76,4 +62,4 @@ module LogStash; module Outputs; class SumoLogic;
|
|
76
62
|
end # append_compress_header
|
77
63
|
|
78
64
|
end
|
79
|
-
end; end; end
|
65
|
+
end; end; end
|
@@ -1,28 +1,43 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "logstash/outputs/sumologic/common"
|
3
|
-
require "logstash/outputs/sumologic/statistics"
|
4
|
-
|
5
2
|
module LogStash; module Outputs; class SumoLogic;
|
6
3
|
class MessageQueue
|
7
4
|
|
5
|
+
require "logstash/outputs/sumologic/common"
|
6
|
+
require "logstash/outputs/sumologic/statistics"
|
7
|
+
include LogStash::Outputs::SumoLogic::Common
|
8
|
+
|
8
9
|
def initialize(stats, config)
|
9
10
|
@queue_max = (config["queue_max"] ||= 1) < 1 ? 1 : config["queue_max"]
|
10
11
|
@queue = SizedQueue::new(@queue_max)
|
12
|
+
log_info("initialize memory queue", :max => @queue_max)
|
13
|
+
@queue_bytesize = Concurrent::AtomicFixnum.new
|
11
14
|
@stats = stats
|
12
|
-
end
|
15
|
+
end # def initialize
|
13
16
|
|
14
|
-
def enq(
|
15
|
-
|
16
|
-
|
17
|
-
@
|
18
|
-
|
19
|
-
|
17
|
+
def enq(batch)
|
18
|
+
batch_size = batch.payload.bytesize
|
19
|
+
if (batch_size > 0)
|
20
|
+
@queue.enq(batch)
|
21
|
+
@stats.record_enque(batch_size)
|
22
|
+
@queue_bytesize.update { |v| v + batch_size }
|
23
|
+
log_dbg("enqueue",
|
24
|
+
:objects_in_queue => size,
|
25
|
+
:bytes_in_queue => @queue_bytesize,
|
26
|
+
:size => batch_size)
|
27
|
+
end
|
28
|
+
end # def enq
|
20
29
|
|
21
30
|
def deq()
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
31
|
+
batch = @queue.deq()
|
32
|
+
batch_size = batch.payload.bytesize
|
33
|
+
@stats.record_deque(batch_size)
|
34
|
+
@queue_bytesize.update { |v| v - batch_size }
|
35
|
+
log_dbg("dequeue",
|
36
|
+
:objects_in_queue => size,
|
37
|
+
:bytes_in_queue => @queue_bytesize,
|
38
|
+
:size => batch_size)
|
39
|
+
batch
|
40
|
+
end # def deq
|
26
41
|
|
27
42
|
def drain()
|
28
43
|
@queue.size.times.map {
|
@@ -33,6 +48,10 @@ module LogStash; module Outputs; class SumoLogic;
|
|
33
48
|
def size()
|
34
49
|
@queue.size()
|
35
50
|
end # size
|
51
|
+
|
52
|
+
def bytesize()
|
53
|
+
@queue_bytesize.value
|
54
|
+
end # bytesize
|
36
55
|
|
37
56
|
end
|
38
57
|
end; end; end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "logstash/outputs/sumologic/common"
|
3
|
-
require "logstash/outputs/sumologic/statistics"
|
4
|
-
require "logstash/outputs/sumologic/message_queue"
|
5
2
|
|
6
3
|
module LogStash; module Outputs; class SumoLogic;
|
7
4
|
class Monitor
|
8
5
|
|
6
|
+
require "logstash/outputs/sumologic/common"
|
7
|
+
require "logstash/outputs/sumologic/statistics"
|
8
|
+
require "logstash/outputs/sumologic/message_queue"
|
9
9
|
include LogStash::Outputs::SumoLogic::Common
|
10
10
|
|
11
11
|
attr_reader :is_pile
|
@@ -14,6 +14,7 @@ module LogStash; module Outputs; class SumoLogic;
|
|
14
14
|
@queue = queue
|
15
15
|
@stats = stats
|
16
16
|
@stopping = Concurrent::AtomicBoolean.new(false)
|
17
|
+
@header_builder = HeaderBuilder.new(config)
|
17
18
|
|
18
19
|
@enabled = config["stats_enabled"] ||= false
|
19
20
|
@interval = config["stats_interval"] ||= 60
|
@@ -21,13 +22,14 @@ module LogStash; module Outputs; class SumoLogic;
|
|
21
22
|
end # initialize
|
22
23
|
|
23
24
|
def start()
|
25
|
+
log_info("starting monitor...", :interval => @interval)
|
24
26
|
@stopping.make_false()
|
25
27
|
if (@enabled)
|
26
28
|
@monitor_t = Thread.new {
|
27
29
|
while @stopping.false?
|
28
30
|
Stud.stoppable_sleep(@interval) { @stopping.true? }
|
29
|
-
if @stats.
|
30
|
-
@queue.enq(build_stats_payload())
|
31
|
+
if @stats.total_log_lines.value > 0 || @stats.total_metrics_datapoints.value > 0
|
32
|
+
@queue.enq(Batch.new(@header_builder.build_stats(), build_stats_payload()))
|
31
33
|
end
|
32
34
|
end # while
|
33
35
|
}
|
@@ -37,9 +39,9 @@ module LogStash; module Outputs; class SumoLogic;
|
|
37
39
|
def stop()
|
38
40
|
@stopping.make_true()
|
39
41
|
if (@enabled)
|
40
|
-
log_info
|
42
|
+
log_info("shutting down monitor...")
|
41
43
|
@monitor_t.join
|
42
|
-
log_info
|
44
|
+
log_info("monitor is fully shutted down")
|
43
45
|
end
|
44
46
|
end # def stop
|
45
47
|
|
@@ -58,9 +60,12 @@ module LogStash; module Outputs; class SumoLogic;
|
|
58
60
|
"total_response_success"
|
59
61
|
].map { |key|
|
60
62
|
value = @stats.send(key).value
|
63
|
+
log_dbg("stats",
|
64
|
+
:key => key,
|
65
|
+
:value => value)
|
61
66
|
build_metric_line(key, value, timestamp)
|
62
67
|
}.join($/)
|
63
|
-
|
68
|
+
|
64
69
|
"#{STATS_TAG}#{counters}"
|
65
70
|
end # def build_stats_payload
|
66
71
|
|
@@ -69,4 +74,4 @@ module LogStash; module Outputs; class SumoLogic;
|
|
69
74
|
end # def build_metric_line
|
70
75
|
|
71
76
|
end
|
72
|
-
end; end; end
|
77
|
+
end; end; end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "logstash/json"
|
3
|
-
require "logstash/event"
|
4
|
-
|
5
|
-
require "logstash/outputs/sumologic/common"
|
6
2
|
|
7
3
|
module LogStash; module Outputs; class SumoLogic;
|
8
4
|
class PayloadBuilder
|
9
5
|
|
6
|
+
require "logstash/json"
|
7
|
+
require "logstash/event"
|
8
|
+
require "logstash/outputs/sumologic/common"
|
10
9
|
include LogStash::Outputs::SumoLogic::Common
|
11
10
|
|
12
11
|
TIMESTAMP_FIELD = "@timestamp"
|
@@ -128,12 +127,17 @@ module LogStash; module Outputs; class SumoLogic;
|
|
128
127
|
end # def expand_hash
|
129
128
|
|
130
129
|
def apply_template(template, event)
|
131
|
-
if template
|
130
|
+
if template == JSON_PLACEHOLDER
|
131
|
+
hash = event2hash(event)
|
132
|
+
LogStash::Json.dump(hash)
|
133
|
+
elsif template.include? JSON_PLACEHOLDER
|
134
|
+
result = event.sprintf(template)
|
132
135
|
hash = event2hash(event)
|
133
136
|
dump = LogStash::Json.dump(hash)
|
134
|
-
|
137
|
+
result.gsub(JSON_PLACEHOLDER) { dump }
|
138
|
+
else
|
139
|
+
event.sprintf(template)
|
135
140
|
end
|
136
|
-
event.sprintf(template)
|
137
141
|
end # def expand
|
138
142
|
|
139
143
|
def get_metrics_name(event, name)
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "logstash/outputs/sumologic/common"
|
3
|
-
require "logstash/outputs/sumologic/statistics"
|
4
|
-
require "logstash/outputs/sumologic/message_queue"
|
5
2
|
|
6
3
|
module LogStash; module Outputs; class SumoLogic;
|
7
4
|
class Piler
|
8
5
|
|
6
|
+
require "logstash/outputs/sumologic/common"
|
7
|
+
require "logstash/outputs/sumologic/statistics"
|
8
|
+
require "logstash/outputs/sumologic/message_queue"
|
9
9
|
include LogStash::Outputs::SumoLogic::Common
|
10
10
|
|
11
11
|
attr_reader :is_pile
|
@@ -17,23 +17,26 @@ module LogStash; module Outputs; class SumoLogic;
|
|
17
17
|
@queue = queue
|
18
18
|
@stats = stats
|
19
19
|
@stopping = Concurrent::AtomicBoolean.new(false)
|
20
|
+
@payload_builder = PayloadBuilder.new(@stats, config)
|
21
|
+
@header_builder = HeaderBuilder.new(config)
|
20
22
|
@is_pile = (@interval > 0 && @pile_max > 0)
|
21
|
-
|
22
23
|
if (@is_pile)
|
23
|
-
@pile =
|
24
|
-
@pile_size = 0
|
24
|
+
@pile = Hash.new("")
|
25
25
|
@semaphore = Mutex.new
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
end # def initialize
|
29
29
|
|
30
30
|
def start()
|
31
31
|
@stopping.make_false()
|
32
32
|
if (@is_pile)
|
33
|
+
log_info("starting piler...",
|
34
|
+
:max => @pile_max,
|
35
|
+
:timeout => @interval)
|
33
36
|
@piler_t = Thread.new {
|
34
37
|
while @stopping.false?
|
35
38
|
Stud.stoppable_sleep(@interval) { @stopping.true? }
|
36
|
-
log_dbg("timeout,
|
39
|
+
log_dbg("timeout", :timeout => @interval)
|
37
40
|
enq_and_clear()
|
38
41
|
end # while
|
39
42
|
}
|
@@ -43,45 +46,44 @@ module LogStash; module Outputs; class SumoLogic;
|
|
43
46
|
def stop()
|
44
47
|
@stopping.make_true()
|
45
48
|
if (@is_pile)
|
46
|
-
log_info
|
47
|
-
@piler_t.join
|
48
|
-
log_info
|
49
|
+
log_info("shutting down piler in #{@interval * 2} secs ...")
|
50
|
+
@piler_t.join(@interval * 2)
|
51
|
+
log_info("piler is fully shutted down")
|
49
52
|
end
|
50
53
|
end # def stop
|
51
54
|
|
52
|
-
def input(
|
55
|
+
def input(event)
|
53
56
|
if (@stopping.true?)
|
54
|
-
log_warn
|
55
|
-
|
56
|
-
@semaphore.synchronize {
|
57
|
-
if @pile_size + entry.bytesize > @pile_max
|
58
|
-
@queue.enq(@pile.join($/))
|
59
|
-
@pile.clear
|
60
|
-
@pile_size = 0
|
61
|
-
@stats.record_clear_pile()
|
62
|
-
end
|
63
|
-
@pile << entry
|
64
|
-
@pile_size += entry.bytesize
|
65
|
-
@stats.record_input(entry)
|
66
|
-
}
|
57
|
+
log_warn("piler is shutting down, event is dropped",
|
58
|
+
"event" => event)
|
67
59
|
else
|
68
|
-
@
|
69
|
-
|
60
|
+
headers = @header_builder.build(event)
|
61
|
+
payload = @payload_builder.build(event)
|
62
|
+
if (@is_pile)
|
63
|
+
@semaphore.synchronize {
|
64
|
+
content = @pile[headers]
|
65
|
+
size = content.bytesize
|
66
|
+
if size + payload.bytesize > @pile_max
|
67
|
+
@queue.enq(Batch.new(headers, content))
|
68
|
+
@pile[headers] = ""
|
69
|
+
end
|
70
|
+
@pile[headers] = blank?(@pile[headers]) ? payload : "#{@pile[headers]}\n#{payload}"
|
71
|
+
}
|
72
|
+
else
|
73
|
+
@queue.enq(Batch.new(headers, payload))
|
74
|
+
end # if
|
75
|
+
end
|
70
76
|
end # def input
|
71
77
|
|
72
78
|
private
|
73
79
|
def enq_and_clear()
|
74
|
-
|
75
|
-
@
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@stats.record_clear_pile()
|
81
|
-
end
|
82
|
-
}
|
83
|
-
end
|
80
|
+
@semaphore.synchronize {
|
81
|
+
@pile.each do |headers, content|
|
82
|
+
@queue.enq(Batch.new(headers, content))
|
83
|
+
end
|
84
|
+
@pile.clear()
|
85
|
+
}
|
84
86
|
end # def enq_and_clear
|
85
87
|
|
86
88
|
end
|
87
|
-
end; end; end
|
89
|
+
end; end; end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
require "net/https"
|
3
|
-
require "socket"
|
4
|
-
require "thread"
|
5
|
-
require "uri"
|
6
|
-
require "logstash/outputs/sumologic/common"
|
7
|
-
require "logstash/outputs/sumologic/compressor"
|
8
|
-
require "logstash/outputs/sumologic/header_builder"
|
9
|
-
require "logstash/outputs/sumologic/statistics"
|
10
|
-
require "logstash/outputs/sumologic/message_queue"
|
11
2
|
|
12
3
|
module LogStash; module Outputs; class SumoLogic;
|
13
4
|
class Sender
|
14
5
|
|
6
|
+
require "net/https"
|
7
|
+
require "socket"
|
8
|
+
require "thread"
|
9
|
+
require "uri"
|
10
|
+
require "logstash/outputs/sumologic/common"
|
11
|
+
require "logstash/outputs/sumologic/compressor"
|
12
|
+
require "logstash/outputs/sumologic/header_builder"
|
13
|
+
require "logstash/outputs/sumologic/statistics"
|
14
|
+
require "logstash/outputs/sumologic/message_queue"
|
15
15
|
include LogStash::Outputs::SumoLogic::Common
|
16
|
-
|
16
|
+
|
17
17
|
|
18
18
|
def initialize(client, queue, stats, config)
|
19
19
|
@client = client
|
@@ -28,37 +28,37 @@ module LogStash; module Outputs; class SumoLogic;
|
|
28
28
|
@tokens = SizedQueue.new(@sender_max)
|
29
29
|
@sender_max.times { |t| @tokens << t }
|
30
30
|
|
31
|
-
@header_builder = LogStash::Outputs::SumoLogic::HeaderBuilder.new(config)
|
32
|
-
@headers = @header_builder.build()
|
33
|
-
@stats_headers = @header_builder.build_stats()
|
34
31
|
@compressor = LogStash::Outputs::SumoLogic::Compressor.new(config)
|
35
32
|
|
36
33
|
end # def initialize
|
37
34
|
|
38
35
|
def start()
|
36
|
+
log_info("starting sender...",
|
37
|
+
:max => @sender_max,
|
38
|
+
:requeue => @sleep_before_requeue)
|
39
39
|
@stopping.make_false()
|
40
40
|
@sender_t = Thread.new {
|
41
41
|
while @stopping.false?
|
42
|
-
|
43
|
-
send_request(
|
42
|
+
batch = @queue.deq()
|
43
|
+
send_request(batch)
|
44
44
|
end # while
|
45
|
-
@queue.drain().map { |
|
46
|
-
send_request(
|
45
|
+
@queue.drain().map { |batch|
|
46
|
+
send_request(batch)
|
47
47
|
}
|
48
|
-
log_info
|
48
|
+
log_info("waiting while senders finishing...")
|
49
49
|
while @tokens.size < @sender_max
|
50
50
|
sleep 1
|
51
51
|
end # while
|
52
52
|
}
|
53
|
-
end # def
|
53
|
+
end # def start
|
54
54
|
|
55
55
|
def stop()
|
56
|
-
log_info
|
56
|
+
log_info("shutting down sender...")
|
57
57
|
@stopping.make_true()
|
58
|
-
@queue.enq(STOP_TAG)
|
58
|
+
@queue.enq(Batch.new(Hash.new, STOP_TAG))
|
59
59
|
@sender_t.join
|
60
|
-
log_info
|
61
|
-
end # def
|
60
|
+
log_info("sender is fully shutted down")
|
61
|
+
end # def stop
|
62
62
|
|
63
63
|
def connect()
|
64
64
|
uri = URI.parse(@url)
|
@@ -68,34 +68,33 @@ module LogStash; module Outputs; class SumoLogic;
|
|
68
68
|
begin
|
69
69
|
res = http.request(request)
|
70
70
|
if res.code.to_i != 200
|
71
|
-
log_err(
|
72
|
-
"Server rejected the request",
|
71
|
+
log_err("ping rejected",
|
73
72
|
:url => @url,
|
74
|
-
:code => res.code
|
75
|
-
|
73
|
+
:code => res.code,
|
74
|
+
:body => res.body)
|
76
75
|
false
|
77
76
|
else
|
78
|
-
|
79
|
-
|
80
|
-
:url => @url
|
81
|
-
)
|
77
|
+
log_info("ping accepted",
|
78
|
+
:url => @url)
|
82
79
|
true
|
83
80
|
end
|
84
|
-
rescue Exception =>
|
85
|
-
log_err(
|
86
|
-
"Cannot connect to given url",
|
81
|
+
rescue Exception => exception
|
82
|
+
log_err("ping failed",
|
87
83
|
:url => @url,
|
88
|
-
:
|
89
|
-
|
84
|
+
:message => exception.message,
|
85
|
+
:class => exception.class.name,
|
86
|
+
:backtrace => exception.backtrace)
|
90
87
|
false
|
91
88
|
end
|
92
89
|
end # def connect
|
93
90
|
|
94
91
|
private
|
95
92
|
|
96
|
-
def send_request(
|
93
|
+
def send_request(batch)
|
94
|
+
content = batch.payload
|
95
|
+
headers = batch.headers
|
97
96
|
if content == STOP_TAG
|
98
|
-
|
97
|
+
log_info("STOP_TAG is received.")
|
99
98
|
return
|
100
99
|
end
|
101
100
|
|
@@ -103,12 +102,15 @@ module LogStash; module Outputs; class SumoLogic;
|
|
103
102
|
|
104
103
|
if @stats_enabled && content.start_with?(STATS_TAG)
|
105
104
|
body = @compressor.compress(content[STATS_TAG.length..-1])
|
106
|
-
headers = @stats_headers
|
107
105
|
else
|
108
106
|
body = @compressor.compress(content)
|
109
|
-
headers = @headers
|
110
107
|
end
|
111
|
-
|
108
|
+
|
109
|
+
log_dbg("sending request",
|
110
|
+
:headers => headers,
|
111
|
+
:content_size => content.size,
|
112
|
+
:content => content[0..20],
|
113
|
+
:payload_size => body.size)
|
112
114
|
request = @client.send(:background).send(:post, @url, :body => body, :headers => headers)
|
113
115
|
|
114
116
|
request.on_complete do
|
@@ -118,19 +120,16 @@ module LogStash; module Outputs; class SumoLogic;
|
|
118
120
|
request.on_success do |response|
|
119
121
|
@stats.record_response_success(response.code)
|
120
122
|
if response.code < 200 || response.code > 299
|
121
|
-
log_err(
|
122
|
-
"HTTP request rejected(#{response.code})",
|
123
|
+
log_err("request rejected",
|
123
124
|
:token => token,
|
124
125
|
:code => response.code,
|
125
126
|
:headers => headers,
|
126
|
-
:contet => content[0..20]
|
127
|
-
)
|
127
|
+
:contet => content[0..20])
|
128
128
|
if response.code == 429 || response.code == 503 || response.code == 504
|
129
|
-
requeue_message(
|
129
|
+
requeue_message(batch)
|
130
130
|
end
|
131
131
|
else
|
132
|
-
log_dbg(
|
133
|
-
"HTTP request accepted",
|
132
|
+
log_dbg("request accepted",
|
134
133
|
:token => token,
|
135
134
|
:code => response.code)
|
136
135
|
end
|
@@ -138,30 +137,34 @@ module LogStash; module Outputs; class SumoLogic;
|
|
138
137
|
|
139
138
|
request.on_failure do |exception|
|
140
139
|
@stats.record_response_failure()
|
141
|
-
log_err(
|
142
|
-
"Error in network transmission",
|
140
|
+
log_err("error in network transmission",
|
143
141
|
:token => token,
|
144
142
|
:message => exception.message,
|
145
143
|
:class => exception.class.name,
|
146
|
-
:backtrace => exception.backtrace
|
147
|
-
)
|
148
|
-
requeue_message(content)
|
144
|
+
:backtrace => exception.backtrace)
|
145
|
+
requeue_message(batch)
|
149
146
|
end
|
150
147
|
|
151
148
|
@stats.record_request(content.bytesize, body.bytesize)
|
152
149
|
request.call
|
153
150
|
end # def send_request
|
154
151
|
|
155
|
-
def requeue_message(
|
156
|
-
|
157
|
-
|
158
|
-
|
152
|
+
def requeue_message(batch)
|
153
|
+
content = batch.payload
|
154
|
+
if @stats_enabled && content.start_with?(STATS_TAG)
|
155
|
+
log_warn("do not requeue stats payload",
|
156
|
+
:content => content)
|
157
|
+
elsif @stopping.false? && @sleep_before_requeue >= 0
|
158
|
+
log_info("requeue message",
|
159
159
|
:after => @sleep_before_requeue,
|
160
|
-
:
|
160
|
+
:queue_size => @queue.size,
|
161
|
+
:content_size => content.size,
|
162
|
+
:content => content[0..20],
|
163
|
+
:headers => batch.headers)
|
161
164
|
Stud.stoppable_sleep(@sleep_before_requeue) { @stopping.true? }
|
162
|
-
@queue.enq(
|
165
|
+
@queue.enq(batch)
|
163
166
|
end
|
164
167
|
end # def reque_message
|
165
168
|
|
166
169
|
end
|
167
|
-
end; end; end
|
170
|
+
end; end; end
|