VOOZH about

URL: https://deepwiki.com/hypervel/telescope/2.3.2-request-watcher

⇱ Request Watcher | hypervel/telescope | DeepWiki


Loading...
Last indexed: 7 February 2026 (146f77)
Menu

Request Watcher

Purpose and Scope

The RequestWatcher is the most comprehensive watcher in Telescope's monitoring system, responsible for capturing complete HTTP request and response data for every incoming request to the application. This watcher records 14 distinct data points including request metadata (IP, URI, method), routing information (controller action, middleware), request/response headers and payloads, session data, execution metrics (duration, memory), and coroutine context state.

The RequestWatcher is unique among watchers in that it executes at request completion and triggers the storage phase for all entries accumulated during the request lifecycle. For information about other infrastructure watchers, see Additional Watchers. For details on how storage is triggered, see Storage Lifecycle Management.

Sources: src/Watchers/RequestWatcher.php26-290


Registration and Event Integration

The RequestWatcher registers itself during Telescope's bootstrap phase by subscribing to the RequestHandled event, which fires after the HTTP response has been prepared but before it is sent to the client.

Registration Process


The registration process involves two critical steps:

  1. Request Lifecycle Enablement src/Watchers/RequestWatcher.php62-81: The watcher modifies the Hyperf server configuration to enable enable_request_lifecycle option for all HTTP servers. This ensures that the framework dispatches RequestReceived and RequestHandled events, which are required for Telescope's monitoring to function properly.

  2. Event Listener Registration src/Watchers/RequestWatcher.php58-60: The watcher subscribes its recordRequest() method to the RequestHandled event via the PSR-14 EventDispatcherInterface.

Sources: src/Watchers/RequestWatcher.php51-81


Data Collection Schema

The RequestWatcher captures comprehensive request and response data organized into 14 distinct fields. Each field is extracted from different sources within the HTTP lifecycle.

Captured Fields

FieldTypeSourceDescription
ip_addressstringRequestContract::ip()Client IP address
uristringRequestContract::fullUrl()Request URI relative to application root
methodstringRequestContract::method()HTTP method (GET, POST, etc.)
controller_actionstringDispatched::handler->callbackResolved controller/action or route handler
middlewarearrayContext::get('request.middleware')Stack of middleware executed
headersarrayServerRequestInterface::getHeaders()Request headers (sanitized)
payloadarrayRequestContract::all() + uploaded filesRequest input including parsed files
sessionarraySession::all()Session variables (if session exists)
response_headersarrayResponseInterface::getHeaders()Response headers (sanitized)
response_statusintResponseInterface::getStatusCode()HTTP status code
responsearray|stringResponseInterface::getBody()Formatted response content
contextarrayContext::getContainer()Hyperf coroutine context state
durationintmicrotime(true) - request_time_floatRequest execution time in milliseconds
memoryfloatmemory_get_peak_usage(true)Peak memory usage in MB

Sources: src/Watchers/RequestWatcher.php99-114


Request Recording Lifecycle

The following diagram illustrates the complete lifecycle of request recording, from event trigger to storage completion:


Sources: src/Watchers/RequestWatcher.php86-118


Filtering Mechanisms

The RequestWatcher provides two configurable filtering mechanisms to exclude specific requests from being recorded based on HTTP method or response status code.

HTTP Method Filtering

The shouldIgnoreHttpMethod() method checks incoming requests against a configured list of HTTP methods to ignore src/Watchers/RequestWatcher.php123-135 The ignore list is read from the watcher's options array (ignore_http_methods) and cached in the $ignoreHttpMethods property after normalizing to lowercase.

Configuration Example:


Status Code Filtering

The shouldIgnoreStatusCode() method filters requests based on the HTTP response status code src/Watchers/RequestWatcher.php140-146 This is commonly used to exclude successful requests (2xx) or specific error codes from monitoring.

Configuration Example:


Both filters are evaluated early in the recordRequest() method src/Watchers/RequestWatcher.php88-93 preventing unnecessary data extraction if the request should be ignored.

Sources: src/Watchers/RequestWatcher.php88-146


Data Sanitization

The RequestWatcher implements multi-layered sanitization to prevent sensitive data from being stored in Telescope entries. Three categories of data are sanitized: request headers, request parameters, and response parameters.

Sanitization Flow


Header Sanitization

The headers() method processes both request and response headers src/Watchers/RequestWatcher.php151-161 It first converts multi-value headers (arrays) into comma-separated strings, then applies the hideParameters() method using the Telescope::$hiddenRequestHeaders array as a mask. Any header matching a pattern in the mask is replaced with '********'.

Payload Sanitization

The payload() method sanitizes request input, session data, and response bodies src/Watchers/RequestWatcher.php166-172 It applies the hideParameters() method using the Telescope::$hiddenRequestParameters array for request data and Telescope::$hiddenResponseParameters for response data. The sanitization supports nested array structures through the use of Arr::get() and Arr::set().

Parameter Hiding Implementation

The hideParameters() method performs the actual sanitization src/Watchers/RequestWatcher.php177-186:

For each hidden parameter pattern:
 If Arr::get(data, parameter) exists:
 Arr::set(data, parameter, '********')

