semantic_logger 4.1.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/semantic_logger.rb +6 -13
- data/lib/semantic_logger/ansi_colors.rb +10 -10
- data/lib/semantic_logger/appender.rb +42 -26
- data/lib/semantic_logger/appender/async.rb +179 -0
- data/lib/semantic_logger/appender/async_batch.rb +95 -0
- data/lib/semantic_logger/appender/bugsnag.rb +2 -1
- data/lib/semantic_logger/appender/elasticsearch.rb +113 -81
- data/lib/semantic_logger/appender/elasticsearch_http.rb +1 -3
- data/lib/semantic_logger/appender/file.rb +1 -3
- data/lib/semantic_logger/appender/graylog.rb +6 -5
- data/lib/semantic_logger/appender/honeybadger.rb +0 -2
- data/lib/semantic_logger/appender/http.rb +25 -10
- data/lib/semantic_logger/appender/kafka.rb +1 -3
- data/lib/semantic_logger/appender/mongodb.rb +1 -3
- data/lib/semantic_logger/appender/new_relic.rb +7 -3
- data/lib/semantic_logger/appender/sentry.rb +6 -7
- data/lib/semantic_logger/appender/splunk.rb +1 -2
- data/lib/semantic_logger/appender/splunk_http.rb +3 -4
- data/lib/semantic_logger/appender/syslog.rb +1 -3
- data/lib/semantic_logger/appender/tcp.rb +7 -9
- data/lib/semantic_logger/appender/udp.rb +0 -2
- data/lib/semantic_logger/appender/wrapper.rb +0 -2
- data/lib/semantic_logger/base.rb +76 -19
- data/lib/semantic_logger/formatters.rb +37 -0
- data/lib/semantic_logger/formatters/base.rb +10 -3
- data/lib/semantic_logger/formatters/json.rb +2 -6
- data/lib/semantic_logger/formatters/one_line.rb +18 -0
- data/lib/semantic_logger/formatters/raw.rb +8 -2
- data/lib/semantic_logger/formatters/signalfx.rb +169 -0
- data/lib/semantic_logger/log.rb +23 -14
- data/lib/semantic_logger/loggable.rb +88 -15
- data/lib/semantic_logger/logger.rb +0 -20
- data/lib/semantic_logger/metric/new_relic.rb +75 -0
- data/lib/semantic_logger/metric/signalfx.rb +123 -0
- data/lib/semantic_logger/{metrics → metric}/statsd.rb +20 -8
- data/lib/semantic_logger/processor.rb +67 -169
- data/lib/semantic_logger/semantic_logger.rb +7 -31
- data/lib/semantic_logger/subscriber.rb +32 -36
- data/lib/semantic_logger/utils.rb +47 -0
- data/lib/semantic_logger/version.rb +1 -1
- data/test/appender/async_batch_test.rb +61 -0
- data/test/appender/async_test.rb +45 -0
- data/test/appender/elasticsearch_http_test.rb +3 -3
- data/test/appender/elasticsearch_test.rb +211 -49
- data/test/appender/file_test.rb +9 -8
- data/test/appender/mongodb_test.rb +3 -3
- data/test/appender/newrelic_rpm.rb +6 -0
- data/test/appender/sentry_test.rb +3 -1
- data/test/appender/wrapper_test.rb +29 -0
- data/test/concerns/compatibility_test.rb +64 -60
- data/test/debug_as_trace_logger_test.rb +62 -77
- data/test/formatters/one_line_test.rb +61 -0
- data/test/formatters/signalfx_test.rb +200 -0
- data/test/formatters_test.rb +36 -0
- data/test/in_memory_appender.rb +9 -0
- data/test/in_memory_appender_helper.rb +43 -0
- data/test/in_memory_batch_appender.rb +9 -0
- data/test/in_memory_metrics_appender.rb +14 -0
- data/test/loggable_test.rb +15 -30
- data/test/logger_test.rb +181 -135
- data/test/measure_test.rb +212 -113
- data/test/metric/new_relic_test.rb +36 -0
- data/test/metric/signalfx_test.rb +78 -0
- data/test/semantic_logger_test.rb +58 -65
- data/test/test_helper.rb +19 -2
- metadata +33 -7
- data/lib/semantic_logger/metrics/new_relic.rb +0 -30
- data/lib/semantic_logger/metrics/udp.rb +0 -80
- data/test/mock_logger.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b67fae09283837194e489b469dace9f3b5103901
|
4
|
+
data.tar.gz: fc112ededd82585ff40307585e65769ab92601ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a548305f79d04f28a1c2989132eb148f29da9415a5a3bc06b7879d7d95cabe94627533ad56c50a925137f3dfeca1dec62c43707472ade54eb331fd9f764f91a4
|
7
|
+
data.tar.gz: 7bf65721bfb19e865601ef929774877ab514607d86f150e86bb59be969cbecf080d2330e83c8ae2ba4aa2c44ea9b428773e5a791e281a142aeb20b4028036492
|
data/lib/semantic_logger.rb
CHANGED
@@ -8,29 +8,22 @@ module SemanticLogger
|
|
8
8
|
autoload :Appender, 'semantic_logger/appender'
|
9
9
|
autoload :Base, 'semantic_logger/base'
|
10
10
|
autoload :DebugAsTraceLogger, 'semantic_logger/debug_as_trace_logger'
|
11
|
+
autoload :Formatters, 'semantic_logger/formatters'
|
11
12
|
autoload :Log, 'semantic_logger/log'
|
12
13
|
autoload :Logger, 'semantic_logger/logger'
|
13
14
|
autoload :Loggable, 'semantic_logger/loggable'
|
14
15
|
autoload :Processor, 'semantic_logger/processor'
|
15
16
|
autoload :Subscriber, 'semantic_logger/subscriber'
|
17
|
+
autoload :Utils, 'semantic_logger/utils'
|
16
18
|
|
17
19
|
module Concerns
|
18
20
|
autoload :Compatibility, 'semantic_logger/concerns/compatibility'
|
19
21
|
end
|
20
22
|
|
21
|
-
module
|
22
|
-
autoload :
|
23
|
-
autoload :
|
24
|
-
autoload :
|
25
|
-
autoload :Json, 'semantic_logger/formatters/json'
|
26
|
-
autoload :Raw, 'semantic_logger/formatters/raw'
|
27
|
-
autoload :Syslog, 'semantic_logger/formatters/syslog'
|
28
|
-
end
|
29
|
-
|
30
|
-
module Metrics
|
31
|
-
autoload :NewRelic, 'semantic_logger/metrics/new_relic'
|
32
|
-
autoload :Statsd, 'semantic_logger/metrics/statsd'
|
33
|
-
autoload :Udp, 'semantic_logger/metrics/udp'
|
23
|
+
module Metric
|
24
|
+
autoload :NewRelic, 'semantic_logger/metric/new_relic'
|
25
|
+
autoload :Signalfx, 'semantic_logger/metric/signalfx'
|
26
|
+
autoload :Statsd, 'semantic_logger/metric/statsd'
|
34
27
|
end
|
35
28
|
|
36
29
|
if defined?(JRuby)
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module SemanticLogger
|
2
2
|
# Formatting & colors used by optional color formatter
|
3
3
|
module AnsiColors
|
4
|
-
CLEAR
|
5
|
-
BOLD
|
6
|
-
BLACK
|
7
|
-
RED
|
8
|
-
GREEN
|
9
|
-
YELLOW
|
10
|
-
BLUE
|
11
|
-
MAGENTA
|
12
|
-
CYAN
|
13
|
-
WHITE
|
4
|
+
CLEAR = "\e[0m"
|
5
|
+
BOLD = "\e[1m"
|
6
|
+
BLACK = "\e[30m"
|
7
|
+
RED = "\e[31m"
|
8
|
+
GREEN = "\e[32m"
|
9
|
+
YELLOW = "\e[33m"
|
10
|
+
BLUE = "\e[34m"
|
11
|
+
MAGENTA = "\e[35m"
|
12
|
+
CYAN = "\e[36m"
|
13
|
+
WHITE = "\e[37m"
|
14
14
|
|
15
15
|
# DEPRECATED - NOT USED
|
16
16
|
LEVEL_MAP = {
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module SemanticLogger
|
2
2
|
module Appender
|
3
3
|
# @formatter:off
|
4
|
+
autoload :Async, 'semantic_logger/appender/async'
|
5
|
+
autoload :AsyncBatch, 'semantic_logger/appender/async_batch'
|
4
6
|
autoload :Bugsnag, 'semantic_logger/appender/bugsnag'
|
5
7
|
autoload :Elasticsearch, 'semantic_logger/appender/elasticsearch'
|
6
8
|
autoload :ElasticsearchHttp, 'semantic_logger/appender/elasticsearch_http'
|
@@ -34,45 +36,59 @@ module SemanticLogger
|
|
34
36
|
end
|
35
37
|
|
36
38
|
# Returns [SemanticLogger::Subscriber] appender for the supplied options
|
37
|
-
def self.
|
39
|
+
def self.factory(options, &block)
|
40
|
+
options = options.dup
|
41
|
+
async = options.delete(:async)
|
42
|
+
batch = options.delete(:batch)
|
43
|
+
|
44
|
+
# Extract batch and async options
|
45
|
+
proxy_options = {}
|
46
|
+
ASYNC_OPTION_KEYS.each { |key| proxy_options[key] = options.delete(key) if options.key?(key) }
|
47
|
+
|
48
|
+
appender = build(options, &block)
|
49
|
+
|
50
|
+
# If appender implements #batch, then it should use the batch proxy by default.
|
51
|
+
batch = true if batch.nil? && appender.respond_to?(:batch)
|
52
|
+
|
53
|
+
if batch == true
|
54
|
+
proxy_options[:appender] = appender
|
55
|
+
Appender::AsyncBatch.new(proxy_options)
|
56
|
+
elsif async == true
|
57
|
+
proxy_options[:appender] = appender
|
58
|
+
Appender::Async.new(proxy_options)
|
59
|
+
else
|
60
|
+
appender
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
ASYNC_OPTION_KEYS = [:max_queue_size, :lag_threshold_s, :batch_size, :batch_seconds, :lag_check_interval]
|
67
|
+
|
68
|
+
# Returns [Subscriber] instance from the supplied options.
|
69
|
+
def self.build(options, &block)
|
38
70
|
if options[:io] || options[:file_name]
|
39
71
|
SemanticLogger::Appender::File.new(options, &block)
|
40
72
|
elsif appender = options.delete(:appender)
|
41
73
|
if appender.is_a?(Symbol)
|
42
|
-
constantize_symbol(appender).new(options)
|
74
|
+
SemanticLogger::Utils.constantize_symbol(appender).new(options)
|
43
75
|
elsif appender.is_a?(Subscriber)
|
44
76
|
appender
|
45
77
|
else
|
46
78
|
raise(ArgumentError, "Parameter :appender must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
|
47
79
|
end
|
48
|
-
elsif options
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def self.constantize_symbol(symbol, namespace = 'SemanticLogger::Appender')
|
54
|
-
klass = "#{namespace}::#{camelize(symbol.to_s)}"
|
55
|
-
begin
|
56
|
-
if RUBY_VERSION.to_i >= 2
|
57
|
-
Object.const_get(klass)
|
80
|
+
elsif appender = options.delete(:metric)
|
81
|
+
if appender.is_a?(Symbol)
|
82
|
+
SemanticLogger::Utils.constantize_symbol(appender, 'SemanticLogger::Metric').new(options)
|
83
|
+
elsif appender.is_a?(Subscriber)
|
84
|
+
appender
|
58
85
|
else
|
59
|
-
|
86
|
+
raise(ArgumentError, "Parameter :metric must be either a Symbol or an object derived from SemanticLogger::Subscriber, not: #{appender.inspect}")
|
60
87
|
end
|
61
|
-
|
62
|
-
|
88
|
+
elsif options[:logger]
|
89
|
+
SemanticLogger::Appender::Wrapper.new(options, &block)
|
63
90
|
end
|
64
91
|
end
|
65
92
|
|
66
|
-
private
|
67
|
-
|
68
|
-
# Borrow from Rails, when not running Rails
|
69
|
-
def self.camelize(term)
|
70
|
-
string = term.to_s
|
71
|
-
string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
|
72
|
-
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
73
|
-
string.gsub!('/'.freeze, '::'.freeze)
|
74
|
-
string
|
75
|
-
end
|
76
|
-
|
77
93
|
end
|
78
94
|
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module SemanticLogger
|
4
|
+
module Appender
|
5
|
+
# Allow any appender to run asynchronously in a separate thread.
|
6
|
+
class Async
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
attr_accessor :logger, :lag_check_interval, :lag_threshold_s
|
10
|
+
attr_reader :queue, :appender
|
11
|
+
|
12
|
+
# Forward methods that can be called directly
|
13
|
+
def_delegator :@appender, :name
|
14
|
+
def_delegator :@appender, :should_log?
|
15
|
+
def_delegator :@appender, :filter
|
16
|
+
def_delegator :@appender, :host
|
17
|
+
def_delegator :@appender, :application
|
18
|
+
def_delegator :@appender, :level
|
19
|
+
def_delegator :@appender, :level=
|
20
|
+
def_delegator :@appender, :logger
|
21
|
+
|
22
|
+
# Appender proxy to allow an existing appender to run asynchronously in a separate thread.
|
23
|
+
#
|
24
|
+
# Parameters:
|
25
|
+
# name: [String]
|
26
|
+
# Name to use for the log thread and the log name when logging any errors from this appender.
|
27
|
+
#
|
28
|
+
# max_queue_size: [Integer]
|
29
|
+
# The maximum number of log messages to hold on the queue before blocking attempts to add to the queue.
|
30
|
+
# -1: The queue size is uncapped and will never block no matter how long the queue is.
|
31
|
+
# Default: 10,000
|
32
|
+
#
|
33
|
+
# lag_threshold_s [Float]
|
34
|
+
# Log a warning when a log message has been on the queue for longer than this period in seconds.
|
35
|
+
# Default: 30
|
36
|
+
#
|
37
|
+
# lag_check_interval: [Integer]
|
38
|
+
# Number of messages to process before checking for slow logging.
|
39
|
+
# Default: 1,000
|
40
|
+
def initialize(appender:,
|
41
|
+
name: appender.class.name,
|
42
|
+
max_queue_size: 10_000,
|
43
|
+
lag_check_interval: 1_000,
|
44
|
+
lag_threshold_s: 30)
|
45
|
+
|
46
|
+
@appender = appender
|
47
|
+
@lag_check_interval = lag_check_interval
|
48
|
+
@lag_threshold_s = lag_threshold_s
|
49
|
+
|
50
|
+
if max_queue_size == -1
|
51
|
+
@queue = Queue.new
|
52
|
+
@capped = false
|
53
|
+
else
|
54
|
+
@queue = SizedQueue.new(max_queue_size)
|
55
|
+
@capped = true
|
56
|
+
end
|
57
|
+
thread
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns [true|false] if the queue has a capped size.
|
61
|
+
def capped?
|
62
|
+
@capped
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns [Thread] the worker thread.
|
66
|
+
#
|
67
|
+
# Starts the worker thread if not running.
|
68
|
+
def thread
|
69
|
+
return @thread if @thread && @thread.alive?
|
70
|
+
@thread = Thread.new { process }
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns true if the worker thread is active
|
74
|
+
def active?
|
75
|
+
@thread && @thread.alive?
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add log message for processing.
|
79
|
+
def log(log)
|
80
|
+
queue << log
|
81
|
+
end
|
82
|
+
|
83
|
+
# Flush all queued log entries disk, database, etc.
|
84
|
+
# All queued log messages are written and then each appender is flushed in turn.
|
85
|
+
def flush
|
86
|
+
submit_request(:flush)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Close all appenders and flush any outstanding messages.
|
90
|
+
def close
|
91
|
+
# TODO: Prevent new close requests once this appender has been closed.
|
92
|
+
submit_request(:close)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
# Separate thread for batching up log messages before writing.
|
98
|
+
def process
|
99
|
+
# This thread is designed to never go down unless the main thread terminates
|
100
|
+
# or the appender is closed.
|
101
|
+
Thread.current.name = logger.name
|
102
|
+
logger.trace "Async: Appender thread active"
|
103
|
+
begin
|
104
|
+
process_messages
|
105
|
+
rescue StandardError => exception
|
106
|
+
# This block may be called after the file handles have been released by Ruby
|
107
|
+
logger.error('Async: Restarting due to exception', exception) rescue nil
|
108
|
+
retry
|
109
|
+
rescue Exception => exception
|
110
|
+
# This block may be called after the file handles have been released by Ruby
|
111
|
+
logger.error('Async: Stopping due to fatal exception', exception) rescue nil
|
112
|
+
ensure
|
113
|
+
@thread = nil
|
114
|
+
# This block may be called after the file handles have been released by Ruby
|
115
|
+
logger.trace('Async: Thread has stopped') rescue nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def process_messages
|
120
|
+
count = 0
|
121
|
+
while message = queue.pop
|
122
|
+
if message.is_a?(Log)
|
123
|
+
appender.log(message)
|
124
|
+
count += 1
|
125
|
+
# Check every few log messages whether this appender thread is falling behind
|
126
|
+
if count > lag_check_interval
|
127
|
+
check_lag(message)
|
128
|
+
count = 0
|
129
|
+
end
|
130
|
+
else
|
131
|
+
break unless process_message(message)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Returns false when message processing should be stopped
|
137
|
+
def process_message(message)
|
138
|
+
case message[:command]
|
139
|
+
when :flush
|
140
|
+
appender.flush
|
141
|
+
message[:reply_queue] << true if message[:reply_queue]
|
142
|
+
when :close
|
143
|
+
appender.close
|
144
|
+
message[:reply_queue] << true if message[:reply_queue]
|
145
|
+
return false
|
146
|
+
else
|
147
|
+
logger.warn "Async: Appender thread: Ignoring unknown command: #{message[:command]}"
|
148
|
+
end
|
149
|
+
true
|
150
|
+
end
|
151
|
+
|
152
|
+
def check_lag(log)
|
153
|
+
if (diff = Time.now - log.time) > lag_threshold_s
|
154
|
+
logger.warn "Async: Appender thread has fallen behind by #{diff} seconds with #{queue.size} messages queued up. Consider reducing the log level or changing the appenders"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Submit command and wait for reply
|
159
|
+
def submit_request(command)
|
160
|
+
return false unless active?
|
161
|
+
|
162
|
+
queue_size = queue.size
|
163
|
+
msg = "Async: Queued log messages: #{queue_size}, running command: #{command}"
|
164
|
+
if queue_size > 1_000
|
165
|
+
logger.warn msg
|
166
|
+
elsif queue_size > 100
|
167
|
+
logger.info msg
|
168
|
+
elsif queue_size > 0
|
169
|
+
logger.trace msg
|
170
|
+
end
|
171
|
+
|
172
|
+
reply_queue = Queue.new
|
173
|
+
queue << {command: command, reply_queue: reply_queue}
|
174
|
+
reply_queue.pop
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
module SemanticLogger
|
4
|
+
module Appender
|
5
|
+
# Log asynchronously in batches using a separate thread.
|
6
|
+
#
|
7
|
+
# Log messages are grouped up and only logged when:
|
8
|
+
# * The number of queued messages is exceeded.
|
9
|
+
# * Or, the appropriate amount of time has passed since the last batch was sent.
|
10
|
+
class AsyncBatch < Async
|
11
|
+
attr_accessor :batch_size, :batch_seconds
|
12
|
+
attr_reader :signal
|
13
|
+
|
14
|
+
# Batching Appender proxy for appenders that support batches.
|
15
|
+
#
|
16
|
+
# Parameters:
|
17
|
+
# batch_size: [Integer]
|
18
|
+
# Maximum number of messages to batch up before sending.
|
19
|
+
# Default: 300
|
20
|
+
#
|
21
|
+
# batch_seconds: [Integer]
|
22
|
+
# Maximum number of seconds between sending batches.
|
23
|
+
# Default: 5
|
24
|
+
#
|
25
|
+
# See SemanticLogger::Appender::Async for other paramaters
|
26
|
+
#
|
27
|
+
# Note:
|
28
|
+
# * `lag_check_interval` is not applicable to batches, since the first message of every batch
|
29
|
+
# is the oldest and is always checked to see if the lag interval has been exceeded.
|
30
|
+
def initialize(appender:,
|
31
|
+
name: appender.class.name,
|
32
|
+
max_queue_size: 10_000,
|
33
|
+
lag_threshold_s: 30,
|
34
|
+
batch_size: 300,
|
35
|
+
batch_seconds: 5)
|
36
|
+
|
37
|
+
@batch_size = batch_size
|
38
|
+
@batch_seconds = batch_seconds
|
39
|
+
@signal = Concurrent::Event.new
|
40
|
+
super(
|
41
|
+
appender: appender,
|
42
|
+
name: name,
|
43
|
+
max_queue_size: max_queue_size,
|
44
|
+
lag_threshold_s: lag_threshold_s
|
45
|
+
)
|
46
|
+
|
47
|
+
raise(ArgumentError, "#{appender.class.name} does not support batching. It must implement #batch") unless appender.respond_to?(:batch)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Add log message for processing.
|
51
|
+
def log(log)
|
52
|
+
result = super(log)
|
53
|
+
# Wake up the processing thread since the number of queued messages has been exceeded.
|
54
|
+
signal.set if queue.size >= batch_size
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Separate thread for batching up log messages before writing.
|
61
|
+
def process_messages
|
62
|
+
loop do
|
63
|
+
# Wait for batch interval or number of messages to be exceeded.
|
64
|
+
signal.wait(batch_seconds)
|
65
|
+
|
66
|
+
logs = []
|
67
|
+
first = true
|
68
|
+
message_count = queue.length
|
69
|
+
message_count.times do
|
70
|
+
# Queue#pop(true) raises an exception when there are no more messages, which is considered expensive.
|
71
|
+
message = queue.pop
|
72
|
+
if message.is_a?(Log)
|
73
|
+
logs << message
|
74
|
+
if first
|
75
|
+
check_lag(message)
|
76
|
+
first = false
|
77
|
+
end
|
78
|
+
else
|
79
|
+
process_message(message)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
appender.batch(logs) if logs.size > 0
|
83
|
+
signal.reset unless queue.size >= batch_size
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def submit_request(command)
|
88
|
+
# Wake up the processing thread to process this command immediately.
|
89
|
+
signal.set
|
90
|
+
super
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -48,13 +48,14 @@ class SemanticLogger::Appender::Bugsnag < SemanticLogger::Subscriber
|
|
48
48
|
|
49
49
|
# Send an error notification to Bugsnag
|
50
50
|
def log(log)
|
51
|
-
return false unless should_log?(log)
|
52
51
|
# Ignore logs coming from Bugsnag itself
|
53
52
|
return false if log.name == 'Bugsnag'
|
54
53
|
|
55
54
|
# Send error messages as Runtime exceptions
|
56
55
|
exception =
|
57
56
|
if log.exception
|
57
|
+
# Manually constructed Exception, without a backtrace.
|
58
|
+
log.exception.set_backtrace(log.backtrace) if !log.exception.backtrace && log.backtrace
|
58
59
|
log.exception
|
59
60
|
else
|
60
61
|
error = RuntimeError.new(log.message)
|