td-logger 0.3.27 → 0.4.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 +5 -5
- data/ChangeLog +12 -0
- data/SECURITY.md +7 -0
- data/VERSION +1 -1
- data/lib/td/logger/agent/rails/config.rb +2 -2
- data/lib/td/logger/agent/rails/yaml.rb +8 -0
- data/lib/td/logger/td_logger.rb +1 -0
- data/lib/td/logger/version.rb +1 -1
- metadata +53 -38
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -4
- data/.travis.yml +0 -29
- data/Gemfile +0 -3
- data/Rakefile +0 -13
- data/appveyor.yml +0 -17
- data/spec/spec_helper.rb +0 -29
- data/spec/td/logger/agent/config_spec.rb +0 -260
- data/spec/td/logger/agent/rack_spec.rb +0 -37
- data/spec/td/logger/agent/rails_spec.rb +0 -155
- data/spec/td/logger/event_spec.rb +0 -136
- data/spec/td/logger/treasure_data_logger_spec.rb +0 -669
- data/spec/td/logger_spec.rb +0 -128
- data/td-logger.gemspec +0 -45
@@ -1,669 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe TreasureData::Logger::TreasureDataLogger do
|
5
|
-
context 'init' do
|
6
|
-
it 'with apikey' do
|
7
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_1')
|
8
|
-
expect(td.instance_variable_get(:@client).api.apikey).to eq('test_1')
|
9
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@ssl)).to eq(true)
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'with apikey and use_ssl' do
|
13
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_1', :use_ssl => true)
|
14
|
-
expect(td.instance_variable_get(:@client).api.apikey).to eq('test_1')
|
15
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@ssl)).to eq(true)
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'with apikey and ssl' do
|
19
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_1', :ssl => true)
|
20
|
-
expect(td.instance_variable_get(:@client).api.apikey).to eq('test_1')
|
21
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@ssl)).to eq(true)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'with apikey and HTTP endpoint' do
|
25
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_1', :endpoint => "http://idontexi.st")
|
26
|
-
expect(td.instance_variable_get(:@client).api.apikey).to eq('test_1')
|
27
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@host)).to eq("idontexi.st")
|
28
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@port)).to eq(80)
|
29
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@ssl)).to eq(false)
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'with apikey and HTTPS endpoint' do
|
33
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_1', :endpoint => "https://idontexi.st")
|
34
|
-
expect(td.instance_variable_get(:@client).api.apikey).to eq('test_1')
|
35
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@host)).to eq("idontexi.st")
|
36
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@port)).to eq(443)
|
37
|
-
expect(td.instance_variable_get(:@client).api.instance_variable_get(:@ssl)).to eq(true)
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'db config' do
|
41
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_1')
|
42
|
-
time = Time.now
|
43
|
-
expect(td).to receive(:add).with('db1', 'table1', {:foo => :bar, :time => time.to_i})
|
44
|
-
td.post_with_time('table1', {:foo => :bar}, time)
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'fluent-logger-td compat' do
|
48
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_2')
|
49
|
-
time = Time.now
|
50
|
-
expect(td).to receive(:add).with('overwrite', 'table1', {:foo => :bar, :time => time.to_i})
|
51
|
-
td.post_with_time('overwrite.table1', {:foo => :bar}, time)
|
52
|
-
end
|
53
|
-
|
54
|
-
## TODO this causes real upload
|
55
|
-
#it 'success' do
|
56
|
-
# td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_3')
|
57
|
-
# td.post('valid', {}).should == true
|
58
|
-
#end
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'validate' do
|
62
|
-
it 'validate table name' do
|
63
|
-
td = TreasureData::Logger::TreasureDataLogger.new('db1', :apikey => 'test_4')
|
64
|
-
expect {
|
65
|
-
td.post('invalid-name', {})
|
66
|
-
}.to raise_error(RuntimeError)
|
67
|
-
expect {
|
68
|
-
td.post('', {})
|
69
|
-
}.to raise_error(RuntimeError)
|
70
|
-
expect {
|
71
|
-
td.post('9', {})
|
72
|
-
}.to raise_error(RuntimeError)
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'validate database name' do
|
76
|
-
td = TreasureData::Logger::TreasureDataLogger.new('invalid-db-name', :apikey => 'test_5')
|
77
|
-
expect {
|
78
|
-
td.post('table', {})
|
79
|
-
}.to raise_error(RuntimeError)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
it "raise error if `apikey` option is missing" do
|
84
|
-
expect{ described_class.new("dummy-tag", {}) }.to raise_error(ArgumentError)
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "#logger" do
|
88
|
-
let(:tag_prefix) { "dummy" }
|
89
|
-
|
90
|
-
subject { described_class.new(tag_prefix, {apikey: "dummy"}.merge(options)).logger }
|
91
|
-
|
92
|
-
context "`debug` option given" do
|
93
|
-
let(:options) { {debug: true} }
|
94
|
-
|
95
|
-
it { expect(subject.level).to eq ::Logger::DEBUG }
|
96
|
-
end
|
97
|
-
|
98
|
-
context "not `debug` option given" do
|
99
|
-
let(:options) { {} }
|
100
|
-
|
101
|
-
it { expect(subject.level).to eq ::Logger::INFO }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
describe "#post_with_time" do
|
106
|
-
let(:td) { described_class.new(prefix, {apikey: 'test_1'}.merge(options)) }
|
107
|
-
let(:tag) { "foo.bar" }
|
108
|
-
let(:time) { Time.now }
|
109
|
-
let(:prefix) { "dummy" }
|
110
|
-
let(:record) { {greeting: "hello", time: 1234567890} }
|
111
|
-
let(:options) { {} }
|
112
|
-
|
113
|
-
subject { td.post_with_time(tag, record, time) }
|
114
|
-
|
115
|
-
describe "db and table" do
|
116
|
-
context "no `tag_prefix` option given" do
|
117
|
-
let(:prefix) { "" }
|
118
|
-
|
119
|
-
it "`db` and `table` determine with tag" do
|
120
|
-
db, table = tag.split(".")[-2, 2]
|
121
|
-
allow(td).to receive(:add).with(db, table, record)
|
122
|
-
subject
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
context "`tag_prefix` option given" do
|
127
|
-
let(:prefix) { "prefix" }
|
128
|
-
|
129
|
-
it "`db` and `table` determine with tag and tag_prefix" do
|
130
|
-
db, table = "#{prefix}.#{tag}".split(".")[-2, 2]
|
131
|
-
allow(td).to receive(:add).with(db, table, record)
|
132
|
-
subject
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
describe "inject time to record" do
|
138
|
-
context "record has no `:time` key" do
|
139
|
-
let(:record) { {greeting: "hello"} }
|
140
|
-
|
141
|
-
it "fill-in :time key with `time` argument" do
|
142
|
-
allow(td).to receive(:add).with(anything, anything, record.merge(time: time.to_i))
|
143
|
-
subject
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context "record has `:time` key" do
|
148
|
-
let(:record) { {greeting: "hello", time: 1234567890 } }
|
149
|
-
|
150
|
-
it do
|
151
|
-
allow(td).to receive(:add).with(anything, anything, record)
|
152
|
-
subject
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
describe "#add" do
|
159
|
-
let(:td) { described_class.new(prefix, {apikey: 'test_1'}) }
|
160
|
-
let(:prefix) { "prefix" }
|
161
|
-
let(:db) { "database" }
|
162
|
-
let(:table) { "table" }
|
163
|
-
let(:valid_message) { {"foo" => "FOO", "bar" => "BAR"} }
|
164
|
-
|
165
|
-
before do
|
166
|
-
# don't try to upload data causing by `at_exit { close }` that registered at TreasureDataLogger#initialize
|
167
|
-
# this hack causes "zlib(finalizer): Zlib::GzipWriter object must be closed explicitly." warning, but ignoreable for our tests..
|
168
|
-
allow_any_instance_of(TreasureData::Logger::TreasureDataLogger).to receive(:at_exit).and_return(true)
|
169
|
-
end
|
170
|
-
|
171
|
-
subject { td.send(:add, db, table, message) } # NOTE: `add` is private method
|
172
|
-
|
173
|
-
describe "message type" do
|
174
|
-
shared_examples_for "should fail `add` because not a hash" do
|
175
|
-
it { is_expected.to eq false }
|
176
|
-
it "logging error" do
|
177
|
-
expect(td.logger).to receive(:error).with(/TreasureDataLogger: record must be a Hash:/)
|
178
|
-
subject
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
context "string" do
|
183
|
-
let(:message) { "string" }
|
184
|
-
it_behaves_like "should fail `add` because not a hash"
|
185
|
-
end
|
186
|
-
|
187
|
-
context "array" do
|
188
|
-
let(:message) { ["hello"] }
|
189
|
-
it_behaves_like "should fail `add` because not a hash"
|
190
|
-
end
|
191
|
-
|
192
|
-
context "fixnum" do
|
193
|
-
let(:message) { 42 }
|
194
|
-
it_behaves_like "should fail `add` because not a hash"
|
195
|
-
end
|
196
|
-
|
197
|
-
context "hash" do
|
198
|
-
let(:message) { {foo: 42} }
|
199
|
-
|
200
|
-
it { is_expected.to eq true }
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
describe "queue is full" do
|
205
|
-
let(:queue) { td.instance_variable_get(:@queue) }
|
206
|
-
let(:max) { td.instance_variable_get(:@queue_limit) }
|
207
|
-
let(:message) { valid_message }
|
208
|
-
|
209
|
-
before do
|
210
|
-
(max + 1).times { queue << [db, table, {"foo" => "bar"}.to_msgpack] }
|
211
|
-
end
|
212
|
-
|
213
|
-
it { is_expected.to eq false }
|
214
|
-
it do
|
215
|
-
expect(td.logger).to receive(:error).with(/TreasureDataLogger: queue length exceeds limit. can't add new event log:/)
|
216
|
-
subject
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "if `to_msgpack` failed" do
|
221
|
-
let(:message) { valid_message }
|
222
|
-
|
223
|
-
before { allow(td).to receive(:to_msgpack) { raise "something error" } }
|
224
|
-
|
225
|
-
it { is_expected.to eq false }
|
226
|
-
it do
|
227
|
-
expect(td.logger).to receive(:error).with(/TreasureDataLogger: Can't convert to msgpack:/)
|
228
|
-
subject
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
describe "buffer size/cardinality check" do
|
233
|
-
let(:max) { TreasureData::Logger::TreasureDataLogger::MAX_KEY_CARDINALITY }
|
234
|
-
let(:warn) { TreasureData::Logger::TreasureDataLogger::WARN_KEY_CARDINALITY }
|
235
|
-
let(:map_key) { [db, table] }
|
236
|
-
let(:record_keys) { max.times }
|
237
|
-
let(:message) { record_keys.inject({}){|r, n| r[n] = n; r } }
|
238
|
-
|
239
|
-
context "buffer size == MAX_KEY_CARDINALITY" do
|
240
|
-
it { is_expected.to eq true }
|
241
|
-
end
|
242
|
-
|
243
|
-
context "buffer size > MAX_KEY_CARDINALITY" do
|
244
|
-
let(:record_keys) { (max + 1).times }
|
245
|
-
|
246
|
-
it { is_expected.to eq false }
|
247
|
-
it do
|
248
|
-
expect(td.logger).to receive(:error).with(/TreasureDataLogger: kind of keys in a buffer exceeds/)
|
249
|
-
expect(td.instance_variable_get(:@map)).to receive(:delete).with(map_key)
|
250
|
-
subject
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
context "before <= WARN && WARN < after" do
|
255
|
-
let(:record_keys) { (warn + 1).times } # just one key
|
256
|
-
|
257
|
-
it do
|
258
|
-
expect(td.logger).to receive(:warn).with("TreasureDataLogger: kind of keys in a buffer exceeds #{warn} which is too large. please check the schema design.")
|
259
|
-
subject
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
context "buffer.size > @chunk_limit" do
|
264
|
-
let(:chunk_limit) { 0 }
|
265
|
-
|
266
|
-
before { td.instance_variable_set(:@chunk_limit, chunk_limit) }
|
267
|
-
|
268
|
-
it do
|
269
|
-
expect(td.instance_variable_get(:@queue)).to receive(:<<).with([db, table, anything])
|
270
|
-
expect(td.instance_variable_get(:@map)).to receive(:delete).with(map_key)
|
271
|
-
expect(td.instance_variable_get(:@cond)).to receive(:signal)
|
272
|
-
subject
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
describe "#to_msgpack" do
|
279
|
-
let(:td) { described_class.new("prefix", {apikey: 'test_1'}) }
|
280
|
-
|
281
|
-
subject { td.send(:to_msgpack, target) }
|
282
|
-
|
283
|
-
shared_examples_for "original to_msgpack only invoked" do
|
284
|
-
after { subject }
|
285
|
-
|
286
|
-
it { expect(target).to receive(:to_msgpack) }
|
287
|
-
it { expect(JSON).to_not receive(:dump) }
|
288
|
-
it { expect(JSON).to_not receive(:load) }
|
289
|
-
end
|
290
|
-
|
291
|
-
shared_examples_for "JSON.load/dump then to_msgpack invoke" do
|
292
|
-
after { subject }
|
293
|
-
|
294
|
-
it { expect(JSON).to receive(:dump).with(target) }
|
295
|
-
it { expect(JSON).to receive(:load) }
|
296
|
-
end
|
297
|
-
|
298
|
-
context "have to_msgpack objects" do
|
299
|
-
# see also for official supported objects: https://github.com/msgpack/msgpack-ruby/blob/master/ext/msgpack/core_ext.c
|
300
|
-
context "string" do
|
301
|
-
let(:target) { "foobar" }
|
302
|
-
it_behaves_like "original to_msgpack only invoked"
|
303
|
-
end
|
304
|
-
|
305
|
-
context "array" do
|
306
|
-
let(:target) { [1] }
|
307
|
-
it_behaves_like "original to_msgpack only invoked"
|
308
|
-
end
|
309
|
-
|
310
|
-
context "hash" do
|
311
|
-
let(:target) { {foo: "foo"} }
|
312
|
-
it_behaves_like "original to_msgpack only invoked"
|
313
|
-
end
|
314
|
-
|
315
|
-
context "time" do
|
316
|
-
let(:target) { Time.now }
|
317
|
-
it_behaves_like "original to_msgpack only invoked"
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
context "have not to_msgpack objects" do
|
322
|
-
context "date" do
|
323
|
-
let(:target) { Date.today }
|
324
|
-
it_behaves_like "JSON.load/dump then to_msgpack invoke"
|
325
|
-
end
|
326
|
-
|
327
|
-
context "class" do
|
328
|
-
let(:target) { Class.new }
|
329
|
-
it_behaves_like "JSON.load/dump then to_msgpack invoke"
|
330
|
-
end
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
describe "#upload" do
|
335
|
-
let(:td) { described_class.new(prefix, options) }
|
336
|
-
let(:prefix) { "prefix" }
|
337
|
-
let(:options) { {apikey: "apikey"} }
|
338
|
-
let(:db) { "database" }
|
339
|
-
let(:table) { "table" }
|
340
|
-
let(:message) { {foo: "FOO"} }
|
341
|
-
|
342
|
-
subject { td.send(:upload, db, table, message.to_msgpack) } # NOTE: `upload` is private method
|
343
|
-
|
344
|
-
describe "TreasureDataLogger::Client#import success" do
|
345
|
-
context 'unuse unique_key' do
|
346
|
-
it do
|
347
|
-
expect(td.instance_variable_get(:@client)).to receive(:import).with(db, table, "msgpack.gz", anything, anything, nil)
|
348
|
-
subject
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
context 'use unique_key' do
|
353
|
-
let(:options) { {apikey: "apike", use_unique_key: true} }
|
354
|
-
|
355
|
-
it do
|
356
|
-
expect(td.instance_variable_get(:@client)).to receive(:import).with(db, table, "msgpack.gz", anything, anything, kind_of(String))
|
357
|
-
subject
|
358
|
-
end
|
359
|
-
end
|
360
|
-
end
|
361
|
-
|
362
|
-
describe "TreasureDataLogger::NotFoundError" do
|
363
|
-
let(:client) { td.instance_variable_get(:@client) }
|
364
|
-
|
365
|
-
before do
|
366
|
-
# NOTE: raise "not found" client.import at first called, but second and later call not raise
|
367
|
-
queue = [true]
|
368
|
-
allow(client).to receive(:import){
|
369
|
-
raise TreasureData::NotFoundError, "not found" if queue.shift
|
370
|
-
true
|
371
|
-
}
|
372
|
-
end
|
373
|
-
|
374
|
-
context "auto_create_table options disabled" do
|
375
|
-
let(:options) { {apikey: "apikey", auto_create_table: false} }
|
376
|
-
|
377
|
-
it do
|
378
|
-
expect{ subject }.to raise_error(TreasureData::NotFoundError)
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
|
-
context "auto_create_table options enabled" do
|
383
|
-
let(:options) { {apikey: "apikey", auto_create_table: true} }
|
384
|
-
|
385
|
-
it "try to create table with exists database" do
|
386
|
-
expect(client).to receive(:create_log_table)
|
387
|
-
subject
|
388
|
-
end
|
389
|
-
|
390
|
-
it "try to create table with no exists databae" do
|
391
|
-
queue = [true]
|
392
|
-
allow(client).to receive(:create_log_table){ raise TreasureData::NotFoundError, "not found again" if queue.shift}
|
393
|
-
expect(client).to receive(:create_database)
|
394
|
-
subject
|
395
|
-
end
|
396
|
-
|
397
|
-
it "retry @client.import after create table" do
|
398
|
-
expect(client).to receive(:create_log_table)
|
399
|
-
expect(client).to receive(:import).twice # second call is retry
|
400
|
-
subject
|
401
|
-
end
|
402
|
-
end
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
describe "#flush" do
|
407
|
-
let(:td) { described_class.new("prefix", {apikey: 'test_1'}) }
|
408
|
-
let(:db) { "database" }
|
409
|
-
let(:table) { "table" }
|
410
|
-
|
411
|
-
subject { td.flush }
|
412
|
-
|
413
|
-
before { allow(td).to receive(:try_flush) } # do not call try_flush actually, try_flush test is in other place
|
414
|
-
|
415
|
-
it "lock mutex and release" do
|
416
|
-
expect(td.instance_variable_get(:@mutex)).to receive(:lock)
|
417
|
-
expect(td.instance_variable_get(:@mutex)).to receive(:unlock)
|
418
|
-
subject
|
419
|
-
end
|
420
|
-
|
421
|
-
it "call #try_flush" do
|
422
|
-
expect(td).to receive(:try_flush).with(no_args)
|
423
|
-
subject
|
424
|
-
end
|
425
|
-
|
426
|
-
it "@map to be flushed (enqueue)" do
|
427
|
-
buffer = TreasureData::Logger::TreasureDataLogger::Buffer.new
|
428
|
-
td.instance_variable_set(:@map, {[db, table] => buffer})
|
429
|
-
expect(td.instance_variable_get(:@queue)).to receive(:<<).with([db, table, buffer.flush!])
|
430
|
-
subject
|
431
|
-
end
|
432
|
-
|
433
|
-
it "rescue anything error" do
|
434
|
-
allow(td).to receive(:try_flush){ raise "something error" }
|
435
|
-
expect(td.instance_variable_get(:@logger)).to receive(:error).with(/Unexpected error at flush:/)
|
436
|
-
expect(td.instance_variable_get(:@logger)).to receive(:info).at_least(1) # backtrace
|
437
|
-
expect(td.instance_variable_get(:@mutex)).to_not be_locked
|
438
|
-
subject
|
439
|
-
end
|
440
|
-
end
|
441
|
-
|
442
|
-
describe "#try_flush" do
|
443
|
-
let(:td) { described_class.new("prefix", {apikey: 'test_1'}) }
|
444
|
-
let(:db) { "database" }
|
445
|
-
let(:table) { "table" }
|
446
|
-
|
447
|
-
let(:mutex) { td.instance_variable_get(:@mutex) }
|
448
|
-
let(:queue) { td.instance_variable_get(:@queue) }
|
449
|
-
let(:logger) { td.instance_variable_get(:@logger) }
|
450
|
-
|
451
|
-
let(:buffer) { TreasureData::Logger::TreasureDataLogger::Buffer.new }
|
452
|
-
|
453
|
-
before { allow_any_instance_of(TreasureData::Logger::TreasureDataLogger).to receive(:at_exit).and_return(true) }
|
454
|
-
before { mutex.lock } # try_flush is expected mutex locked that called
|
455
|
-
after { mutex.unlock }
|
456
|
-
|
457
|
-
subject { td.send(:try_flush) }
|
458
|
-
|
459
|
-
describe "force flush small buffers if queue is empty" do
|
460
|
-
|
461
|
-
before { allow(td).to receive(:upload) } # do not call `upload` actually, that method test is in other place
|
462
|
-
before { td.instance_variable_set(:@map, {[db, table] => buffer}) } # dummy data append
|
463
|
-
|
464
|
-
context "queue is empty" do
|
465
|
-
it do
|
466
|
-
expect(queue).to receive(:<<).with([db, table, anything])
|
467
|
-
subject
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
context "queue is not empty" do
|
472
|
-
before { queue << [db, table, buffer.flush!] }
|
473
|
-
|
474
|
-
it do
|
475
|
-
expect(queue).to_not receive(:<<).with([db, table, anything])
|
476
|
-
subject
|
477
|
-
end
|
478
|
-
end
|
479
|
-
end
|
480
|
-
|
481
|
-
context "queue and on-memory buffer are empty" do
|
482
|
-
before { allow(td).to receive(:upload) } # do not call `upload` actually, that method test is in other place
|
483
|
-
|
484
|
-
it "return false" do
|
485
|
-
is_expected.to eq false
|
486
|
-
end
|
487
|
-
|
488
|
-
it "don't call #upload" do
|
489
|
-
expect(td).to_not receive(:upload)
|
490
|
-
subject
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
context "some data having" do
|
495
|
-
describe "queue to upload" do
|
496
|
-
before do
|
497
|
-
times.times do |n|
|
498
|
-
buf = TreasureData::Logger::TreasureDataLogger::Buffer.new
|
499
|
-
buf.append(n)
|
500
|
-
queue << [db, table, buf.flush!]
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
context "100 queue" do
|
505
|
-
let(:times) { 100 }
|
506
|
-
|
507
|
-
it "call upload 100 times" do
|
508
|
-
expect(td).to receive(:upload).exactly(times)
|
509
|
-
subject
|
510
|
-
end
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
describe "upload fail" do
|
515
|
-
before do
|
516
|
-
100.times do |n|
|
517
|
-
buf = TreasureData::Logger::TreasureDataLogger::Buffer.new
|
518
|
-
buf.append(n)
|
519
|
-
queue << [db, table, buf.flush!]
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
# NOTE: @retry_limit is hard coded as 12
|
524
|
-
before do
|
525
|
-
times = error_times.times.to_a
|
526
|
-
allow(td).to receive(:upload){
|
527
|
-
if n = times.shift
|
528
|
-
raise "something error (#{n})"
|
529
|
-
else
|
530
|
-
true
|
531
|
-
end
|
532
|
-
}
|
533
|
-
end
|
534
|
-
|
535
|
-
context "errors 0 times" do
|
536
|
-
let(:error_times) { 0 }
|
537
|
-
|
538
|
-
it { expect(logger).to_not receive(:info); subject }
|
539
|
-
it { expect(logger).to_not receive(:error); subject }
|
540
|
-
end
|
541
|
-
|
542
|
-
context "errors 1 times" do
|
543
|
-
let(:error_times) { 1 }
|
544
|
-
|
545
|
-
it do
|
546
|
-
expect(queue).to_not receive(:clear)
|
547
|
-
subject
|
548
|
-
end
|
549
|
-
|
550
|
-
it do
|
551
|
-
expect(logger).to receive(:error).with(/Failed to upload event logs to Treasure Data, retrying:/)
|
552
|
-
subject
|
553
|
-
end
|
554
|
-
|
555
|
-
it "not trash" do
|
556
|
-
expect(logger).to_not receive(:error).with(/Failed to upload event logs to Treasure Data, trashed:/)
|
557
|
-
subject
|
558
|
-
end
|
559
|
-
|
560
|
-
it "error_count should reset" do
|
561
|
-
expect(td.instance_variable_get(:@error_count)).to eq 0
|
562
|
-
subject
|
563
|
-
end
|
564
|
-
end
|
565
|
-
|
566
|
-
context "errors 20 times" do
|
567
|
-
let(:error_times) { 20 }
|
568
|
-
|
569
|
-
it do
|
570
|
-
skip "try_flush has bug?"
|
571
|
-
expect(queue).to receive(:clear)
|
572
|
-
subject
|
573
|
-
end
|
574
|
-
|
575
|
-
it do
|
576
|
-
skip "try_flush has bug?"
|
577
|
-
expect(logger).to receive(:error).with(/Failed to upload event logs to Treasure Data, retrying:/)
|
578
|
-
expect(logger).to receive(:error).with(/Failed to upload event logs to Treasure Data, trashed:/)
|
579
|
-
subject
|
580
|
-
end
|
581
|
-
|
582
|
-
it do
|
583
|
-
skip "try_flush has bug?"
|
584
|
-
expect(queue).to_not receive(:clear)
|
585
|
-
subject
|
586
|
-
end
|
587
|
-
|
588
|
-
it "output backtrace as INFO level" do
|
589
|
-
skip "try_flush has bug?"
|
590
|
-
expect(logger).to receive(:info).at_least(1) # backtrace
|
591
|
-
subject
|
592
|
-
end
|
593
|
-
|
594
|
-
it "error_count should reset" do
|
595
|
-
skip "try_flush has bug?"
|
596
|
-
expect(td.instance_variable_get(:@error_count)).to eq 0
|
597
|
-
subject
|
598
|
-
end
|
599
|
-
end
|
600
|
-
end
|
601
|
-
end
|
602
|
-
end
|
603
|
-
|
604
|
-
describe "#close" do
|
605
|
-
let(:td) { described_class.new("prefix", {apikey: 'test_1'}) }
|
606
|
-
let(:db) { "database" }
|
607
|
-
let(:table) { "table" }
|
608
|
-
let(:queue) { td.instance_variable_get(:@queue) }
|
609
|
-
let(:logger) { td.instance_variable_get(:@logger) }
|
610
|
-
|
611
|
-
subject { td.close }
|
612
|
-
|
613
|
-
context "queue is empty" do
|
614
|
-
it do
|
615
|
-
expect(td).to_not receive(:upload)
|
616
|
-
subject
|
617
|
-
end
|
618
|
-
end
|
619
|
-
|
620
|
-
context "queue is not empty" do
|
621
|
-
before { queue << [db, table, TreasureData::Logger::TreasureDataLogger::Buffer.new.flush!] }
|
622
|
-
|
623
|
-
context "upload success" do
|
624
|
-
it do
|
625
|
-
expect(td).to receive(:upload)
|
626
|
-
subject
|
627
|
-
end
|
628
|
-
end
|
629
|
-
|
630
|
-
context "upload fail" do
|
631
|
-
it do
|
632
|
-
allow(td).to receive(:upload){ raise "something error"}
|
633
|
-
expect(logger).to receive(:error).with(/Failed to upload event logs to Treasure Data, trashed:/)
|
634
|
-
subject
|
635
|
-
end
|
636
|
-
end
|
637
|
-
end
|
638
|
-
|
639
|
-
context "@map is empty" do
|
640
|
-
it do
|
641
|
-
expect(td).to_not receive(:upload)
|
642
|
-
subject
|
643
|
-
end
|
644
|
-
end
|
645
|
-
|
646
|
-
context "@map is not empty" do
|
647
|
-
before do
|
648
|
-
buffer = TreasureData::Logger::TreasureDataLogger::Buffer.new
|
649
|
-
td.instance_variable_set(:@map, {[db, table] => buffer})
|
650
|
-
end
|
651
|
-
|
652
|
-
context "upload success" do
|
653
|
-
it do
|
654
|
-
expect(td).to receive(:upload)
|
655
|
-
subject
|
656
|
-
end
|
657
|
-
end
|
658
|
-
|
659
|
-
context "upload fail" do
|
660
|
-
it do
|
661
|
-
allow(td).to receive(:upload){ raise "something error" }
|
662
|
-
expect(logger).to receive(:error).with(/Failed to upload event logs to Treasure Data, trashed:/)
|
663
|
-
subject
|
664
|
-
end
|
665
|
-
end
|
666
|
-
end
|
667
|
-
end
|
668
|
-
end
|
669
|
-
|