[Serve] Add client IP address to HTTP access logs#60967
Merged
Conversation
Signed-off-by: harshit <harshit@anyscale.com>
Contributor
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
abrarsheikh
reviewed
Feb 13, 2026
abrarsheikh
left a comment
Contributor
There was a problem hiding this comment.
let's gate this feature behind a feature flag, which is off by default.
…ture flag The client IP logging feature is now off by default for privacy. Set RAY_SERVE_LOG_CLIENT_ADDRESS=1 to enable it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: harshit <harshit@anyscale.com>
Contributor
Author
done. |
…rrors The test uses serve_and_ray_shutdown which kills the shared Ray instance. Placing it between serve_instance tests caused subsequent teardowns to fail with "Client has already been shut down." Move it to the serve_and_ray_shutdown test section at the bottom of the file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: harshit <harshit@anyscale.com>
abrarsheikh
reviewed
Feb 17, 2026
Address review feedback: fix ambiguous IPv6 log output (e.g. ::1:54321 -> [::1]:54321), add client address extraction for gRPC requests via context.peer(), propagate _client through request context in replicas for handle-to-handle calls, and add gRPC access log integration test. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: harshit <harshit@anyscale.com>
Move gRPC-specific imports back to inline inside the test function and skip test_grpc_access_log_client_address when RAY_SERVE_ENABLE_HA_PROXY is enabled, since the gRPC test is not compatible with HAProxy CI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: harshit <harshit@anyscale.com>
Signed-off-by: harshit <harshit@anyscale.com>
Signed-off-by: harshit <harshit@anyscale.com>
Signed-off-by: harshit <harshit@anyscale.com>
Signed-off-by: harshit <harshit@anyscale.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Signed-off-by: harshit <harshit@anyscale.com>
abrarsheikh
approved these changes
Mar 16, 2026
Lucas61000
pushed a commit
to Lucas61000/ray
that referenced
this pull request
May 15, 2026
## Summary
- Add client IP:port to Ray Serve HTTP access logs
- Thread client address from the proxy through the request context and
metadata to the replica
- Handle both proxy-routed and direct ingress HTTP paths
For services behind a load balancer, uvicorn's `ProxyHeadersMiddleware`
(enabled by default) resolves `X-Forwarded-For` into `scope["client"]`
automatically, so the logged IP reflects the original client when
`FORWARDED_ALLOW_IPS` is configured.
## How It Works
The client IP is available at the entry point (proxy or direct ingress
replica) but needs to reach the replica's access log, which runs in a
separate process. The data flows through existing infrastructure:
```
External Client (10.0.91.46:54321)
|
[ Proxy ]
| 1. Reads scope["client"] via proxy_request.client
| 2. format_client_address() formats the raw tuple into "host:port"
| 3. Logs it in the proxy access log
| 4. Passes it into _RequestContext._client
|
[ DeploymentHandle ]
| 5. default_impl.py copies _RequestContext._client → RequestMetadata._client
|
[ Replica ]
| 6. Reads request_metadata._client and logs it in the replica access log
```
For **direct ingress HTTP** (replica serves HTTP directly, no proxy),
the replica reads `scope["client"]` itself and formats it with the same
`format_client_address()`.
---
## Update: Feature flag gating
Per review feedback, the client IP logging is now gated behind a feature
flag that is **off by default**:
```
RAY_SERVE_LOG_CLIENT_ADDRESS=1
```
The gate is centralized in `access_log_msg()` in `logging_utils.py` —
when the flag is off, the `client` parameter is ignored and the log
format is unchanged from before this PR. The client address data still
flows through the request context, but is simply not rendered in logs
unless the flag is enabled.
**Tests:** Added a parametrized integration test
(`test_http_access_log_client_address`) that verifies both flag states —
client IP present when on, absent when off.
---------
Signed-off-by: harshit <harshit@anyscale.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
For services behind a load balancer, uvicorn's
ProxyHeadersMiddleware(enabled by default) resolvesX-Forwarded-Forintoscope["client"]automatically, so the logged IP reflects the original client whenFORWARDED_ALLOW_IPSis configured.How It Works
The client IP is available at the entry point (proxy or direct ingress replica) but needs to reach the replica's access log, which runs in a separate process. The data flows through existing infrastructure:
For direct ingress HTTP (replica serves HTTP directly, no proxy), the replica reads
scope["client"]itself and formats it with the sameformat_client_address().Update: Feature flag gating
Per review feedback, the client IP logging is now gated behind a feature flag that is off by default:
The gate is centralized in
access_log_msg()inlogging_utils.py— when the flag is off, theclientparameter is ignored and the log format is unchanged from before this PR. The client address data still flows through the request context, but is simply not rendered in logs unless the flag is enabled.Tests: Added a parametrized integration test (
test_http_access_log_client_address) that verifies both flag states — client IP present when on, absent when off.