Skip to content

fix: add PROPAGATION_EXCLUDE_PORTS to httpclient-4.x plugin#800

Merged
wu-sheng merged 5 commits intoapache:mainfrom
daguimu:fix/httpclient4-propagation-exclude-ports-issue13700
Mar 26, 2026
Merged

fix: add PROPAGATION_EXCLUDE_PORTS to httpclient-4.x plugin#800
wu-sheng merged 5 commits intoapache:mainfrom
daguimu:fix/httpclient4-propagation-exclude-ports-issue13700

Conversation

@daguimu
Copy link
Contributor

@daguimu daguimu commented Mar 26, 2026

Problem

When the SkyWalking Java agent enhances an application that uses ClickHouse JDBC via HTTP (port 8123), the httpclient-4.x plugin unconditionally injects sw8, sw8-correlation, and sw8-x propagation headers into every outbound HTTP request. ClickHouse rejects requests containing unknown headers, returning HTTP 400 Bad Request, which breaks all JDBC queries.

Root Cause

HttpClientExecuteInterceptor.beforeMethod() iterates over all ContextCarrier items and calls httpRequest.setHeader() without checking whether the target server can tolerate extra headers. The httpclient-5.x plugin already solved this with a PROPAGATION_EXCLUDE_PORTS config, but httpclient-4.x was missing this feature.

Fix

  • Add PROPAGATION_EXCLUDE_PORTS config to HttpClientPluginConfig.Plugin.HttpClient (default: "8123")
  • Add skipIntercept() logic to HttpClientExecuteInterceptor that checks the destination port against the exclusion list before creating spans or injecting headers
  • When the port is excluded, beforeMethod, afterMethod, and handleMethodException all return early, leaving the HTTP request completely untouched
  • Port parsing is lazy and cached (double-checked locking) for zero overhead on the hot path
  • Add the config entry to agent.config

Tests Added

  • requestToExcludedPort_noSpanAndNoHeaderInjected - verifies port 8123 produces no trace segment and no header injection
  • requestToRegularPort_spanCreatedAndHeadersInjected - verifies port 8080 is still traced normally
  • whenExcludePortsEmpty_allPortsAreTraced - verifies empty config traces everything including 8123
  • multipleExcludedPorts_allSkippedAndNonExcludedStillTraced - verifies multi-port config (8123,9200) works correctly
  • excludedPort_handleMethodExceptionSkipped - verifies exception handling is also skipped for excluded ports

All existing httpclient-4.x tests continue to pass.

Impact

  • Only affects httpclient-4.x plugin users whose target servers reject unknown HTTP headers (e.g. ClickHouse)
  • Default config (8123) matches the httpclient-5.x plugin behavior
  • No behavioral change for non-excluded ports
  • Configurable via plugin.httpclient.propagation_exclude_ports or env var SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS

Fixes apache/skywalking#13700

Some HTTP-based protocols (e.g. ClickHouse on port 8123) reject
requests containing unknown HTTP headers such as sw8, returning
HTTP 400. The httpclient-5.x plugin already has this feature but
httpclient-4.x was missing it.

Add a PROPAGATION_EXCLUDE_PORTS config (default: "8123") to the
httpclient-4.x plugin so that requests to excluded ports skip
span creation and header injection entirely.

Fixes apache/skywalking#13700
@wu-sheng
Copy link
Member

#797 should have fixed this? Is CK using 4.x and 5.x?

Since httpclient-4.x now skips port 8123, the nested HTTP exit span
is no longer created, so the http.status_code tag no longer appears
on ClickHouse JDBC exit spans. Update expected test data accordingly.
@daguimu
Copy link
Contributor Author

daguimu commented Mar 26, 2026

Thanks for the review! PR #797 added PROPAGATION_EXCLUDE_PORTS to the httpclient-5.x plugin. However, ClickHouse JDBC v0.3.1 (used in the clickhouse-0.3.1-scenario E2E test) uses Apache HttpClient 4.5.13 (org.apache.http.impl.client.CloseableHttpClient) as its HTTP transport, which is intercepted by the httpclient-4.x plugin — a separate plugin that doesn't have this feature yet.

This PR adds the same PROPAGATION_EXCLUDE_PORTS support to the httpclient-4.x plugin to cover this case.

@wu-sheng
Copy link
Member

e2e doesn't matter at all. They passed anyway. the point is, is 0.3.1 ck client still used?

@daguimu
Copy link
Contributor Author

daguimu commented Mar 26, 2026

The issue reporter in apache/skywalking#13700 confirmed the problem is caused by the httpclient-4.x plugin — their workaround was SW_EXCLUDE_PLUGINS=httpclient-4.x.

This fix is not specific to ClickHouse JDBC v0.3.1 — any application using Apache HttpClient 4.x to communicate with a server that rejects unknown headers (e.g., ClickHouse on port 8123) would be affected. Apache HttpClient 4.x (org.apache.httpcomponents:httpclient) remains widely used in the Java ecosystem.

