timber 2.0.19 → 2.0.20

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: 2e4d4e220779ebe8ea442c98c2f03f36cf12f438
4
- data.tar.gz: e995c553745a8839d306eea480d359063a779b9c
3
+ metadata.gz: 946dc64576210d225bbf4952fa78363705b3b87f
4
+ data.tar.gz: e972b58acf8efc60ebcc79746939d7bbceeadd06
5
5
  SHA512:
6
- metadata.gz: ca96f8e714fef59f4a14155b0376094928171636f2ca4cbb372ef928112d5e4c9c1f4be40c2cb856f94568d4139066e95d4544380fa043540c831a138f06a5d0
7
- data.tar.gz: 41e76ccddb69c9961330560d78c9d82d941e2af0ad91e6e506ae99628147ea3ff96f43c9979299fdaa84b3638adaf88512e1e1532f11c7b33aae8a5287853031
6
+ metadata.gz: f44fdf7da119df5a80cd1cb589f1c55d8fee39bfccd6cacf35eaf9b5944afdc227cb6d715473c651d3830035915bc62df11cae4c7c58a779331870fa23659d26
7
+ data.tar.gz: 7cad85ce7ea3c9df75fd2d3fc7e18df07d42d20f294bba6af8803dce710f7b9a7e0a8990ef243d3feff942807625ffb8b40bc2ecde89c98e2604a7e129c94533
@@ -1,3 +1,6 @@
1
+ require "base64"
2
+ require "net/https"
3
+
1
4
  module Timber
2
5
  module LogDevices
3
6
  # A highly efficient log device that buffers and delivers log messages over HTTPS to
@@ -80,6 +83,10 @@ module Timber
80
83
  # each HTTP payload. If the queue exceeds this limit an HTTP request will be issued. Bigger
81
84
  # payloads mean higher throughput, but also use more memory. Timber will not accept
82
85
  # payloads larger than 1mb.
86
+ # @option attributes [Symbol] :flush_continuously (true) This should only be disabled under
87
+ # special circumstsances (like test suites). Setting this to `false` disables the
88
+ # continuous flushing of log message. As a result, flushing must be handled externally
89
+ # via the #flush method.
83
90
  # @option attributes [Symbol] :flush_interval (1) How often the client should
84
91
  # attempt to deliver logs to the Timber API in fractional seconds. The HTTP client buffers
85
92
  # logs and this options represents how often that will happen, assuming `:batch_byte_size`
@@ -106,22 +113,25 @@ module Timber
106
113
  @api_key = api_key || raise(ArgumentError.new("The api_key parameter cannot be blank"))
107
114
  @timber_url = URI.parse(options[:timber_url] || ENV['TIMBER_URL'] || TIMBER_URL)
108
115
  @batch_size = options[:batch_size] || 1_000
116
+ @flush_continuously = options[:flush_continuously] != false
109
117
  @flush_interval = options[:flush_interval] || 1 # 1 second
110
118
  @requests_per_conn = options[:requests_per_conn] || 2_500
111
119
  @msg_queue = LogMsgQueue.new(@batch_size)
112
120
  @request_queue = options[:request_queue] || SizedQueue.new(3)
113
121
  @requests_in_flight = 0
114
-
115
- if options[:threads] != false
116
- @outlet_thread = Thread.new { outlet }
117
- @flush_thread = Thread.new { intervaled_flush }
118
- end
119
122
  end
120
123
 
121
124
  # Write a new log line message to the buffer, and deliver if the msg exceeds the
122
125
  # payload limit.
123
126
  def write(msg)
124
127
  @msg_queue.enqueue(msg)
128
+
129
+ # Lazily start flush threads to ensure threads are alive after forking processes.
130
+ # If the threads are started during instantiation they will not be copied when
131
+ # the current process is forked. This is the case with various web servers,
132
+ # such as phusion passenger.
133
+ ensure_flush_threads_are_started
134
+
125
135
  if @msg_queue.full?
126
136
  debug_logger.debug("Flushing timber buffer via write") if debug_logger
127
137
  flush
@@ -129,6 +139,19 @@ module Timber
129
139
  true
130
140
  end
131
141
 
142
+ def flush
143
+ @last_flush = Time.now
144
+ msgs = @msg_queue.flush
145
+ return if msgs.empty?
146
+
147
+ req = Net::HTTP::Post.new(@timber_url.path)
148
+ req['Authorization'] = authorization_payload
149
+ req['Content-Type'] = CONTENT_TYPE
150
+ req['User-Agent'] = USER_AGENT
151
+ req.body = msgs.to_msgpack
152
+ @request_queue.enq(req)
153
+ end
154
+
132
155
  # Closes the log device, cleans up, and attempts one last delivery.
133
156
  def close
134
157
  @flush_thread.kill if @flush_thread
@@ -141,17 +164,20 @@ module Timber
141
164
  Timber::Config.instance.debug_logger
142
165
  end
143
166
 
144
- def flush
145
- @last_flush = Time.now
146
- msgs = @msg_queue.flush
147
- return if msgs.empty?
148
-
149
- req = Net::HTTP::Post.new(@timber_url.path)
150
- req['Authorization'] = authorization_payload
151
- req['Content-Type'] = CONTENT_TYPE
152
- req['User-Agent'] = USER_AGENT
153
- req.body = msgs.to_msgpack
154
- @request_queue.enq(req)
167
+ # This is a convenience method to ensure the flush thread are
168
+ # started. This is called lazily from #write so that we
169
+ # only start the threads as needed, but it also ensures
170
+ # threads are started after process forking.
171
+ def ensure_flush_threads_are_started
172
+ if @flush_continuously
173
+ if @outlet_thread.nil? || !@outlet_thread.alive?
174
+ @outlet_thread = Thread.new { outlet }
175
+ end
176
+
177
+ if @flush_thread.nil? || !@flush_thread.alive?
178
+ @flush_thread = Thread.new { intervaled_flush }
179
+ end
180
+ end
155
181
  end
