timber 2.0.20 → 2.0.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 946dc64576210d225bbf4952fa78363705b3b87f
4
- data.tar.gz: e972b58acf8efc60ebcc79746939d7bbceeadd06
3
+ metadata.gz: f65e44d5582af9d177dabd02f2229adda5ea094b
4
+ data.tar.gz: a113bb27776a6403b3b237b49d33c7fbac962758
5
5
  SHA512:
6
- metadata.gz: f44fdf7da119df5a80cd1cb589f1c55d8fee39bfccd6cacf35eaf9b5944afdc227cb6d715473c651d3830035915bc62df11cae4c7c58a779331870fa23659d26
7
- data.tar.gz: 7cad85ce7ea3c9df75fd2d3fc7e18df07d42d20f294bba6af8803dce710f7b9a7e0a8990ef243d3feff942807625ffb8b40bc2ecde89c98e2604a7e129c94533
6
+ metadata.gz: 10b371f99e2c4f4203526917a770140095581e17a12b72fba44dfc8db8b2151a198b5e771527fb715f6c9c4fe9e0d1c56772ff6663fb31c07f76bd95210339d4
7
+ data.tar.gz: e0b9fd2b91d7de66b4bee5305337afeb5017ec42fff2c76e8374c957af5d88445701aa029fca846f2f7e7778e4ffa7231989ea6c05d3814f307e244e5b2607d0
data/.travis.yml CHANGED
@@ -22,7 +22,7 @@ env:
22
22
  before_script:
23
23
  - echo $BUNDLE_GEMFILE
24
24
  - bundle install
25
- script: bundle exec rspec
25
+ script: bundle exec rspec --format documentation
26
26
  matrix:
27
27
  fast_finish: true
28
28
  exclude:
data/lib/timber/config.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require "logger"
1
2
  require "singleton"
2
3
 
3
4
  module Timber
@@ -13,6 +14,13 @@ module Timber
13
14
  class Config
14
15
  class NoLoggerError < StandardError; end
15
16
 
17
+ class SimpleFormatter < ::Logger::Formatter
18
+ # This method is invoked when a log event occurs
19
+ def call(severity, timestamp, progname, msg)
20
+ "[Timber] #{String === msg ? msg : msg.inspect}\n"
21
+ end
22
+ end
23
+
16
24
  PRODUCTION_NAME = "production".freeze
17
25
  STAGING_NAME = "staging".freeze
18
26
 
@@ -54,6 +62,7 @@ module Timber
54
62
  file.binmode
55
63
  file.sync = config.autoflush_log
56
64
  file_logger = ::Logger.new(file)
65
+ file_logger.formatter = SimpleFormatter.new
57
66
  self.debug_logger = file_logger
58
67
  end
59
68
 
@@ -65,6 +74,7 @@ module Timber
65
74
  # Timber::Config.instance.debug_to_file("log/timber.log")
66
75
  def debug_to_stdout
67
76
  stdout_logger = ::Logger.new(STDOUT)
77
+ stdout_logger.formatter = SimpleFormatter.new
68
78
  self.debug_logger = stdout_logger
69
79
  end
70
80
 
@@ -133,7 +143,11 @@ module Timber
133
143
  # @example Everything else
134
144
  # Timber::Config.instance.logger = Timber::Logger.new(STDOUT)
135
145
  def logger
136
- @logger || Logger.new(STDOUT)
146
+ if @logger.is_a?(Proc)
147
+ @logger.call()
148
+ else
149
+ @logger ||= Logger.new(STDOUT)
150
+ end
137
151
  end
138
152
 
139
153
  private
@@ -3,12 +3,12 @@ require "logger"
3
3
  # Attempt to require Rails. We can not list it as a gem
4
4
  # dependency because we want to support multiple frameworks.
5
5
  begin
6
- require("rails")
6
+ require "rails"
7
7
  rescue LoadError
8
8
  end
9
9
 
