loga 2.5.3 → 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.
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