Class: Findbug::Capture::Context
- Inherits:
-
Object
- Object
- Findbug::Capture::Context
- Defined in:
- lib/findbug/capture/context.rb
Overview
Context stores request-scoped data that gets attached to errors.
THREAD-LOCAL STORAGE
In a multi-threaded server like Puma, multiple requests run concurrently. Each request needs its OWN context - we can’t share a global variable or Request A’s user would appear on Request B’s errors!
Solution: Thread.current - a hash specific to each thread.
Thread 1 (Request A):
Context.set_user(id: 1)
# Thread.current[:findbug_context] = { user: { id: 1 } }
Thread 2 (Request B):
Context.set_user(id: 2)
# Thread.current[:findbug_context] = { user: { id: 2 } }
Thread 1: Context.current[:user] → { id: 1 } ✓ Correct!
Thread 2: Context.current[:user] → { id: 2 } ✓ Correct!
WHAT GETS STORED?
-
User - who was affected
-
Tags - short key-value pairs for filtering
-
Extra - arbitrary data about the request
-
Breadcrumbs - trail of events before the error
-
Request - HTTP request details (auto-captured)
Constant Summary collapse
- THREAD_KEY =
:findbug_context- MAX_BREADCRUMBS =
50
Class Method Summary collapse
-
.add_breadcrumb(breadcrumb) ⇒ Object
Add a breadcrumb.
-
.add_tag(key, value) ⇒ Object
Add a tag.
-
.breadcrumbs ⇒ Array<Hash>
Get all breadcrumbs.
-
.clear! ⇒ Object
Clear the context (call between requests).
-
.current ⇒ Hash
Get the current context hash.
-
.extra ⇒ Hash
Get extra data.
-
.from_rack_request(rack_request) ⇒ Hash
Create context from a Rack request.
-
.merge(data) ⇒ Object
Merge extra data into context.
-
.request ⇒ Hash
Get request data.
-
.set_request(request_data) ⇒ Object
Set request data (auto-populated by middleware).
-
.set_user(user_data) ⇒ Object
Set user information.
-
.tags ⇒ Hash
Get all tags.
-
.to_h ⇒ Hash
Get the complete context for capturing.
-
.user ⇒ Hash?
Get current user.
Class Method Details
.add_breadcrumb(breadcrumb) ⇒ Object
Add a breadcrumb
Breadcrumbs are a chronological trail of events leading to an error. Think of them like a log, but attached to the error.
141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/findbug/capture/context.rb', line 141 def () crumbs = current[:breadcrumbs] # Add timestamp if not provided [:timestamp] ||= Time.now.utc.iso8601(3) crumbs << # Keep only the most recent breadcrumbs # This prevents memory issues from long-running requests crumbs.shift while crumbs.size > MAX_BREADCRUMBS end |
.add_tag(key, value) ⇒ Object
Add a tag
Tags are short key-value pairs optimized for filtering. Unlike extra data, tags are indexed and searchable.
89 90 91 |
# File 'lib/findbug/capture/context.rb', line 89 def add_tag(key, value) current[:tags][key.to_sym] = value end |
.breadcrumbs ⇒ Array<Hash>
Get all breadcrumbs
158 159 160 |
# File 'lib/findbug/capture/context.rb', line 158 def current[:breadcrumbs] end |
.clear! ⇒ Object
Clear the context (call between requests)
This MUST be called after each request to prevent context leaking. The Railtie sets this up via after_action.
54 55 56 |
# File 'lib/findbug/capture/context.rb', line 54 def clear! Thread.current[THREAD_KEY] = nil end |
.current ⇒ Hash
Get the current context hash
45 46 47 |
# File 'lib/findbug/capture/context.rb', line 45 def current Thread.current[THREAD_KEY] ||= default_context end |
.extra ⇒ Hash
Get extra data
119 120 121 |
# File 'lib/findbug/capture/context.rb', line 119 def extra current[:extra] end |
.from_rack_request(rack_request) ⇒ Hash
Create context from a Rack request
This extracts useful information from the HTTP request. Called automatically by the middleware.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/findbug/capture/context.rb', line 202 def from_rack_request(rack_request) { method: rack_request.request_method, url: rack_request.url, path: rack_request.path, query_string: scrub_query_string(rack_request.query_string), headers: scrub_headers(extract_headers(rack_request)), ip: rack_request.ip, user_agent: rack_request.user_agent, content_type: rack_request.content_type, content_length: rack_request.content_length, request_id: rack_request.env["action_dispatch.request_id"] } end |
.merge(data) ⇒ Object
Merge extra data into context
Extra data is arbitrary key-value pairs that provide more detail. Use this for non-indexed, detailed information.
111 112 113 |
# File 'lib/findbug/capture/context.rb', line 111 def merge(data) current[:extra].merge!(data) end |
.request ⇒ Hash
Get request data
174 175 176 |
# File 'lib/findbug/capture/context.rb', line 174 def request current[:request] end |
.set_request(request_data) ⇒ Object
Set request data (auto-populated by middleware)
166 167 168 |
# File 'lib/findbug/capture/context.rb', line 166 def set_request(request_data) current[:request] = request_data end |
.set_user(user_data) ⇒ Object
Set user information
65 66 67 |
# File 'lib/findbug/capture/context.rb', line 65 def set_user(user_data) current[:user] = scrub_user_data(user_data) end |
.tags ⇒ Hash
Get all tags
97 98 99 |
# File 'lib/findbug/capture/context.rb', line 97 def current[:tags] end |
.to_h ⇒ Hash
Get the complete context for capturing
This returns all context data in a format ready for storage.
184 185 186 187 188 189 190 191 192 |
# File 'lib/findbug/capture/context.rb', line 184 def to_h ctx = current.dup ctx.compact! # Remove nil values # Convert breadcrumbs to array (it's already an array, but be explicit) ctx[:breadcrumbs] = ctx[:breadcrumbs].dup if ctx[:breadcrumbs] ctx end |
.user ⇒ Hash?
Get current user
73 74 75 |
# File 'lib/findbug/capture/context.rb', line 73 def user current[:user] end |