10
10
  if defined?(::Rails) && defined?(::Rails::Railtie)
11
- require 'timber/frameworks/rails'
11
+ require "timber/frameworks/rails"
12
12
  end
13
13
 
14
14
  module Timber
@@ -48,14 +48,17 @@ module Timber
48
48
  class Railtie < ::Rails::Railtie
49
49
  config.timber = Config.instance
50
50
 
51
- # Initialize Timber immediately after the logger in case anything uses the logger
52
- # during the initialization process.
53
- initializer(:timber, after: :initialize_logger) do
54
- logger = Rails.ensure_timber_logger(::Rails.logger)
55
- Rails.set_logger(logger)
51
+ config.before_initialize do
52
+ Timber::Config.instance.logger = Proc.new { ::Rails.logger }
53
+ end
56
54
 
55
+ # Must be loaded after initializers so that we respect any Timber configuration
56
+ # set
57
+ initializer(:timber, after: :load_config_initializers) do
57
58
  Integrations.integrate!
58
59
 
60
+ # Install the Rack middlewares so that we capture structured data instead of
61
+ # raw text logs.
59
62
  timber_operations = Integrations::Rack.middlewares.collect do |middleware_class|
60
63
  [:use, [middleware_class], nil]
61
64
  end
@@ -63,43 +66,6 @@ module Timber
63
66
  config.app_middleware.timber_operations = timber_operations
64
67
  end
65
68
  end
66
-
67
- # This builds a new Timber::Logger from an existing logger. This allows us to transparentl
68
- # switch users onto the Timber::Logger since we support a more useful logging API.
69
- def self.ensure_timber_logger(existing_logger)
70
- if existing_logger.is_a?(Logger)
71
- return existing_logger
72
- end
73
-
74
- log_device = existing_logger.instance_variable_get(:@logdev).try(:dev)
75
- logger = Logger.new(log_device)
76
- logger.level = existing_logger.try(:level) || Logger::DEBUG
77
- if defined?(::ActiveSupport::TaggedLogging)
78
- logger = ::ActiveSupport::TaggedLogging.new(logger)
79
- end
80
- logger
81
- end
82
-
83
- # Sets the Rails logger. Rails
84
- def self.set_logger(logger)
85
- if defined?(::ActiveSupport::TaggedLogging) && !logger.is_a?(::ActiveSupport::TaggedLogging)
86
- logger = ::ActiveSupport::TaggedLogging.new(logger)
87
- end
88
-
89
- Config.instance.logger = logger
90
-
91
- # Set the various Rails framework loggers. We *have* to do this because Rails
92
- # internally sets these with an ActiveSupport.onload(:active_record) { } callback.
93
- # We don't have an opportunity to intercept this since the :initialize_logger
94
- # initializer loads these modules. Moreover, earlier version of rails don't do this
95
- # at all, hence the defined? checks. Yay for being implicit.
96
- ::ActionCable::Server::Base.logger = logger if defined?(::ActionCable::Server::Base) && ::ActionCable::Server::Base.respond_to?(:logger=)
97
- ::ActionController::Base.logger = logger if defined?(::ActionController::Base) && ::ActionController::Base.respond_to?(:logger=)
98
- ::ActionMailer::Base.logger = logger if defined?(::ActionMailer::Base) && ::ActionMailer::Base.respond_to?(:logger=)
99
- ::ActionView::Base.logger = logger if defined?(::ActionView::Base) && ::ActionView::Base.respond_to?(:logger=)
100
- ::ActiveRecord::Base.logger = logger if defined?(::ActiveRecord::Base) && ::ActiveRecord::Base.respond_to?(:logger=)
101
- ::Rails.logger = logger
102
- end
103
69
  end
104
70
  end
105
71
  end
