loga 2.5.3 → 2.5.4

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
  SHA256:
3
- metadata.gz: 252a23996e615f29819c4465c083adb286278026baaf2c2d693883bf76560e24
4
- data.tar.gz: c410a1c3442a4f66fd299c456cf62ae7cc21d8beb89ce16ba98460a0b1142b3f
3
+ metadata.gz: b0e5af261daf89f7f7e4b80be296a8f19307a33f187a501e23eb5295fbedd8f2
4
+ data.tar.gz: ed0d0281f4d40078051363434600bdd9a8f843ba70a85fde3b110d56a58e2ca3
5
5
  SHA512:
6
- metadata.gz: bbeb468b6ddd72798c497a8f1f2f0d34acf189e9ada83d4dc6d878461e9d65b19365582deb9a9ce48886379f10e97185c551c228b4a0adc827a3d1d2d686c987
7
- data.tar.gz: f063246243858c1645bfd9b02b50396268c0c3c72ae966d2e070f22cf2dd332635601c66ab4c550680c49eb9faaaafaae0c60e98c71fa249f14de5fd45881eb4
6
+ metadata.gz: 64128d6a8442ce7006629f3056c94487e9316f7c07cd284b3f96f3bb01fd5daccd3a7e4372dfb746376e8e91e2ccb52e015e381bd1c2fdc1774b86e5a5a78f43
7
+ data.tar.gz: bf0393ec37a4f9f8a023d031b5823ad94151fc98b9f1d2ce1ee2bea8b580c88db3013b35b73c68636dfb482dbabd1019771b0b0542ec11c8b2ab0baad290a022
data/CHANGELOG.md CHANGED
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## [2.5.4] - 2021-03-24
8
+ ### Fixed
9
+ - Remove state from Rack middleware, to prevent race conditions where one request would overwrite the state of another
10
+
7
11
  ## [2.5.3] - 2020-10-27
8
12
  ### Fixed
9
13
  - Support for sidekiq 6 - previous versions were causing sidekiq to crash with `Internal exception!`
@@ -5,7 +5,7 @@ source "https://rubygems.org"
5
5
  gem "rails", "~> 6.0.0"
6
6
 
7
7
  group :test do
8
- gem "simplecov"
8
+ gem "simplecov", "~> 0.17.0"
9
9
  end
10
10
 
11
11
  gemspec path: "../"
@@ -5,7 +5,7 @@ source "https://rubygems.org"
5
5
  gem "sidekiq", "~> 5.1.0"
6
6
 
7
7
  group :test do
8
- gem "simplecov"
8
+ gem "simplecov", "~> 0.17.0"
9
9
  end
10
10
 
11
11
  gemspec path: "../"
@@ -5,7 +5,7 @@ source "https://rubygems.org"
5
5
  gem "sidekiq", "~> 6.0"
6
6
 
7
7
  group :test do
8
- gem "simplecov"
8
+ gem "simplecov", "~> 0.17.0"
9
9
  end
10
10
 
11
11
  gemspec path: "../"
@@ -5,7 +5,7 @@ source "https://rubygems.org"
5
5
  gem "sinatra", "~> 1.4.0"
6
6
 
7
7
  group :test do
8
- gem "simplecov"
8
+ gem "simplecov", "~> 0.17.0"
9
9
  end
10
10
 
11
11
  gemspec path: "../"
@@ -3,7 +3,7 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  group :test do
6
- gem "simplecov"
6
+ gem "simplecov", "~> 0.17.0"
7
7
  end
8
8
 
9
9
  gemspec path: "../"
@@ -7,65 +7,57 @@ module Loga
7
7
  @app = app
8
8
  end
9
9
 
10
- def call(env)
10
+ def call(env, started_at = Time.now)
11
11
  request = Loga::Rack::Request.new(env)
12
12
  env['loga.request.original_path'] = request.path
13
13
 
14
14
  if logger.respond_to?(:tagged)
15
- logger.tagged(compute_tags(request)) { call_app(request, env) }
15
+ logger.tagged(compute_tags(request)) { call_app(request, env, started_at) }
16
16
  else
17
- call_app(request, env)
17
+ call_app(request, env, started_at)
18
18
  end
19
19
  end
20
20
 
21
21
  private
22
22
 
23
- attr_reader :data, :env, :request, :started_at
24
-
25
- def call_app(request, env)
26
- @data = {}
27
- @env = env
28
- @request = request
29
- @started_at = Time.now
30
-
31
- @app.call(env).tap { |status, _headers, _body| data['status'] = status.to_i }
23
+ def call_app(request, env, started_at)
24
+ status, _headers, _body = @app.call(env)
32
25
  ensure
33
- set_data
34
- send_message
35
- end
26
+ data = generate_data(request, status, started_at)
36
27
 
