loga 2.4.0 → 2.5.4

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.
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Loga::Sidekiq do
4
4
  describe '.configure_logging' do
5
- context 'when sidekiq version is 5.1' do
5
+ context 'when sidekiq is defined' do
6
6
  it 'gets invoked on Loga.configure' do
7
7
  allow(described_class).to receive(:configure_logging)
8
8
 
@@ -18,7 +18,7 @@ RSpec.describe Loga::Sidekiq do
18
18
  expect(described_class).to have_received(:configure_logging)
19
19
  end
20
20
 
21
- it 'assigns our custom sidekiq job logger' do
21
+ it 'assigns our custom sidekiq job logger depending on the sidekiq version' do
22
22
  Loga.reset
23
23
 
24
24
  Loga.configure(
@@ -28,7 +28,14 @@ RSpec.describe Loga::Sidekiq do
28
28
  format: :gelf,
29
29
  )
30
30
 
31
- expect(::Sidekiq.options[:job_logger]).to eq(Loga::Sidekiq::JobLogger)
31
+ m = ENV['BUNDLE_GEMFILE'].match(/sidekiq(?<version>\d+)/)
32
+
33
+ case m['version']
34
+ when '51'
35
+ expect(::Sidekiq.options[:job_logger]).to eq(Loga::Sidekiq5::JobLogger)
36
+ when '6'
37
+ expect(::Sidekiq.options[:job_logger]).to eq(Loga::Sidekiq6::JobLogger)
38
+ end
32
39
  end
33
40
  end
34
41
 
data/spec/spec_helper.rb CHANGED
@@ -29,14 +29,23 @@ when /sinatra/
29
29
  when /unit/
30
30
  rspec_pattern = 'unit/**/*_spec.rb'
31
31
  require 'loga'
32
- when /sidekiq/
33
- sidekiq_specs = [
34
- 'integration/sidekiq_spec.rb',
35
- 'spec/loga/sidekiq/**/*_spec.rb',
36
- 'spec/loga/sidekiq_spec.rb',
37
- ]
38
-
39
- rspec_pattern = sidekiq_specs.join(',')
32
+ when /sidekiq(?<version>\d+)/
33
+ case $LAST_MATCH_INFO['version']
34
+ when '51'
35
+ rspec_pattern = [
36
+ 'spec/integration/sidekiq5_spec.rb',
37
+ 'spec/loga/sidekiq5/**/*_spec.rb',
38
+ 'spec/loga/sidekiq_spec.rb',
39
+ ].join(',')
40
+ when '6'
41
+ rspec_pattern = [
42
+ 'spec/integration/sidekiq6_spec.rb',
43
+ 'spec/loga/sidekiq6/**/*_spec.rb',
44
+ 'spec/loga/sidekiq_spec.rb',
45
+ ].join(',')
46
+ else
47
+ raise 'FIXME: Unknown sidekiq - update this file.'
48
+ end
40
49
 
41
50
  require 'sidekiq'
42
51
  require 'sidekiq/cli'
@@ -166,6 +166,49 @@ describe Loga::Formatters::GELFFormatter do
166
166
  end
167
167
  end
168
168
 
169
+ context 'when working with sidekiq context' do
170
+ let(:options) { { message: 'Wooden house' } }
171
+ let(:message) { Loga::Event.new(options) }
172
+ let(:sidekiq_context) { { class: 'MyWorker', jid: '123' } }
173
+
174
+ before do
175
+ klass = Class.new do
176
+ class << self
177
+ attr_accessor :current
178
+ end
179
+ end
180
+ klass.current = sidekiq_context
181
+ stub_const('::Sidekiq::Context', klass)
182
+ end
183
+
184
+ it 'includes the ::Sidekiq::Context.current data' do
185
+ expect(json['_class']).to eq('MyWorker')
186
+ expect(json['_jid']).to eq('123')
187
+ end
188
+
189
+ include_examples 'valid GELF message'
190
+
191
+ describe 'overwriting sidekiq context data with manual one' do
192
+ let(:options) { { message: 'Test', data: { class: 'CoolTest' } } }
193
+
194
+ it 'uses the manual data instead of the sidekiq context' do
195
+ expect(json['_class']).to eq('CoolTest')
196
+ end
197
+
198
+ include_examples 'valid GELF message'
199
+ end
200
+
201
+ describe ':elapsed in the sidekiq context' do
202
+ let(:sidekiq_context) { { class: 'MyWorker', jid: '123', elapsed: '22.2' } }
203
+
204
+ it 'transforms it to _duration' do
205
+ expect(json['_duration']).to eq(22.2)
206
+ end
207
+
208
+ include_examples 'valid GELF message'
209
+ end
210
+ end
211
+
169
212
  {
170
213
  'DEBUG' => 7,
171
214
  'INFO' => 6,
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
  require 'rack/test'
3
3
 
4
- # rubocop:disable RSpec/SubjectStub, RSpec/MessageSpies, RSpec/VerifiedDoubles
4
+ # rubocop:disable RSpec/VerifiedDoubles RSpec/MessageSpies
5
5
  describe Loga::Rack::Logger do
6
- subject { described_class.new(app) }
6
+ subject(:middleware) { described_class.new(app) }
7
7
 
8
8
  let(:env) { Rack::MockRequest.env_for('/about_us?limit=1', options) }
9
9
  let(:options) { {} }
@@ -21,18 +21,25 @@ describe Loga::Rack::Logger do
21
21
  )