156
182
 
157
183
  def intervaled_flush
@@ -5,7 +5,7 @@ module Timber
5
5
  # `Logger` and the log device that you set it up with.
6
6
  class LogEntry #:nodoc:
7
7
  DT_PRECISION = 6.freeze
8
- SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/2.0.1/schema.json".freeze
8
+ SCHEMA = "https://raw.githubusercontent.com/timberio/log-event-json-schema/v2.0.4/schema.json".freeze
9
9
 
10
10
  attr_reader :context_snapshot, :event, :level, :message, :progname, :tags, :time, :time_ms
11
11
 
@@ -1,3 +1,3 @@
1
1
  module Timber
2
- VERSION = "2.0.19"
2
+ VERSION = "2.0.20"
3
3
  end
@@ -1,13 +1,18 @@
1
1
  require "spec_helper"
2
2
 
3
+ # Note: these tests access instance variables and private methods as a means of
4
+ # not muddying the public API. This object should expose a simple buffer like
5
+ # API, tests should not alter that.
3
6
  describe Timber::LogDevices::HTTP do
4
7
  describe "#initialize" do
5
8
  it "should initialize properly" do
6
9
  http = described_class.new("MYKEY", flush_interval: 0.1)
10
+
11
+ # Ensure that threads have not started
7
12
  thread = http.instance_variable_get(:@flush_thread)
8
- expect(thread).to be_alive
9
- thread = http.instance_variable_get(:@flush_thread)
10
- expect(thread).to be_alive
13
+ expect(thread).to be_nil
14
+ thread = http.instance_variable_get(:@outlet_thread)
15
+ expect(thread).to be_nil
11
16
  end
12
17
  end
13
18
 
@@ -20,6 +25,15 @@ describe Timber::LogDevices::HTTP do
20
25
  expect(msg_queue.flush).to eq(["test log message"])
21
26
  end
22
27
 
28
+ it "should start the flush threads" do
29
+ http.write("test log message")
30
+
31
+ thread = http.instance_variable_get(:@flush_thread)
32
+ expect(thread).to be_alive
33
+ thread = http.instance_variable_get(:@outlet_thread)
34
+ expect(thread).to be_alive
35
+ end
36
+
23
37
  context "with a low batch size" do
24
38
  let(:http) { described_class.new("MYKEY", :batch_size => 2) }
25
39
 
@@ -35,6 +49,7 @@ describe Timber::LogDevices::HTTP do
35
49
  let(:http) { described_class.new("MYKEY") }
36
50
 
37
51
  it "should kill the threads" do
52
+ http.send(:ensure_flush_threads_are_started)
38
53
  http.close
39
54
  thread = http.instance_variable_get(:@flush_thread)
40
55
  sleep 0.1 # too fast!
@@ -57,7 +72,7 @@ describe Timber::LogDevices::HTTP do
57
72
  let(:time) { Time.utc(2016, 9, 1, 12, 0, 0) }
58
73
 
59
74
  it "should add a request to the queue" do
60
- http = described_class.new("MYKEY", threads: false)
75
+ http = described_class.new("MYKEY", flush_continuously: false)
61
76
  log_entry = Timber::LogEntry.new("INFO", time, nil, "test log message 1", nil, nil)
62
77
  http.write(log_entry)
63
78
  log_entry = Timber::LogEntry.new("INFO", time, nil, "test log message 2", nil, nil)
@@ -73,7 +88,7 @@ describe Timber::LogDevices::HTTP do
73
88
  end
74
89
 
75
90
  it "should preserve formatting for mshpack payloads" do
76
- http = described_class.new("MYKEY", threads: false)
91
+ http = described_class.new("MYKEY", flush_continuously: false)
77
92
  http.write("This is a log message 1".to_msgpack)
78
93
  http.write("This is a log message 2".to_msgpack)
79
94
  http.send(:flush)
@@ -84,9 +99,10 @@ describe Timber::LogDevices::HTTP do
84
99
  describe "#intervaled_flush" do
85
100
  it "should start a intervaled flush thread and flush on an interval" do
86
101
  http = described_class.new("MYKEY", flush_interval: 0.1)
102
+ http.send(:ensure_flush_threads_are_started)
87
103
  expect(http).to receive(:flush).exactly(1).times
88
104
  sleep 0.12 # too fast!
89
- mock = expect(http).to receive(:flush).exactly(1).times
105
+ expect(http).to receive(:flush).exactly(1).times
90
106
  sleep 0.12 # too fast!
91
107
  end
92
108
  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.19
4
+ version: 2.0.20
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-15 00:00:00.000000000 Z
11
+ date: 2017-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -264,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
264
  version: '0'
265
265
  requirements: []
266
266
  rubyforge_project:
267
- rubygems_version: 2.6.8
267
+ rubygems_version: 2.5.2
268
268
  signing_key:
269
269
  specification_version: 4
270
270
  summary: Log Better. Solve Problems Faster. https://timber.io