trace_request_id 0.1.2
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 +7 -0
- data/README.md +127 -0
- data/lib/rack/trace_id.rb +41 -0
- data/lib/trace_request_id/railtie.rb +45 -0
- data/lib/trace_request_id/sidekiq_client_middleware.rb +26 -0
- data/lib/trace_request_id/sidekiq_server_middleware.rb +22 -0
- data/lib/trace_request_id/version.rb +5 -0
- data/lib/trace_request_id.rb +41 -0
- metadata +55 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f42a8225e6860b237f499a3b00e8d1204d1035873cbd8b9c69caee39b8de100c
|
|
4
|
+
data.tar.gz: a9934505dcb9b0528e20edddce2eb27edfa03d26f6f5a8a568c7ea7df8b4da74
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8d04f12d5654cb4a7ebc16934b430cdc853a100911b4c9406ab297a2398e33522921c7977f435849dba1d95951475b0682640d216a69af44fccf1574c47c456f
|
|
7
|
+
data.tar.gz: 0cfa01653d617229b8057f8d80494ea7fa6461536448050e0b07ed7e424957cc2686b2e6b5cdce2c8e92ae0352722fed23837df244dbce87b569e1953eaf0276
|
data/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# TraceRequestId
|
|
2
|
+
|
|
3
|
+
A Ruby gem that stores X-Request-Id in thread context and passes it to Sidekiq jobs to trace user journeys.
|
|
4
|
+
This gem helps maintain request context across different parts of your application, making it easier to track
|
|
5
|
+
and debug user requests through your system.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Thread-safe storage of request IDs
|
|
10
|
+
- Automatic UUID generation for new requests
|
|
11
|
+
- Sidekiq integration for passing request IDs to background jobs
|
|
12
|
+
- Rails middleware support for automatic request ID handling
|
|
13
|
+
- Simple API for managing request IDs
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Add this line to your application's Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'trace_request_id'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
And then execute:
|
|
24
|
+
|
|
25
|
+
$ bundle install
|
|
26
|
+
|
|
27
|
+
Or install it yourself as:
|
|
28
|
+
|
|
29
|
+
$ gem install trace_request_id
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Basic Usage
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
# Get the current request ID (returns nil if not set)
|
|
37
|
+
TraceRequestId.id
|
|
38
|
+
|
|
39
|
+
# Set a request ID
|
|
40
|
+
TraceRequestId.id = "custom-request-id"
|
|
41
|
+
|
|
42
|
+
# Get or initialize a request ID (generates UUID if not set)
|
|
43
|
+
TraceRequestId.id(init: true)
|
|
44
|
+
|
|
45
|
+
# Clear the current request ID
|
|
46
|
+
TraceRequestId.clear
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Sinatra Integration
|
|
50
|
+
|
|
51
|
+
```ruby
|
|
52
|
+
class MyApplication < Sinatra::Base
|
|
53
|
+
use Rack::TraceId
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Rails Integration
|
|
58
|
+
|
|
59
|
+
The gem provides a Rails middleware that automatically handles request IDs.
|
|
60
|
+
|
|
61
|
+
It registers Rails middleware using Railtie, inserting it after ActionDispatch::RequestId
|
|
62
|
+
|
|
63
|
+
The middleware:
|
|
64
|
+
- Extracts the request ID from the Rails request (set by ActionDispatch::RequestId)
|
|
65
|
+
- Stores it in the thread context for the duration of the request
|
|
66
|
+
- Cleans up the thread context after the request completes
|
|
67
|
+
|
|
68
|
+
### Sidekiq Integration
|
|
69
|
+
|
|
70
|
+
The gem registers Sidekiq middleware automatically using Railtie.
|
|
71
|
+
The gem provides both client and server middleware to maintain request context across background jobs.
|
|
72
|
+
|
|
73
|
+
#### Client Middleware
|
|
74
|
+
|
|
75
|
+
- Captures the current trace ID from the thread context
|
|
76
|
+
- Stores it in the job payload before saving to Redis
|
|
77
|
+
- Generates a new UUID if no trace ID exists
|
|
78
|
+
|
|
79
|
+
#### Server Middleware
|
|
80
|
+
|
|
81
|
+
- Restores the trace ID from the job payload to the worker thread context
|
|
82
|
+
- Automatically cleans up the thread context after the job completes
|
|
83
|
+
|
|
84
|
+
## Thread Safety
|
|
85
|
+
|
|
86
|
+
The gem is designed to be thread-safe. Each thread maintains its own request ID context, making it safe to use in multi-threaded environments.
|
|
87
|
+
|
|
88
|
+
Example of thread isolation:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
# Main thread
|
|
92
|
+
TraceRequestId.id = "main-thread-id"
|
|
93
|
+
|
|
94
|
+
# Different threads maintain separate contexts
|
|
95
|
+
thread1 = Thread.new do
|
|
96
|
+
TraceRequestId.id = "thread1-id"
|
|
97
|
+
# TraceRequestId.id returns "thread1-id"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
thread2 = Thread.new do
|
|
101
|
+
TraceRequestId.id = "thread2-id"
|
|
102
|
+
# TraceRequestId.id returns "thread2-id"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Main thread still has its original ID
|
|
106
|
+
# TraceRequestId.id returns "main-thread-id"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Development
|
|
110
|
+
|
|
111
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
|
112
|
+
Then, to run the tests:
|
|
113
|
+
- rspec --pattern spec/*.rb
|
|
114
|
+
- cd spec/dummy_app
|
|
115
|
+
- rspec
|
|
116
|
+
- cd ../spec/dummy_app_no_sidekiq
|
|
117
|
+
- rspec
|
|
118
|
+
- cd ../spec/dummy_sinatra
|
|
119
|
+
- rspec
|
|
120
|
+
|
|
121
|
+
## Contributing
|
|
122
|
+
|
|
123
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/den1049/trace_request_id.
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'securerandom'
|
|
4
|
+
|
|
5
|
+
module Rack
|
|
6
|
+
# Middleware to store +request_id+ in the thread context as +trace_id+ and clean it up at the end of the request.
|
|
7
|
+
#
|
|
8
|
+
# For rails app it needs to be inserted after ActionDispatch::RequestId to ensure that request_id
|
|
9
|
+
# will be retrieved or generated with ActionDispatch::RequestId.
|
|
10
|
+
# config.middleware.insert_after ActionDispatch::RequestId, Rack::TraceId
|
|
11
|
+
class TraceId
|
|
12
|
+
def initialize(app)
|
|
13
|
+
@app = app
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call(env)
|
|
17
|
+
with_trace_id(env) do
|
|
18
|
+
@app.call(env)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# Extracts +request_id+ from +env+ argument, then wraps block with thread context store and clear steps
|
|
25
|
+
def with_trace_id(env)
|
|
26
|
+
TraceRequestId.id = env_request_id(env)
|
|
27
|
+
|
|
28
|
+
yield
|
|
29
|
+
ensure
|
|
30
|
+
TraceRequestId.clear
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def env_request_id(env)
|
|
34
|
+
return env['HTTP_X_REQUEST_ID'] || SecureRandom.uuid unless defined?(ActionDispatch::Request)
|
|
35
|
+
|
|
36
|
+
# extract request_id assigned by ActionDispatch::RequestId middleware
|
|
37
|
+
req = ActionDispatch::Request.new env
|
|
38
|
+
req.request_id
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class TraceRequestId
|
|
4
|
+
class Railtie < Rails::Railtie # :nodoc:
|
|
5
|
+
initializer 'trace_request_id.configure_rails_initialization' do |app|
|
|
6
|
+
app.middleware.insert_after ActionDispatch::RequestId, Rack::TraceId
|
|
7
|
+
register_sidekiq_middleware if defined?(Sidekiq)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def register_sidekiq_middleware
|
|
13
|
+
register_sidekiq_client_middleware
|
|
14
|
+
register_sidekiq_server_middleware
|
|
15
|
+
register_sidekiq_test_middleware if defined?(Sidekiq::Testing)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def register_sidekiq_client_middleware
|
|
19
|
+
Sidekiq.configure_client do |config|
|
|
20
|
+
config.client_middleware do |chain|
|
|
21
|
+
chain.add SidekiqClientMiddleware
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def register_sidekiq_server_middleware
|
|
27
|
+
Sidekiq.configure_server do |config|
|
|
28
|
+
config.client_middleware do |chain|
|
|
29
|
+
chain.add SidekiqClientMiddleware
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
config.server_middleware do |chain|
|
|
33
|
+
chain.add SidekiqServerMiddleware
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def register_sidekiq_test_middleware
|
|
39
|
+
# attach Sidekiq middleware to Sidekiq:Testing
|
|
40
|
+
Sidekiq::Testing.server_middleware do |chain|
|
|
41
|
+
chain.add SidekiqServerMiddleware
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class TraceRequestId
|
|
4
|
+
# Stores +trace_id+ from the thread context to the job context before saving it to Redis.
|
|
5
|
+
#
|
|
6
|
+
# It needs to be inserted in the SidekiqClient chain at the start.
|
|
7
|
+
# Sidekiq.configure_client do |config|
|
|
8
|
+
# config.client_middleware do |chain|
|
|
9
|
+
# chain.add TraceRequestId::SidekiqClientMiddleware
|
|
10
|
+
# # ... other client middlewares
|
|
11
|
+
# end
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# Sidekiq.configure_server do |config|
|
|
15
|
+
# config.client_middleware do |chain|
|
|
16
|
+
# chain.add TraceRequestId::SidekiqClientMiddleware
|
|
17
|
+
# # ... other client middlewares
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
class SidekiqClientMiddleware
|
|
21
|
+
def call(_worker_class, job, _queue, _redis_pool = '')
|
|
22
|
+
job[TraceRequestId::TRACE_ID] = TraceRequestId.id(init: true)
|
|
23
|
+
yield
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class TraceRequestId
|
|
4
|
+
# Restores +trace_id+ from the job context (Redis) to the thread context before starting a job.
|
|
5
|
+
#
|
|
6
|
+
# It needs to be inserted in the SidekiqClient chain at the start.
|
|
7
|
+
# Sidekiq.configure_server do |config|
|
|
8
|
+
# config.server_middleware do |chain|
|
|
9
|
+
# chain.add TraceRequestId::SidekiqServerMiddleware
|
|
10
|
+
# # ... other server middlewares
|
|
11
|
+
# end
|
|
12
|
+
# end
|
|
13
|
+
class SidekiqServerMiddleware
|
|
14
|
+
def call(_worker, job, _queue)
|
|
15
|
+
TraceRequestId.id = job[TraceRequestId::TRACE_ID]
|
|
16
|
+
|
|
17
|
+
yield
|
|
18
|
+
ensure
|
|
19
|
+
TraceRequestId.clear
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'trace_request_id/version'
|
|
4
|
+
require_relative 'rack/trace_id'
|
|
5
|
+
require_relative 'trace_request_id/railtie' if defined?(Rails::Railtie)
|
|
6
|
+
require_relative 'trace_request_id/sidekiq_client_middleware' if defined?(Sidekiq)
|
|
7
|
+
require_relative 'trace_request_id/sidekiq_server_middleware' if defined?(Sidekiq)
|
|
8
|
+
|
|
9
|
+
# Module to store trace id in the thread context
|
|
10
|
+
class TraceRequestId
|
|
11
|
+
TRACE_ID = '__trace_id'
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
# Get the current trace id, or +nil+ if one has not been set.
|
|
15
|
+
def id(init: false)
|
|
16
|
+
self.id = new_trace_id_value if init && current_trace_id.to_s.strip.empty?
|
|
17
|
+
|
|
18
|
+
current_trace_id
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Set the new trace id.
|
|
22
|
+
def id=(new_trace_id)
|
|
23
|
+
Thread.current.thread_variable_set(TRACE_ID, new_trace_id)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Clear the trace id from the current thread.
|
|
27
|
+
def clear
|
|
28
|
+
Thread.current.thread_variable_set(TRACE_ID, nil)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def current_trace_id
|
|
34
|
+
Thread.current.thread_variable_get(TRACE_ID)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def new_trace_id_value
|
|
38
|
+
SecureRandom.uuid
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: trace_request_id
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Denis
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2025-06-18 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: |-
|
|
14
|
+
This gem helps track user journey storing X-Request-Id in the thread context
|
|
15
|
+
and passing it to Sidekiq jobs
|
|
16
|
+
email:
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- README.md
|
|
22
|
+
- lib/rack/trace_id.rb
|
|
23
|
+
- lib/trace_request_id.rb
|
|
24
|
+
- lib/trace_request_id/railtie.rb
|
|
25
|
+
- lib/trace_request_id/sidekiq_client_middleware.rb
|
|
26
|
+
- lib/trace_request_id/sidekiq_server_middleware.rb
|
|
27
|
+
- lib/trace_request_id/version.rb
|
|
28
|
+
homepage: https://github.com/den1049/trace_request_id
|
|
29
|
+
licenses:
|
|
30
|
+
- MIT
|
|
31
|
+
metadata:
|
|
32
|
+
homepage_uri: https://github.com/den1049/trace_request_id
|
|
33
|
+
source_code_uri: https://github.com/den1049/trace_request_id
|
|
34
|
+
changelog_uri: https://github.com/den1049/trace_request_id/blob/main/CHANGELOG.md
|
|
35
|
+
rubygems_mfa_required: 'true'
|
|
36
|
+
post_install_message:
|
|
37
|
+
rdoc_options: []
|
|
38
|
+
require_paths:
|
|
39
|
+
- lib
|
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: 2.7.0
|
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0'
|
|
50
|
+
requirements: []
|
|
51
|
+
rubygems_version: 3.1.6
|
|
52
|
+
signing_key:
|
|
53
|
+
specification_version: 4
|
|
54
|
+
summary: A gem to store X-Request-Id in thread context and pass it to Sidekiq jobs
|
|
55
|
+
test_files: []
|