This implementation supports dot notation for nested keys (e.g., 'user.password', 'auth.token'), enabling precise control over which nested fields are sanitized.

Sources: src/Watchers/RequestWatcher.php151-186


Input Extraction

The RequestWatcher extracts request input including both standard form data and uploaded files through the input() method src/Watchers/RequestWatcher.php201-213

File Upload Handling

Uploaded files are processed recursively using array_walk_recursive() to transform file objects into metadata arrays:

FieldValue
nameOriginal client filename from getClientOriginalName()
sizeFile size in kilobytes (KB) or '0' if not a valid file

The transformed file metadata is then merged with the standard request input using array_replace_recursive(), ensuring that file upload information is integrated into the payload while maintaining the same array structure.

Sources: src/Watchers/RequestWatcher.php201-213


Session Data Capture

Session variables are captured through the sessionVariables() method src/Watchers/RequestWatcher.php191-196 The method first checks if the request has an active session using $this->request->hasSession(). If a session exists, it retrieves all session data via $this->request->session()->all(). If no session is active, an empty array is returned.

The session data is then passed through the payload() sanitization method src/Watchers/RequestWatcher.php107 which applies the Telescope::$hiddenRequestParameters mask to remove sensitive session values.

Sources: src/Watchers/RequestWatcher.php107 src/Watchers/RequestWatcher.php191-196


Response Formatting

The response() method implements intelligent response formatting based on content type and status code src/Watchers/RequestWatcher.php218-254 This formatting strategy balances storage efficiency with debugging utility.

Response Processing Logic


Response Type Handling

ConditionReturn ValuePurpose
Size exceeds limit'Purged By Telescope'Prevent storage bloat
Stream error'Purged By Telescope: {error}'Indicate extraction failure
Valid JSONSanitized JSON arrayEnable inspection of API responses
Content-Type: text/plainRaw content stringPreserve plain text responses
Status 3xx redirect'Redirected to {Location}'Summarize redirect target
Empty content'Empty Response'Indicate no response body
All other cases'HTML Response'Summarize HTML/binary responses

Size Limiting

The contentWithinLimits() method enforces a configurable size limit on response content src/Watchers/RequestWatcher.php259-264:

Limit (KB) = options['size_limit'] ?? 64
Content Length (KB) = mb_strlen(content) / 1000
Is Within Limits = Content Length <= Limit

This prevents large responses (e.g., file downloads, large HTML pages) from consuming excessive storage space.

Sources: src/Watchers/RequestWatcher.php218-264


Context Capture

The getContext() method captures a snapshot of the Hyperf coroutine context state at request completion src/Watchers/RequestWatcher.php269-289 This provides visibility into request-scoped state that may be relevant for debugging.

Context Serialization Strategy

The method iterates through Context::getContainer() and applies type-specific transformations:

Data TypeTransformationExample
Object'object({ClassName})''object(Hypervel\Http\Request)'
Array'array({Count})''array(5)'
String (within limits)Raw string value'user-123'
String (exceeds limits)'Purged By Telescope'Large string truncated
Other scalar typesRaw value42, true, null

The di.depth key is explicitly excluded src/Watchers/RequestWatcher.php273-275 as it is an internal dependency injection tracking variable not relevant for debugging.

String values are checked against the same size limit as response content src/Watchers/RequestWatcher.php281-283 preventing large context strings from bloating storage.

Sources: src/Watchers/RequestWatcher.php269-289


Storage Trigger and Request Completion

The RequestWatcher plays a unique role in Telescope's storage lifecycle by explicitly triggering the storage phase and terminating recording src/Watchers/RequestWatcher.php116-117

Storage Sequence

1. Telescope::recordRequest(entry) // Queue request entry
2. Telescope::store(repository) // Trigger deferred storage
3. Telescope::stopRecording() // Clear recording flags

This explicit storage trigger ensures that:

  1. All entries are grouped together: The request entry is the last entry recorded for a given request, ensuring it shares the same BATCH_ID as all other entries recorded during the request lifecycle (queries, cache operations, logs, etc.)

  2. Storage executes immediately: The store() call retrieves all queued entries from the context and persists them to the repository, preventing entry loss if the request terminates unexpectedly

  3. Recording state is cleaned up: The stopRecording() call clears the SHOULD_RECORD flag from the context, preventing accidental recording in subsequent coroutines that might reuse the same context

This pattern makes the RequestWatcher the "terminal watcher" that concludes each request's monitoring session.

Sources: src/Watchers/RequestWatcher.php116-117


Configuration Reference

The RequestWatcher accepts the following configuration options in the telescope.php configuration file under the watchers array:

OptionTypeDefaultDescription
enabledbooltrueEnable or disable the RequestWatcher
ignore_http_methodsarray[]HTTP methods to exclude (e.g., ['OPTIONS', 'HEAD'])
ignore_status_codesarray[]Response status codes to exclude (e.g., [404, 500])
size_limitint64Maximum response/context size in kilobytes

Example Configuration:


Sources: src/Watchers/RequestWatcher.php126-129 src/Watchers/RequestWatcher.php143-145 src/Watchers/RequestWatcher.php261


Class Structure and Dependencies

The RequestWatcher depends on several framework components to perform its monitoring duties:


Sources: src/Watchers/RequestWatcher.php26-290