37
- # rubocop:disable Metrics/LineLength
38
- def set_data
39
- data['method'] = request.request_method
40
- data['path'] = request.original_path
41
- data['params'] = request.filtered_parameters
42
- data['request_id'] = request.uuid
43
- data['request_ip'] = request.ip
44
- data['user_agent'] = request.user_agent
45
- data['controller'] = request.controller_action_name if request.controller_action_name
46
- data['duration'] = duration_in_ms(started_at, Time.now)
47
-
48
- # If data['status'] is nil we assume an exception was raised when calling the application
49
- data['status'] ||= 500
50
- end
51
- # rubocop:enable Metrics/LineLength
28
+ exception = compute_exception(env)
52
29
 
53
- def send_message
54
30
  event = Loga::Event.new(
55
31
  data: { request: data },
56
- exception: compute_exception,
57
- message: compute_message,
32
+ exception: exception,
33
+ message: compute_message(request, data),
58
34
  timestamp: started_at,
59
35
  type: 'request',
60
36
  )
61
- logger.public_send(compute_level, event)
37
+
38
+ exception ? logger.error(event) : logger.info(event)
39
+ end
40
+
41
+ def generate_data(request, status, started_at)
42
+ controller = request.controller_action_name
43
+ status ||= 500
44
+ {
45
+ 'method' => request.request_method,
46
+ 'path' => request.original_path,
47
+ 'params' => request.filtered_parameters,
48
+ 'request_id' => request.uuid,
49
+ 'request_ip' => request.ip,
50
+ 'user_agent' => request.user_agent,
51
+ 'duration' => duration_in_ms(started_at, Time.now),
52
+ 'status' => status.to_i,
53
+ }.tap { |d| d['controller'] = controller if controller }
62
54
  end
63
55
 
64
56
  def logger
65
57
  Loga.logger
66
58
  end
67
59
 
68
- def compute_message
60
+ def compute_message(request, data)
69
61
  '%<method>s %<filtered_full_path>s %<status>d in %<duration>dms' % {
70
62
  method: request.request_method,
71
63
  filtered_full_path: request.filtered_full_path,
@@ -74,19 +66,14 @@ module Loga
74
66
  }
75
67
  end
76
68
 
77
- def compute_level
78
- compute_exception ? :error : :info
79
- end
69
+ def compute_exception(env)
70
+ exception =
71
+ env['loga.exception'] || env['action_dispatch.exception'] ||
72
+ env['sinatra.error'] || env['rack.exception']
80
73
 
81
- def compute_exception
82
74
  filter_exceptions.include?(exception.class.to_s) ? nil : exception
83
75
  end
84
76
 
85
- def exception
86
- env['loga.exception'] || env['action_dispatch.exception'] ||
87
- env['sinatra.error'] || env['rack.exception']
88
- end
89
-
90
77
  def filter_exceptions
91
78
  Loga.configuration.filter_exceptions
92
79
  end
data/lib/loga/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Loga
2
- VERSION = '2.5.3'.freeze
2
+ VERSION = '2.5.4'.freeze
3
3
  end
@@ -68,7 +68,6 @@ RSpec.describe 'Structured logging with Sinatra', :with_hostname, :timecop do
68
68
  end
69
69
  let(:data) do
70
70
  {
71
- 'status' => 200,
72
71
  'method' => 'GET',
73
72
  'path' => '/ok',
74
73
  'params' => { 'username'=>'yoshi' },
@@ -76,6 +75,7 @@ RSpec.describe 'Structured logging with Sinatra', :with_hostname, :timecop do
76
75
  'request_ip' => '127.0.0.1',
77
76
  'user_agent' => nil,
78
77
  'duration' => 0,
78
+ 'status' => 200,
79
79
  }
80
80
  end
81
81
  let(:data_as_text) { "data=#{{ request: data }.inspect}" }
@@ -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
@@ -69,9 +74,31 @@ describe Loga::Rack::Logger do
69
74
 
70
75
  context 'when an exception is raised' do
71
76
  let(:app) { ->(_env) { raise exception_class } }
72
-
73
- it 'does not rescue the exception' do
74
- expect { subject.call(env) }.to raise_error(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
+ )
75
102
  end
76
103
  end
77
104
 
@@ -113,28 +140,21 @@ describe Loga::Rack::Logger do
113
140
  end
114
141
 
115
142
  context 'when the logger is tagged' do
116
- let(:logger) { double(:logger, tagged: true) }
117
-
118
- before do
119
- allow(subject).to receive(:call_app).with(any_args).and_return(:response)
120
- allow(subject).to receive(:compute_tags).with(any_args).and_return(:tag)
121
- allow(logger).to receive(:tagged).with('hello') do |&block|
122
- block.call
123
- end
124
- 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
125
149
 
126
- context 'when tags are present' do
127
- let(:tags) { [:foo] }
150
+ it 'calls the tags and computes them' do
151
+ middleware.call(env)
128
152
 
129
- it 'yields the app with tags' do
130
- allow(logger).to receive(:tagged)
131
- subject.call(env)
132
- expect(logger).to have_received(:tagged).with(:tag) do |&block|
133
- expect(block.call).to eq(:response)
134
- end
135
- end
153
+ expect(fake_tag_proc)
154
+ .to have_received(:call)
155
+ .with(instance_of(Loga::Rack::Request))
136
156
  end
137
157
  end
138
158
  end
139
159
  end
140
- # 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.5.3
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: 2020-10-27 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