@@ -1,6 +1,6 @@
1
- # We require all of ActiveRecord because #logger usses ActiveRecord::Base.
2
- # We can't require active_record/base directly because ActiveRecord does not require
3
- # files properly.
1
+ # We require all of ActiveRecord because the #logger method in ::ActiveRecord::LogSubscriber
2
+ # uses ActiveRecord::Base. We can't require active_record/base directly because ActiveRecord
3
+ # does not require files properly and we receive unintialized constant errors.
4
4
  require "active_record"
5
5
  require "active_record/log_subscriber"
6
6
 
@@ -6,7 +6,18 @@ module Timber
6
6
  class RequirementNotMetError < StandardError; end
7
7
 
8
8
  class << self
9
+ attr_writer :enabled
10
+
11
+ def enabled?
12
+ @enabled != false
13
+ end
14
+
9
15
  def integrate!(*args)
16
+ if !enabled?
17
+ Config.instance.debug_logger.debug("#{name} integration disabled, skipping") if Config.instance.debug_logger
18
+ return false
19
+ end
20
+
10
21
  new(*args).integrate!
11
22
  Config.instance.debug_logger.debug("Integrated #{name}") if Config.instance.debug_logger
12
23
  true
@@ -5,7 +5,8 @@ module Timber
5
5
  module LogDevices
6
6
  # A highly efficient log device that buffers and delivers log messages over HTTPS to
7
7
  # the Timber API. It uses batches, keep-alive connections, and msgpack to deliver logs with
8
- # high-throughput and little overhead.
8
+ # high-throughput and little overhead. All log preparation and delivery is done asynchronously
9
+ # in a thread as not to block application execution.
9
10
  #
10
11
  # See {#initialize} for options and more details.
11
12
  class HTTP
@@ -118,6 +119,7 @@ module Timber
118
119
  @requests_per_conn = options[:requests_per_conn] || 2_500
119
120
  @msg_queue = LogMsgQueue.new(@batch_size)
120
121
  @request_queue = options[:request_queue] || SizedQueue.new(3)
122
+ @successive_error_count = 0
121
123
  @requests_in_flight = 0
122
124
  end
123
125
 
@@ -133,7 +135,7 @@ module Timber
133
135
  ensure_flush_threads_are_started
134
136
 
135
137
  if @msg_queue.full?
136
- debug_logger.debug("Flushing timber buffer via write") if debug_logger
138
+ debug_logger.debug("Flushing HTTP buffer via write") if debug_logger
137
139
  flush
138
140
  end
139
141
  true
@@ -154,9 +156,26 @@ module Timber
154
156
 
155
157
  # Closes the log device, cleans up, and attempts one last delivery.
156
158
  def close
159
+ # Kill the flush thread immediately since we are about to flush again.
157
160
  @flush_thread.kill if @flush_thread
158
- @outlet_thread.kill if @outlet_thread
161
+
162
+ # Flush all remaining messages
159
163
  flush
164
+
165
+ # Kill the request_outlet thread gracefully. We do not want to kill it while a
166
+ # request is inflight. Ideally we'd let it finish before we die.
167
+ if @request_outlet_thread
168
+ 4.times do
169
+ if @requests_in_flight == 0 && @request_queue.size == 0
170
+ @request_outlet_thread.kill
171
+ break
172
+ else
173
+ debug_logger.error("Busy delivering the final log messages, " +
174
+ "connection will close when complete.")
175
+ sleep 1
176
+ end
177
+ end
178
+ end
160
179
  end
161
180
 
162
181
  private
@@ -170,8 +189,8 @@ module Timber
170
189
  # threads are started after process forking.
171
190
  def ensure_flush_threads_are_started
172
191
  if @flush_continuously
173
- if @outlet_thread.nil? || !@outlet_thread.alive?
174
- @outlet_thread = Thread.new { outlet }
192
+ if @request_outlet_thread.nil? || !@request_outlet_thread.alive?
193
+ @request_outlet_thread = Thread.new { request_outlet }
175
194
  end
176
195
 