22
22
  end
23
23
 
24
- before { Loga.instance_variable_set(:@configuration, configuration) }
24
+ let(:started_at) { Time.new(2021, 1, 2, 9, 30, 4.500, '+00:00') }
25
+
26
+ around do |example|
27
+ Timecop.freeze(Time.new(2021, 1, 2, 9, 30, 5.000, '+00:00'), &example)
28
+ end
29
+
30
+ before do
31
+ allow(Loga).to receive(:configuration).and_return(configuration)
32
+ end
25
33
 
26
34
  shared_examples 'logs the event' do |details|
27
35
  let(:level) { details[:level] }
28
36
 
29
- before do
30
- allow(subject).to receive(:started_at).and_return(:timestamp)
31
- allow(subject).to receive(:duration_in_ms).with(any_args).and_return(5)
32
- end
33
-
34
37
  it 'instantiates a Loga::Event' do
35
- expect(Loga::Event).to receive(:new).with(
38
+ allow(Loga::Event).to receive(:new).and_call_original
39
+
40
+ middleware.call(env, started_at)
41
+
42
+ expect(Loga::Event).to have_received(:new).with(
36
43
  data: {
37
44
  request: {
38
45
  'status' => response_status,
@@ -42,21 +49,19 @@ describe Loga::Rack::Logger do
42
49
  'request_id' => nil,
43
50
  'request_ip' => nil,
44
51
  'user_agent' => nil,
45
- 'duration' => 5,
52
+ 'duration' => 500,
46
53
  },
47
54
  },
48
55
  exception: logged_exception,
49
56
  message: %r{^GET \/about_us\?limit=1 #{response_status} in \d+ms$},
50
- timestamp: :timestamp,
57
+ timestamp: started_at,
51
58
  type: 'request',
52
59
  )
53
-
54
- subject.call(env)
55
60
  end
56
61
 
57
62
  it "logs the Loga::Event with severity #{details[:level]}" do
58
63
  allow(logger).to receive(level)
59
- subject.call(env)
64
+ middleware.call(env, started_at)
60
65
  expect(logger).to have_received(level).with(an_instance_of(Loga::Event))
61
66
  end
62
67
  end
@@ -65,12 +70,35 @@ describe Loga::Rack::Logger do
65
70
  let(:exception) { StandardError.new }
66
71
  let(:logged_exception) { nil }
67
72
  let(:response_status) { 200 }
73
+ let(:exception_class) { Class.new(StandardError) }
68
74
 
69
75
  context 'when an exception is raised' do
70
- let(:app) { ->(_env) { raise exception } }
71
-
72
- it 'does not rescue the exception' do
73
- expect { subject.call(env) }.to raise_error(StandardError)
76
+ let(:app) { ->(_env) { raise exception_class } }
77
+ let(:response_status) { 500 }
78
+
79
+ it 'raises error, but still logs an event' do
80
+ allow(Loga::Event).to receive(:new).and_call_original
81
+
82
+ expect { middleware.call(env, started_at) }.to raise_error(exception_class)
83
+
84
+ expect(Loga::Event).to have_received(:new).with(
85
+ data: {
86
+ request: {
87
+ 'status' => response_status,
88
+ 'method' => 'GET',
89
+ 'path' => '/about_us',
90
+ 'params' => { 'limit' => '1' },
91
+ 'request_id' => nil,
92
+ 'request_ip' => nil,
93
+ 'user_agent' => nil,
94
+ 'duration' => 500,
95
+ },
96
+ },
97
+ exception: logged_exception,
98
+ message: %r{^GET \/about_us\?limit=1 #{response_status} in \d+ms$},
99
+ timestamp: started_at,
100
+ type: 'request',
101
+ )
74
102
  end
75
103
  end
76
104
 
@@ -112,28 +140,21 @@ describe Loga::Rack::Logger do
112
140
  end
113
141
 
114
142
  context 'when the logger is tagged' do
115
- let(:logger) { double(:logger, tagged: true) }
116
-
117
- before do
118
- allow(subject).to receive(:call_app).with(any_args).and_return(:response)
119
- allow(subject).to receive(:compute_tags).with(any_args).and_return(:tag)
120
- allow(logger).to receive(:tagged).with('hello') do |&block|
121
- block.call
122
- end
123
- end
143
+ let(:logger) { Loga::TaggedLogging.new(Logger.new('/dev/null')) }
144
+ let(:fake_tag_proc) { double(:proc, call: true) }
145
+
146
+ let(:tags) { [->(request) { fake_tag_proc.call(request) }] }
147
+
148
+ include_examples 'logs the event', level: :info
124
149
 
125
- context 'when tags are present' do
126
- let(:tags) { [:foo] }
150
+ it 'calls the tags and computes them' do
151
+ middleware.call(env)
127
152
 
128
- it 'yields the app with tags' do
129
- allow(logger).to receive(:tagged)
130
- subject.call(env)
131
- expect(logger).to have_received(:tagged).with(:tag) do |&block|
132
- expect(block.call).to eq(:response)
133
- end
134
- end
153
+ expect(fake_tag_proc)
154
+ .to have_received(:call)
155
+ .with(instance_of(Loga::Rack::Request))
135
156
  end
136
157
  end
137
158
  end
138
159
  end
139
- # rubocop:enable RSpec/SubjectStub, RSpec/MessageSpies, RSpec/VerifiedDoubles
160
+ # rubocop:enable RSpec/VerifiedDoubles RSpec/MessageSpies
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loga
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Funding Circle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-09 00:00:00.000000000 Z
11
+ date: 2021-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -56,14 +56,14 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.6'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.6'
69
69
  - !ruby/object:Gem::Dependency
@@ -259,7 +259,9 @@ files:
259
259
  - gemfiles/rails42.gemfile
260
260
  - gemfiles/rails50.gemfile
261
261
  - gemfiles/rails52.gemfile
262
+ - gemfiles/rails60.gemfile
262
263
  - gemfiles/sidekiq51.gemfile
264
+ - gemfiles/sidekiq6.gemfile
263
265
  - gemfiles/sinatra14.gemfile
264
266
  - gemfiles/unit.gemfile
265
267
  - lib/loga.rb
@@ -279,7 +281,8 @@ files:
279
281
  - lib/loga/railtie.rb
280
282
  - lib/loga/service_version_strategies.rb
281
283
  - lib/loga/sidekiq.rb
282
- - lib/loga/sidekiq/job_logger.rb
284
+ - lib/loga/sidekiq5/job_logger.rb
285
+ - lib/loga/sidekiq6/job_logger.rb
283
286
  - lib/loga/tagged_logging.rb
284
287
  - lib/loga/utilities.rb
285
288
  - lib/loga/version.rb
@@ -290,13 +293,16 @@ files:
290
293
  - spec/fixtures/rails42.rb
291
294
  - spec/fixtures/rails50.rb
292
295
  - spec/fixtures/rails52.rb
296
+ - spec/fixtures/rails60.rb
293
297
  - spec/fixtures/random_bin
294
298
  - spec/integration/rails/action_mailer_spec.rb
295
299
  - spec/integration/rails/railtie_spec.rb
296
300
  - spec/integration/rails/request_spec.rb
297
- - spec/integration/sidekiq_spec.rb
301
+ - spec/integration/sidekiq5_spec.rb
302
+ - spec/integration/sidekiq6_spec.rb
298
303
  - spec/integration/sinatra_spec.rb
299
- - spec/loga/sidekiq/job_logger_spec.rb
304
+ - spec/loga/sidekiq5/job_logger_spec.rb
305
+ - spec/loga/sidekiq6/job_logger_spec.rb
300
306
  - spec/loga/sidekiq_spec.rb
301
307
  - spec/spec_helper.rb
302
308
  - spec/support/gethostname_shared.rb
@@ -345,13 +351,16 @@ test_files:
345
351
  - spec/fixtures/rails42.rb
346
352
  - spec/fixtures/rails50.rb
347
353
  - spec/fixtures/rails52.rb
354
+ - spec/fixtures/rails60.rb
348
355
  - spec/fixtures/random_bin
349
356
  - spec/integration/rails/action_mailer_spec.rb
350
357
  - spec/integration/rails/railtie_spec.rb
351
358
  - spec/integration/rails/request_spec.rb
352
- - spec/integration/sidekiq_spec.rb
359
+ - spec/integration/sidekiq5_spec.rb
360
+ - spec/integration/sidekiq6_spec.rb
353
361
  - spec/integration/sinatra_spec.rb
354
- - spec/loga/sidekiq/job_logger_spec.rb
362
+ - spec/loga/sidekiq5/job_logger_spec.rb
363
+ - spec/loga/sidekiq6/job_logger_spec.rb
355
364
  - spec/loga/sidekiq_spec.rb
356
365
  - spec/spec_helper.rb
357
366
  - spec/support/gethostname_shared.rb
@@ -1,147 +0,0 @@
1
- require 'spec_helper'
2
- require 'timecop'
3
- require 'fakeredis'
4
-
5
- dummy_redis_config = ConnectionPool.new(size: 5) { Redis.new }
6
-
7
- Sidekiq.configure_client do |config|
8
- config.redis = dummy_redis_config
9
- end
10
-
11
- Sidekiq.configure_server do |config|
12
- config.redis = dummy_redis_config
13
- end
14
-
15
- class MySidekiqWorker
16
- include Sidekiq::Worker
17
-
18
- def perform(_name); end
19
- end
20
-
21
- describe 'Sidekiq client logger' do
22
- let(:target) { StringIO.new }
23
-
24
- def read_json_log(line:)
25
- target.rewind
26
- JSON.parse(target.each_line.drop(line - 1).first)
27
- end
28
-
29
- before do
30
- Redis.current.flushall
31
-
32
- Loga.reset
33
-
34
- Loga.configure(
35
- service_name: 'hello_world_app',
36
- service_version: '1.0',
37
- device: target,
38
- format: :gelf,
39
- )
40
- end
41
-
42
- it 'has the proper job logger' do
43
- job_logger = Loga::Sidekiq::JobLogger
44
-
45
- expect(Sidekiq.options[:job_logger]).to eq job_logger
46
- end
47
-
48
- it 'has the proper logger Sidekiq::Logging.logger' do
49
- expect(Sidekiq::Logging.logger).to eq Loga.logger
50
- end
51
-
52
- it 'has the proper logger for Sidekiq.logger' do
53
- expect(Sidekiq.logger).to eq Loga.logger
54
- end
55
-
56
- it 'pushes a new element in the default queue' do
57
- MySidekiqWorker.perform_async('Bob')
58
-
59
- last_element = JSON.parse(Redis.current.lpop('queue:default'))
60
-
61
- aggregate_failures do
62
- expect(last_element['class']).to eq 'MySidekiqWorker'
63
- expect(last_element['args']).to eq ['Bob']
64
- expect(last_element['retry']).to eq true
65
- expect(last_element['queue']).to eq 'default'
66
- end
67
- end
68
-
69
- if ENV['BUNDLE_GEMFILE'] =~ /sidekiq51/
70
- # https://github.com/mperham/sidekiq/blob/97363210b47a4f8a1d8c1233aaa059d6643f5040/test/test_actors.rb#L57-L79
71
- let(:mgr) do
72
- Class.new do
73
- attr_reader :latest_error, :mutex, :cond
74
-
75
- def initialize
76
- @mutex = ::Mutex.new
77
- @cond = ::ConditionVariable.new
78
- end
79
-
80
- def processor_died(_inst, err)
81
- @latest_error = err
82
-
83
- @mutex.synchronize { @cond.signal }
84
- end
85
-
86
- def processor_stopped(_inst)
87
- @mutex.synchronize { @cond.signal }
88
- end
89
-
90
- def options
91
- {
92
- concurrency: 3,
93
- queues: ['default'],
94
- job_logger: Loga::Sidekiq::JobLogger,
95
- }
96
- end
97
- end
98
- end
99
-
100
- it 'logs the job processing event' do
101
- MySidekiqWorker.perform_async('Bob')
102
-
103
- require 'sidekiq/processor'
104
- Sidekiq::Processor.new(mgr.new).start
105
- sleep 0.5
106
-
107
- expected_attributes = {
108
- '_queue'=> 'default',
109
- '_retry'=> true,
110
- '_params'=> ['Bob'],
111
- '_class'=> 'MySidekiqWorker',
112
- '_type'=> 'sidekiq',
113
- '_service.name'=> 'hello_world_app',
114
- '_service.version'=> '1.0',
115
- '_tags'=> '',
116
- 'level'=> 6,
117
- 'version'=> '1.1',
118
- }
119
-
120
- json_line = read_json_log(line: 1)
121
-
122
- aggregate_failures do
123
- expect(json_line).to include(expected_attributes)
124
-
125
- %w[_created_at _enqueued_at _jid _duration timestamp host].each do |key|
126
- expect(json_line).to have_key(key)
127
- end
128
-
129
- expect(json_line['short_message']).to match(/MySidekiqWorker with jid:*/)
130
- end
131
-
132
- # This was a bug - the duration was constantly incresing based on when
133
- # the logger was created. https://github.com/FundingCircle/loga/pull/117
134
- #
135
- # Test that after sleeping for few seconds the duration is still under 500ms
136
- sleep 1
137
-
138
- MySidekiqWorker.perform_async('Bob')
139
-
140
- sleep 1
141
-
142
- json_line = read_json_log(line: 2)
143
-
144
- expect(json_line['_duration']).to be < 500
145
- end
146
- end
147
- end