request_id 0.3.0 → 0.4.0

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
- 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