177
196
  if @flush_thread.nil? || !@flush_thread.alive?
@@ -183,15 +202,17 @@ module Timber
183
202
  def intervaled_flush
184
203
  # Wait specified time period before starting
185
204
  sleep @flush_interval
205
+
186
206
  loop do
187
207
  begin
188
208
  if intervaled_flush_ready?
189
- debug_logger.debug("Flushing timber buffer via the interval") if debug_logger
209
+ debug_logger.debug("Flushing HTTP buffer via the interval") if debug_logger
190
210
  flush
191
211
  end
192
- sleep(0.1)
212
+
213
+ sleep(0.5)
193
214
  rescue Exception => e
194
- logger.error("Timber intervaled flush failed: #{e.inspect}\n\n#{e.backtrace}")
215
+ logger.error("Intervaled HTTP flush failed: #{e.inspect}\n\n#{e.backtrace}")
195
216
  end
196
217
  end
197
218
  end
@@ -200,50 +221,73 @@ module Timber
200
221
  @last_flush.nil? || (Time.now.to_f - @last_flush.to_f).abs >= @flush_interval
201
222
  end
202
223
 
203
- def outlet
224
+ def build_http
225
+ http = Net::HTTP.new(@timber_url.host, @timber_url.port)
226
+ http.set_debug_output(debug_logger) if debug_logger
227
+ http.use_ssl = true if @timber_url.scheme == 'https'
228
+ http.read_timeout = 30
229
+ http.ssl_timeout = 10
230
+ http.open_timeout = 10
231
+ http
232
+ end
233
+
234
+ def request_outlet
204
235
  loop do
205
- http = Net::HTTP.new(@timber_url.host, @timber_url.port)
206
- http.set_debug_output(debug_logger) if debug_logger
207
- http.use_ssl = true if @timber_url.scheme == 'https'
208
- http.read_timeout = 30
209
- http.ssl_timeout = 10
210
- http.open_timeout = 10
236
+ http = build_http
211
237
 
212
238
  begin
213
- debug_logger.info("Starting Timber HTTP connection") if debug_logger
239
+ debug_logger.info("Starting HTTP connection") if debug_logger
240
+
214
241
  http.start do |conn|
215
- num_reqs = 0
216
- while num_reqs < @requests_per_conn
217
- if debug_logger
218
- debug_logger.debug("Waiting on next Timber request")
219
- debug_logger.debug("Number of threads waiting on Timber request queue: #{@request_queue.num_waiting}")
220
- end
221
-
222
- # Blocks waiting for a request.
223
- req = @request_queue.deq
224
- @requests_in_flight += 1
225
- resp = nil
226
- begin
227
- resp = conn.request(req)
228
- rescue => e
229
- debug_logger.error("Timber request error: #{e.message}") if debug_logger
230
- next
231
- ensure
232
- @requests_in_flight -= 1
233
- end
234
- num_reqs += 1
235
- debug_logger.debug("Timber request successful: #{resp.code}") if debug_logger
236
- end
242
+ deliver_requests(conn)
237
243
  end
238
244
  rescue => e
239
- debug_logger.error("Timber request error: #{e.message}") if debug_logger
245
+ debug_logger.error("#request_outlet error: #{e.message}") if debug_logger
240
246
  ensure
241
- debug_logger.debug("Finishing Timber HTTP connection") if debug_logger
247
+ debug_logger.info("Finishing HTTP connection") if debug_logger
242
248
  http.finish if http.started?
243
249
  end
244
250
  end
245
251
  end
246
252
 
