request_id 0.3.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a15cb25ed02ec17242c57798948853b77d0b097c
4
- data.tar.gz: eed296879d558c00b33e507aa195482f29203dc8
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: 9011e2b94dae6364b5af80b30e652d960a89132f
4
+ data.tar.gz: 86957882e9a04e2b1318b54bf7f0739244930767
5
5
  SHA512:
6
- metadata.gz: fe2d085fbe00596365443abcb878130ebcef0c7d367f3207e2e178ea32be493d3a339f217587fb3d08dd7eb9eabac7eade5ebc7d7261244743de58052202f610
7
- data.tar.gz: 7f3543a463295b69d9767ac3b10b6f4a9573f843663a1ca68b0edf8276d21a8ac261871e328550747c81ec53f1565ee1536c6326e26e2a225744c8483e364d9d
6
+ metadata.gz: bc0867cb3c43d4760c8f79b9232e232113f73ff3b85c7f19159c447326f56515e321d530540f51a6362db82cb1778c4009a8e89f84f2d6142f587c8f8df30587
7
+ data.tar.gz: 16adfdda7b0c62c0888e0b39d00f4210c74510f86dc09bce3ff6329f5f6fa238a248dae46ddfae853bd2d79e7f18b759a08d089b5fa8c95d449796a0acbecbfb
data/README.md CHANGED
@@ -3,11 +3,12 @@
3
3
  This is a gem with a collection of middleware for easily cascading [Heroku request id's](https://devcenter.heroku.com/articles/http-request-id)
4
4
  Throughout the system. It includes:
5
5
 
6
- * Rack middleware, which adds the request\_id to `Thread.current[:request\_id]`
6
+ * Rack middleware, which adds the request\_id to `Thread.current[:request_id]`.
7
7
  * Sidekiq Client middleware, which adds the request\_id to the message
8
8
  payload.
9
9
  * Sidekiq Server middleware, which adds the request\_id to
10
10
  `Thread.current[:request_id]` from the request\_id in the message payload.
11
+ * Faraday middleware, which adds the request\_id as a response header `X-Request-Id`.
11
12
 
12
13
  ## Installation
13
14
 
@@ -46,12 +47,53 @@ Sidekiq.configure_server do |config|
46
47
  end
47
48
 
48
49
  config.server_middleware do |chain|
49
- chain.remove Sidekiq::Middleware::Server::Logging
50
50
  chain.add Sidekiq::Middleware::Client::RequestId
51
51
  end
52
52
  end
53
53
  ```
54
54
 
55
+ ### If you're using Faraday
56
+
57
+ Add the middleware.
58
+
59
+ ```ruby
60
+ builder.use Faraday::RequestId
61
+
62
+ ```
63
+
64
+ ### Customization
65
+
66
+ You can customize each middleware to store the value of any header you like in the same fashion. For instance,
67
+ if you wanted to track a `X-Request-Id` header as well as a `X-Session-Id` header, you could do so like this:
68
+
69
+ ```ruby
70
+ # Rack
71
+ use Rack::RequestId
72
+ use Rack::RequestId, key: :request_id, value: -> (env) { env['HTTP_X_SESSION_ID'], response_header: 'X-Session-Id' }
73
+
74
+ # Sidekiq
75
+ Sidekiq.configure_client do |config|
76
+ config.client_middleware do |chain|
77
+ chain.add Sidekiq::Middleware::Client::RequestId
78
+ chain.add Sidekiq::Middleware::Client::RequestId, key: :session_id, value: -> { ::RequestId.get(:session_id) }
79
+ end
80
+ end
81
+
82
+ Sidekiq.configure_server do |config|
83
+ config.client_middleware do |chain|
84
+ chain.add Sidekiq::Middleware::Client::RequestId
85
+ chain.add Sidekiq::Middleware::Client::RequestId, key: :session_id, value: -> { ::RequestId.get(:session_id) }
86
+ end
87
+
88
+ config.server_middleware do |chain|
89
+ chain.add Sidekiq::Middleware::Client::RequestId, key: :session_id, value: lambda { |item| item['session_id'] }
90
+ end
91
+ end
92
+
93
+ # Faraday
94
+ builder.use Faraday::RequestId, key: :session_id, header: 'X-Session-Id'
95
+ ```
96
+
55
97
  ## Contributing
56
98
 
57
99
  1. Fork it
@@ -5,6 +5,11 @@ module Faraday
5
5
  class RequestId < Faraday::Middleware
6
6
  HEADER = 'X-Request-Id'.freeze
7
7
 
8
+ def initialize(app, options = nil)
9
+ super(app)
10
+ @options = options || default_options
11
+ end
12
+
8
13
  def call(env)
9
14
  set_header(env) if needs_header?(env)
10
15
  @app.call(env)
@@ -13,15 +18,15 @@ module Faraday
13
18
  private
14
19
 
15
20
  def needs_header?(env)
16
- request_id && !env[:request_headers][HEADER]
21
+ ::RequestId.get(@options[:key]) && !env[:request_headers][@options[:header]]
17
22
  end
18
23
 
19
24
  def set_header(env)
20
- env[:request_headers][HEADER] = request_id
25
+ env[:request_headers][@options[:header]] = ::RequestId.get(@options[:key])
21
26
  end
22
27
 
23
- def request_id
24
- ::RequestId.request_id
28
+ def default_options
29
+ { key: :request_id, header: HEADER }
25
30
  end
26
31
  end
27
32
  end
@@ -2,7 +2,7 @@ require 'securerandom'
2
2
 
3
3
  module Rack
4
4
 
5
- # Public: Rack middleware that stores the Heroku-Request-Id header in a
5
+ # Public: Rack middleware that stores the X-Request-Id header in a
6
6
  # thread local variable.
7
7
  #
8
8
  # Heroku has a labs feature called request_id, which can be used to tracking
@@ -12,39 +12,35 @@ module Rack
12
12
  #
13
13
  # Examples
14
14
  #
15
- # use Rack::LogRequestId
15
+ # use Rack::RequestId, key: :request_id, value: -> (env) { env['HTTP_X_REQUEST_ID'] }, response_header: 'X-Request-Id'
16
16
  #
17
- # logger.info "request_id=#{Thread.current[:request_id]} Hello world"
17
+ # logger.info "request_id=#{RequestId.request_id} Hello world"
18
18
  # # => request_id=a08a6712229fb991c0e5026c246862c7 Hello world
19
19
  class RequestId
20
20
  REQUEST_HEADER = 'HTTP_X_REQUEST_ID'.freeze
21
21
  RESPONSE_HEADER = 'X-Request-Id'.freeze
22
22
 
23
- def initialize(app, options = {})
23
+ def initialize(app, options = nil)
24
24
  @app = app
25
+ @options = options || default_options
25
26
  end
26
27
 
27
28
  def call(env)
28
- ::RequestId.with_request_id(request_id(env)) do
29
+ ::RequestId.with(@options[:key], @options[:value].call(env)) do
29
30
  status, headers, body = @app.call(env)
30
- headers[RESPONSE_HEADER] ||= ::RequestId.request_id
31
+
32
+ if @options[:response_header]
33
+ headers[@options[:response_header]] ||= ::RequestId.get(@options[:key])
34
+ end
35
+
31
36
  [status, headers, body]
32
37
  end
33
38
  end
34
39
 
35
40
  private
36
41
 
37
- def request_id(env)
38
- env[REQUEST_HEADER] || generate
39
- end
40
-
41
- def generate
42
- generate? && SecureRandom.hex(16)
42
+ def default_options
43
+ { key: :request_id, value: lambda { |env| env[REQUEST_HEADER] }, response_header: RESPONSE_HEADER }
43
44
  end
44
-
45
- def generate?
46
- ::RequestId.configuration.generate
47
- end
48
-
49
45
  end
50
46
  end
@@ -20,7 +20,7 @@ module RequestId
20
20
  #
21
21
  # Returns the String request id.
22
22
  def request_id
23
- Thread.current[:request_id]
23
+ get(:request_id)
24
24
  end
25
25
 
26
26
  # Internal: Set the current request_id.
@@ -32,7 +32,7 @@ module RequestId
32
32
  #
33
33
  # Returns the new String request id.
34
34
  def request_id=(request_id)
35
- Thread.current[:request_id] = request_id
35
+ set(:request_id, request_id)
36
36
  end
37
37
 
38
38
  # Public: Runs the block with the given request id set.
@@ -49,12 +49,28 @@ module RequestId
49
49
  #
50
50
  # RequestId.request_id
51
51
  # # => "9fee77ec37b483983839fe7a753b64d9"
52
- def with_request_id(request_id)
53
- last_request_id = RequestId.request_id
54
- RequestId.request_id = request_id
52
+ def with_request_id(request_id, &block)
53
+ with(:request_id, request_id, &block)
54
+ end
55
+
56
+ # Public: Runs the block with the given id key and value set.
57
+ def with(id_key, id_value)
58
+ last_id = RequestId.get(id_key)
59
+ RequestId.set(id_key, id_value)
55
60
  yield
56
61
  ensure
57
- RequestId.request_id = last_request_id
62
+ RequestId.set(id_key, last_id)
63
+ end
64
+
65
+ # Public: Retrieve the given id, which is generally set by the
66
+ # Rack or Sidekiq middleware.
67
+ def get(id_key)
68
+ Thread.current[id_key]
69
+ end
70
+
71
+ # Public: Set the given id to the given value
72
+ def set(id_key, id_value)
73
+ Thread.current[id_key] = id_value
58
74
  end
59
75
 
60
76
  def configuration
@@ -1,3 +1,3 @@
1
1
  module RequestId
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -2,15 +2,27 @@ module Sidekiq
2
2
  module Middleware
3
3
  module Client
4
4
  class RequestId
5
+ def initialize(options = nil)
6
+ @options = options || default_options
7
+ end
8
+
5
9
  def call(worker, item, queue)
6
- item['request_id'] = request_id if request_id
10
+ item[id_key] = id_value if id_value
7
11
  yield
8
12
  end
9
13
 
10
14
  private
11
15
 
12
- def request_id
13
- ::RequestId.request_id
16
+ def id_key
17
+ @options[:key].to_s
18
+ end
19
+
20
+ def id_value
21
+ @options[:value].call()
22
+ end
23
+
24
+ def default_options
25
+ { key: :request_id, value: lambda { ::RequestId.request_id } }
14
26
  end
15
27
  end
16
28
  end
@@ -12,12 +12,22 @@ module Sidekiq
12
12
  attr_accessor :no_reset
13
13
  end
14
14
 
15
+ def initialize(options = nil)
16
+ @options = options || default_options
17
+ end
18
+
15
19
  def call(worker, item, queue)
16
- ::RequestId.request_id = item['request_id']
20
+ ::RequestId.set(@options[:key], @options[:value].call(item))
17
21
  yield
18
22
  ensure
19
- ::RequestId.request_id = nil unless self.class.no_reset
23
+ ::RequestId.set(@options[:key], nil) unless self.class.no_reset
20
24
  end
25
+
26
+ private
27
+
28
+ def default_options
29
+ { key: :request_id, value: lambda { |item| item['request_id'] } }
30
+ end
21
31
  end
22
32
  end
23
33
  end
@@ -8,7 +8,7 @@ describe Faraday::RequestId do
8
8
  describe '.call' do
9
9
  context 'when a request_id is set' do
10
10
  before do
11
- RequestId.stub(request_id: SecureRandom.hex)
11
+ RequestId.stub(get: SecureRandom.hex)
12
12
  end
13
13
 
14
14
  it 'adds the X-Request-Id header' do
@@ -20,7 +20,7 @@ describe Faraday::RequestId do
20
20
 
21
21
  context 'when no request_id is set' do
22
22
  before do
23
- RequestId.stub(request_id: nil)
23
+ RequestId.stub(get: nil)
24
24
  end
25
25
 
26
26
  it 'does not add the X-Request-Id header' do
@@ -3,7 +3,8 @@ require 'securerandom'
3
3
 
4
4
  describe Rack::RequestId do
5
5
  let(:app) { double('app', call: [200, {}, ['Body']]) }
6
- let(:middleware) { described_class.new app }
6
+ let(:config) { { key: :request_id, value: lambda { |env| env['HTTP_X_REQUEST_ID'] }, response_header: 'X-Request-Id' } }
7
+ let(:middleware) { described_class.new app, config }
7
8
 
8
9
  describe '.call' do
9
10
  let(:request_id) { SecureRandom.hex }
@@ -29,4 +30,31 @@ describe Rack::RequestId do
29
30
  end
30
31
  end
31
32
  end
33
+
34
+ describe 'custom middleware configuration' do
35
+ let(:config) { { key: :session_id, value: lambda { |env| env['HTTP_X_SESSION_ID'] }, response_header: 'X-Session-Id' } }
36
+ let(:session_id) { SecureRandom.hex }
37
+
38
+ it 'stores the custom id in a thread local' do
39
+ Thread.current.should_receive(:[]=).with(:session_id, session_id)
40
+ app.should_receive(:call)
41
+ Thread.current.should_receive(:[]=).with(:session_id, nil)
42
+ middleware.call('HTTP_X_SESSION_ID' => session_id)
43
+ end
44
+
45
+ it 'sets the X-Session-Id header in the response' do
46
+ status, headers, body = middleware.call('HTTP_X_SESSION_ID' => session_id)
47
+ expect(headers['X-Session-Id']).to eq session_id
48
+ end
49
+
50
+ context 'when an exception is raised' do
51
+ it 'still sets the session_id back to nil' do
52
+ Thread.current.should_receive(:[]=).with(:session_id, session_id)
53
+ app.should_receive(:call).and_raise
54
+ Thread.current.should_receive(:[]=).with(:session_id, nil)
55
+ expect { middleware.call('HTTP_X_SESSION_ID' => session_id) }.to raise_error
56
+ end
57
+ end
58
+
59
+ end
32
60
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric J. Holmes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-12 00:00:00.000000000 Z
11
+ date: 2014-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,42 +28,42 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: faraday
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
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: '0'
69
69
  description: Classes for tracking request id
@@ -107,17 +107,17 @@ require_paths:
107
107
  - lib
108
108
  required_ruby_version: !ruby/object:Gem::Requirement
109
109
  requirements:
110
- - - '>='
110
+ - - ! '>='
111
111
  - !ruby/object:Gem::Version
112
112
  version: '0'
113
113
  required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ! '>='
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  requirements: []
119
119
  rubyforge_project:
120
- rubygems_version: 2.0.14
120
+ rubygems_version: 2.2.2
121
121
  signing_key:
122
122
  specification_version: 4
123
123
  summary: Classes for tracking request id