Add HTTP trace logging to AsyncHttpClient#99
Conversation
- Add logHttpRequest() and logHttpResponse() private methods that emit a single, complete DEBUG log entry for each outbound HTTP request and its assembled response (method, URL, headers, body). Logging is gated by log.isDebugEnabled() so there is zero overhead when INFO or above. - Controlled entirely via the AsyncHttpClient logger level in log4j2.xml. Set HTTP_TRACE_LEVEL=DEBUG environment variable to enable; leave unset (defaults to INFO) to silence. No code change required to toggle. - Document the feature in guides/APPENDIX-III.md with sample log output, log4j2.xml configuration snippet, and public endpoint flow examples. - Add HTTP_TRACE_LEVEL entry to the HTTP Client table in guides/CONFIGURATION-REFERENCE.md. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Triggers on pull_request targeting main and on push to main. Uses Java 21 (Temurin), Maven verify, and uploads Surefire reports as artifacts for 7 days. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds DEBUG-level HTTP trace logging for outbound requests/responses made by AsyncHttpClient, along with documentation and CI automation.
Changes:
- Emit DEBUG logs for outbound HTTP requests and fixed-length responses in
AsyncHttpClient. - Document HTTP trace logging configuration and provide public endpoint flow examples.
- Add a GitHub Actions CI workflow to run Maven verify and upload test reports.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| system/platform-core/src/main/java/org/platformlambda/automation/http/AsyncHttpClient.java | Adds request/response trace logging helpers and hooks them into request processing and fixed-length response handling. |
| guides/CONFIGURATION-REFERENCE.md | Documents HTTP_TRACE_LEVEL as the control for enabling the AsyncHttpClient trace logger. |
| guides/APPENDIX-III.md | Adds examples for calling public endpoints and documents HTTP trace logging with sample output/config. |
| .github/workflows/ci.yml | Introduces CI workflow to build and run unit tests on Java 21 and upload surefire reports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| sb.append("\n>>> ").append(request.getMethod()).append(' ') | ||
| .append(request.getTargetHost()).append(uri).append('\n'); | ||
| request.getHeaders().forEach((k, v) -> | ||
| sb.append(" ").append(k).append(": ").append(v).append('\n')); |
There was a problem hiding this comment.
HTTP trace logging currently prints all request headers and their values verbatim. This can leak secrets (e.g., Authorization/Bearer tokens, cookies, API keys) into application logs when DEBUG is enabled. Please redact or omit sensitive headers (case-insensitive match on common names like authorization, cookie, set-cookie, x-api-key, proxy-authorization) and consider stripping any user-info from the logged URL as well.
| po.annotateTrace(DESTINATION, request.getTargetHost() + getRawUrl(uri)); | ||
| if (log.isDebugEnabled()) { | ||
| logHttpRequest(request, uri); | ||
| } | ||
| HttpClient client = HttpClient.create() | ||
| .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout) | ||
| .headers(h -> updateHttpHeaders(po, request, h)); |
There was a problem hiding this comment.
The request log is emitted before updateHttpHeaders() runs, so it may not reflect the actual outbound request: (1) headers added later (sessionInfo, propagated trace header, and the computed Cookie header) are not shown, and (2) headers that will be filtered out by permittedHttpHeader() may still be logged. To make the trace accurate, build/log the final header set using the same filtering/augmentation logic used when sending the request (or log from within updateHttpHeaders after it has constructed the actual HttpHeaders).
| sb.append("\n<<< ").append(response.getStatus()).append('\n'); | ||
| response.getHeaders().forEach((k, v) -> | ||
| sb.append(" ").append(k).append(": ").append(v).append('\n')); | ||
| if (b != null && b.length > 0) { | ||
| sb.append(" body: ").append(Utility.getInstance().getUTF(b)).append('\n'); | ||
| } |
There was a problem hiding this comment.
logHttpResponse() always decodes the response body as UTF-8 text. sendFixedLengthResponse() can be used for non-text/binary responses whenever Content-Length is present, so this can produce unreadable output and potentially very large log messages. Consider logging body text only for known text content types (json/xml/text/javascript), otherwise log a byte count (and optionally truncate body logging to a maximum size) to avoid log bloat and accidental binary dumping.
| Set the `HTTP_TRACE_LEVEL` environment variable to `DEBUG` to enable tracing, or leave it unset | ||
| (defaults to `INFO`) to silence it. No code change or restart of the logging framework is needed — | ||
| only the environment variable controls the output. |
There was a problem hiding this comment.
The documentation claims changing HTTP_TRACE_LEVEL requires no restart and that only the environment variable controls output. In most deployments (e.g., Docker/Kubernetes/systemd), environment variables are fixed at process start, so changing HTTP_TRACE_LEVEL typically requires restarting the application (or at least reloading the log4j2 configuration). Please reword to avoid implying runtime toggling via env var without restart; alternatively, describe using log4j2 configuration reload/monitorInterval if that’s the intended mechanism.
| Set the `HTTP_TRACE_LEVEL` environment variable to `DEBUG` to enable tracing, or leave it unset | |
| (defaults to `INFO`) to silence it. No code change or restart of the logging framework is needed — | |
| only the environment variable controls the output. | |
| Set the `HTTP_TRACE_LEVEL` environment variable to `DEBUG` before starting the application to enable | |
| tracing, or leave it unset (defaults to `INFO`) to silence it. In most deployments, changes to | |
| environment variables take effect only after restarting the application. If you need to change the | |
| logger level without a restart, use Log4j2 configuration reload support for your logging | |
| configuration. |
Add logHttpRequest() and logHttpResponse() private methods that emit a single, complete DEBUG log entry for each outbound HTTP request and its assembled response (method, URL, headers, body). Logging is gated by log.isDebugEnabled() so there is zero overhead when INFO or above.
Controlled entirely via the AsyncHttpClient logger level in log4j2.xml. Set HTTP_TRACE_LEVEL=DEBUG environment variable to enable; leave unset (defaults to INFO) to silence. No code change required to toggle.
Document the feature in guides/APPENDIX-III.md with sample log output, log4j2.xml configuration snippet, and public endpoint flow examples.
Add HTTP_TRACE_LEVEL entry to the HTTP Client table in guides/CONFIGURATION-REFERENCE.md.