253
+ def deliver_requests(conn)
254
+ num_reqs = 0
255
+
256
+ while num_reqs < @requests_per_conn
257
+ debug_logger.info("Waiting on next request, threads waiting: #{@request_queue.num_waiting}") if debug_logger
258
+
259
+ # Blocks waiting for a request.
260
+ req = @request_queue.deq
261
+ @requests_in_flight += 1
262
+
263
+ begin
264
+ resp = conn.request(req)
265
+ rescue => e
266
+ debug_logger.error("#deliver_request error: #{e.message}") if debug_logger
267
+
268
+ @successive_error_count += 1
269
+
270
+ # Back off so that we don't hammer the Timber API.
271
+ calculated_backoff = @successive_error_count * 2
272
+ backoff = calculated_backoff > 30 ? 30 : calculated_backoff
273
+
274
+ debug_logger.error("Backing off #{backoff} seconds, error ##{@successive_error_count}") if debug_logger
275
+
276
+ sleep backoff
277
+
278
+ # Throw the request back on the queue for a retry
279
+ @request_queue.enq(req)
280
+ return false
281
+ ensure
282
+ @requests_in_flight -= 1
283
+ end
284
+
285
+ @successive_error_count = 0
286
+ num_reqs += 1
287
+ debug_logger.info("Request successful: #{resp.code}") if debug_logger
288
+ end
289
+ end
290
+
247
291
  def authorization_payload
248
292
  @authorization_payload ||= "Basic #{Base64.urlsafe_encode64(@api_key).chomp}"
249
293
  end
@@ -71,6 +71,10 @@ module Timber
71
71
  Util::Hash.deep_compact(hash)
72
72
  end
73
73
 
74
+ def inspect
75
+ to_s
76
+ end
77
+
74
78
  def to_json(options = {})
75
79
  as_json(options).to_json
76
80
  end
@@ -79,6 +83,26 @@ module Timber
79
83
  as_json.to_msgpack(*args)
80
84
  end
81
85
 
86
+ # This is used when LogEntry objects make it to a non-Timber logger.
87
+ def to_s
88
+ log_message = message
89
+
90
+ if !event.nil?
91
+ event_hash = event.as_json
92
+ event_type = event_hash.keys.first
93
+
94
+ event_type = if event.is_a?(Events::Custom)
95
+ "event:#{event_type}.#{event.type}"
96
+ else
97
+ "event:#{event_type}"
98
+ end
99
+
100
+ log_message = "#{message} [#{event_type}]"
101
+ end
102
+
103
+ log_message + "\n"
104
+ end
105
+
82
106
  private
83
107
  def formatted_dt
84
108
  @formatted_dt ||= time.iso8601(DT_PRECISION)
data/lib/timber/logger.rb CHANGED
@@ -115,7 +115,8 @@ module Timber
115
115
 
116
116
  # This method is invoked when a log event occurs
117
117
  def call(severity, timestamp, progname, msg)
118
- "#{String === msg ? msg : msg.inspect}\n"
118
+ log_entry = build_log_entry(severity, timestamp, progname, msg)
119
+ log_entry.to_s
119
120
  end
120
121
  end
121
122
 
@@ -197,7 +198,7 @@ module Timber
197
198
 
198
199
  self.level = environment_level
199
200
 
200
- after_initialize if respond_to? :after_initialize
201
+ after_initialize if respond_to?(:after_initialize)
201
202
 
202
203
  @initialized = true
203
204
  end
@@ -1,3 +1,3 @@
1
1
  module Timber
2
- VERSION = "2.0.20"
2
+ VERSION = "2.0.21"
3
3
  end
@@ -46,7 +46,12 @@ if defined?(::Rails)
46
46
  #
47
47
  # You can see here that they use simple class attribute, hence the reason we need
48
48
  # to update all of them: https://github.com/rails/rails/blob/700ec897f97c60016ad748236bf3a49ef15a20de/actionview/lib/action_view/base.rb#L157