@wu-sheng wu-sheng added this to the 9.7.0 milestone Mar 26, 2026
@wu-sheng wu-sheng added enhancement New feature or request plugin labels Mar 26, 2026
@wu-sheng wu-sheng requested a review from Copilot March 26, 2026 03:58
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a PROPAGATION_EXCLUDE_PORTS configuration to the httpclient-4.x plugin so the interceptor can skip span creation and SkyWalking header injection for destination ports (defaulting to ClickHouse’s 8123), preventing HTTP 400s from servers that reject unknown headers.

Changes:

  • Introduce plugin.httpclient.propagation_exclude_ports config (default 8123) and document it in agent.config + release notes.
  • Implement lazy, cached excluded-port parsing in HttpClientExecuteInterceptor and short-circuit before/after/exception paths when excluded.
  • Add unit tests covering excluded vs regular ports and update ClickHouse scenario expected data.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/plugin/scenarios/clickhouse-0.3.1-scenario/config/expectedData.yaml Updates scenario expectations to match new behavior (no HTTP status tag emitted via httpclient-4.x path).
changes/changes-9.5.0.md Adds release note entry for the new exclusion-port config.
apm-sniffer/config/agent.config Documents and wires the new plugin.httpclient.propagation_exclude_ports setting + env var.
apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java Adds PROPAGATION_EXCLUDE_PORTS plugin config field and Javadoc.
apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientPropagationExcludePortTest.java New test suite validating skip behavior and edge cases.
apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java Implements skip-intercept logic with lazy parsing + caching of excluded ports.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

* <p>Default: {@code "8123"} (ClickHouse HTTP interface).
*
* <p>Example – also exclude port 9200 (Elasticsearch):
* {@code plugin.httpclient.PROPAGATION_EXCLUDE_PORTS=8123,9200}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Javadoc example uses plugin.httpclient.PROPAGATION_EXCLUDE_PORTS, but config keys are lowercased by ConfigInitializer (e.g. COLLECT_HTTP_PARAMS maps to plugin.httpclient.collect_http_params). This example should be updated to plugin.httpclient.propagation_exclude_ports=8123,9200 (and/or mention the env var) so users don’t set a key that will be ignored.

Suggested change
* {@code plugin.httpclient.PROPAGATION_EXCLUDE_PORTS=8123,9200}
* {@code plugin.httpclient.propagation_exclude_ports=8123,9200}

Copilot uses AI. Check for mistakes.
Fixes Copilot review comment: ConfigInitializer maps fields to
lowercase keys, so the example should read
plugin.httpclient.propagation_exclude_ports instead of uppercase.
Comment on lines +223 to +224
# Comma-separated list of destination ports whose outbound HTTP requests will be completely skipped by the httpclient-4.x interceptor (no exit span created, no sw8 headers injected). Default: 8123 (ClickHouse HTTP interface).
plugin.httpclient.propagation_exclude_ports=${SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS:8123}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be added as a default. This config should only exist in ck test cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Removed the default from agent.config and moved SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS=8123 to the clickhouse-0.3.1 E2E test scenario only.

Move the PROPAGATION_EXCLUDE_PORTS=8123 config from the global
agent.config default to the clickhouse-0.3.1 E2E test scenario only,
as requested in code review.
* <p>Example – also exclude port 9200 (Elasticsearch):
* {@code plugin.httpclient.propagation_exclude_ports=8123,9200}
*/
public static String PROPAGATION_EXCLUDE_PORTS = "8123";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default value should be removed. No default to exclude. The config item plugin.httpclient.propagation_exclude_ports should be a part of config file, but also have an empty value.

startScript: ./bin/startup.sh
environment:
- SW_JDBC_TRACE_SQL_PARAMETERS=true
- SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS=8123
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This never works, if you don't put the config in the agent.config. The plugin test passed just because you hard coded default value.

…ion_exclude_ports

- Change PROPAGATION_EXCLUDE_PORTS default from "8123" to "" (no ports excluded by default)
- Add config entry back to agent.config with empty default so env var SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS works correctly
- E2E clickhouse test sets the env var to "8123" explicitly
@daguimu
Copy link
Contributor Author

daguimu commented Mar 26, 2026

Fixed both issues in the latest commit (6d822b2):

  1. Removed default value: PROPAGATION_EXCLUDE_PORTS default changed from "8123" to "" — no ports excluded by default.
  2. Restored agent.config entry with empty default so the env var SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS works correctly via ConfigInitializer:
    plugin.httpclient.propagation_exclude_ports=${SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS:}
    
  3. The clickhouse-0.3.1 E2E test sets SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS=8123 explicitly, which now flows through agent.configConfigInitializerHttpClientPluginConfig as expected.

@wu-sheng wu-sheng merged commit b1351bc into apache:main Mar 26, 2026
206 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] clickhouse query failed when client enhance by skywalking-agent

3 participants