49
- Timber::Frameworks::Rails.set_logger(logger)
49
+ ::ActionCable::Server::Base.logger = logger if defined?(::ActionCable::Server::Base) && ::ActionCable::Server::Base.respond_to?(:logger=)
50
+ ::ActionController::Base.logger = logger if defined?(::ActionController::Base) && ::ActionController::Base.respond_to?(:logger=)
51
+ ::ActionMailer::Base.logger = logger if defined?(::ActionMailer::Base) && ::ActionMailer::Base.respond_to?(:logger=)
52
+ ::ActionView::Base.logger = logger if defined?(::ActionView::Base) && ::ActionView::Base.respond_to?(:logger=)
53
+ ::ActiveRecord::Base.logger = logger if defined?(::ActiveRecord::Base) && ::ActiveRecord::Base.respond_to?(:logger=)
54
+ ::Rails.logger = logger
50
55
 
51
56
  yield
52
57
 
@@ -1,5 +1,4 @@
1
1
  require "timber"
2
2
 
3
3
  config = Timber::Config.instance
4
- config.append_metadata = true
5
- config.debug_logger = ::Logger.new(STDOUT)
4
+ config.append_metadata = true
@@ -11,7 +11,7 @@ describe Timber::LogDevices::HTTP do
11
11
  # Ensure that threads have not started
12
12
  thread = http.instance_variable_get(:@flush_thread)
13
13
  expect(thread).to be_nil
14
- thread = http.instance_variable_get(:@outlet_thread)
14
+ thread = http.instance_variable_get(:@request_outlet_thread)
15
15
  expect(thread).to be_nil
16
16
  end
17
17
  end
@@ -23,6 +23,7 @@ describe Timber::LogDevices::HTTP do
23
23
  it "should buffer the messages" do
24
24
  http.write("test log message")
25
25
  expect(msg_queue.flush).to eq(["test log message"])
26
+ http.close
26
27
  end
27
28
 
28
29
  it "should start the flush threads" do
@@ -30,8 +31,10 @@ describe Timber::LogDevices::HTTP do
30
31
 
31
32
  thread = http.instance_variable_get(:@flush_thread)
32
33
  expect(thread).to be_alive
33
- thread = http.instance_variable_get(:@outlet_thread)
34
+ thread = http.instance_variable_get(:@request_outlet_thread)
34
35
  expect(thread).to be_alive
36
+ expect(http).to receive(:flush).exactly(1).times
37
+ http.close
35
38
  end
36
39
 
37
40
  context "with a low batch size" do
@@ -41,6 +44,8 @@ describe Timber::LogDevices::HTTP do
41
44
  http.write("test")
42
45
  expect(http).to receive(:flush).exactly(1).times
43
46
  http.write("my log message")
47
+ expect(http).to receive(:flush).exactly(1).times
48
+ http.close
44
49
  end
45
50
  end
46
51
  end
@@ -54,7 +59,7 @@ describe Timber::LogDevices::HTTP do
54
59
  thread = http.instance_variable_get(:@flush_thread)
55
60
  sleep 0.1 # too fast!
56
61
  expect(thread).to_not be_alive
57
- thread = http.instance_variable_get(:@outlet_thread)
62
+ thread = http.instance_variable_get(:@request_outlet_thread)
58
63
  sleep 0.1 # too fast!
59
64
  expect(thread).to_not be_alive
60
65
  end
@@ -86,13 +91,6 @@ describe Timber::LogDevices::HTTP do
86
91
  message_queue = http.instance_variable_get(:@msg_queue)
87
92
  expect(message_queue.size).to eq(0)
88
93
  end
89
-
90
- it "should preserve formatting for mshpack payloads" do
91
- http = described_class.new("MYKEY", flush_continuously: false)
92
- http.write("This is a log message 1".to_msgpack)
93
- http.write("This is a log message 2".to_msgpack)
94
- http.send(:flush)
95
- end
96
94
  end
97
95
 
98
96
  # Testing a private method because it helps break down our tests
@@ -100,18 +98,17 @@ describe Timber::LogDevices::HTTP do
100
98
  it "should start a intervaled flush thread and flush on an interval" do
101
99
  http = described_class.new("MYKEY", flush_interval: 0.1)
102
100
  http.send(:ensure_flush_threads_are_started)
103
- expect(http).to receive(:flush).exactly(1).times
104
- sleep 0.12 # too fast!
105
- expect(http).to receive(:flush).exactly(1).times
106
- sleep 0.12 # too fast!
101
+ expect(http).to receive(:flush).exactly(2).times
102
+ sleep 0.15 # too fast!
103
+ http.close
107
104
  end
108
105
  end
109
106
 
110
107
  # Outlet
111
- describe "#outlet" do
108
+ describe "#request_outlet" do
112
109
  let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
113
110
 
114
- it "should start a intervaled flush thread and flush on an interval" do
111
+ it "should deliver requests on an interval" do
115
112
  stub = stub_request(:post, "https://logs.timber.io/frames").
116
113
  with(
117
114
  :body => start_with("\x92\x85\xA5level\xA4INFO\xA2dt\xBB2016-09-01T12:00:00.000000Z\xA7message\xB2test log message 1\xA7context\x81\xA6system".force_encoding("ASCII-8BIT")),
@@ -124,13 +121,37 @@ describe Timber::LogDevices::HTTP do
124
121
  to_return(:status => 200, :body => "", :headers => {})
125
122
 
126
123
  http = described_class.new("MYKEY", flush_interval: 0.1)
127
- log_entry = Timber::LogEntry.new("INFO", time, nil, "test log message 1", nil, nil)
128
- http.write(log_entry)
129
- log_entry = Timber::LogEntry.new("INFO", time, nil, "test log message 2", nil, nil)
130
- http.write(log_entry)
131
- sleep 0.3
124
+ log_entry1 = Timber::LogEntry.new("INFO", time, nil, "test log message 1", nil, nil)
125
+ http.write(log_entry1)
126
+ log_entry2 = Timber::LogEntry.new("INFO", time, nil, "test log message 2", nil, nil)
127
+ http.write(log_entry2)
128
+ sleep 1
132
129
 
133
130
  expect(stub).to have_been_requested.times(1)
131
+
132
+ http.close
133
+ end
134
+ end
135
+
136
+ describe "#deliver_requests" do
137
+ it "should handle exceptions properly and return" do
138
+ allow_any_instance_of(Net::HTTP).to receive(:request).and_raise("boom")
139
+
140
+ http_device = described_class.new("MYKEY", flush_continuously: false)
141
+ req_queue = http_device.instance_variable_get(:@request_queue)
142
+
143
+ # Place a request on the queue
144
+ req = Net::HTTP::Post.new("/")
145
+ req_queue.enq(req)
146
+
147
+ # Start a HTTP connection to test the method directly
148
+ http = http_device.send(:build_http)
149
+ http.start do |conn|
150
+ result = http_device.send(:deliver_requests, conn)
151
+ expect(result).to eq(false)
152
+ end
153
+
154
+ expect(req_queue.size).to eq(1)
134
155
  end
135
156
  end
136
157
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timber
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.20
4
+ version: 2.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timber Technologies, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-19 00:00:00.000000000 Z
11
+ date: 2017-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -199,7 +199,6 @@ files:
199
199
  - lib/timber/log_devices/http.rb
200
200
  - lib/timber/log_entry.rb
201
201
  - lib/timber/logger.rb
202
- - lib/timber/logger/metadata_methods.rb
203
202
  - lib/timber/overrides.rb
204
203
  - lib/timber/overrides/lograge.rb
205
204
  - lib/timber/overrides/rails_stdout_logging.rb
@@ -264,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
263
  version: '0'
265
264
  requirements: []
266
265
  rubyforge_project:
267
- rubygems_version: 2.5.2
266
+ rubygems_version: 2.4.5.2
268
267
  signing_key:
269
268
  specification_version: 4
270
269
  summary: Log Better. Solve Problems Faster. https://timber.io
@@ -1 +0,0 @@
1
- metadata_methods.rb