This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new b59a37efd89c CAMEL-26490: camel-telemetry, camel-tracing - present the
http.url, url.path and server.address span attributes like camel.uri (#28867)
b59a37efd89c is described below
commit b59a37efd89ce4c3997ae4717602fceff593da10
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Nov 2 23:00:22 2026 +0100
CAMEL-26490: camel-telemetry, camel-tracing - present the http.url,
url.path and server.address span attributes like camel.uri (#28867)
Without a CamelHttpUrl or CamelHttpUri header, the http.url attribute was
the endpoint URI from the last "http:" onwards: with all the Camel endpoint
options, starting with http://https:// for vertx-http with an https address,
and not set for camel-http with an https address. It is now the service url
of the endpoint when that is an HTTP address, otherwise the endpoint URI
without the component scheme in front of the HTTP address, and without the
endpoint options.
The url.path attribute no longer includes the user info in front of the
host, and http.url and server.address are presented with
URISupport.sanitizeUri, the same way as camel.uri.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../decorators/AbstractHttpSpanDecorator.java | 41 ++++++++--
.../decorators/AbstractSpanDecorator.java | 21 ++++-
.../decorators/AbstractHttpSpanDecoratorTest.java | 95 ++++++++++++++++++++--
.../decorators/AbstractSpanDecoratorTest.java | 56 +++++++++++++
.../decorators/AbstractHttpSpanDecorator.java | 41 ++++++++--
.../tracing/decorators/AbstractSpanDecorator.java | 21 ++++-
.../decorators/AbstractHttpSpanDecoratorTest.java | 95 ++++++++++++++++++++--
.../decorators/AbstractSpanDecoratorTest.java | 56 +++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 17 ++++
9 files changed, 411 insertions(+), 32 deletions(-)
diff --git
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecorator.java
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecorator.java
index 24a1216e796c..0e3029674ab5 100644
---
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecorator.java
+++
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecorator.java
@@ -19,9 +19,12 @@ package org.apache.camel.telemetry.decorators;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
+import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.telemetry.Op;
import org.apache.camel.telemetry.Span;
import org.apache.camel.telemetry.TagConstants;
+import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.URISupport;
public abstract class AbstractHttpSpanDecorator extends AbstractSpanDecorator {
@@ -76,22 +79,46 @@ public abstract class AbstractHttpSpanDecorator extends
AbstractSpanDecorator {
}
protected String getHttpURL(Exchange exchange, Endpoint endpoint) {
+ // the url is presented the same way as the camel.uri tag
Object url = exchange.getIn().getHeader(Exchange.HTTP_URL);
if (url instanceof String str) {
- return str;
+ return URISupport.sanitizeUri(str);
} else {
Object uri = exchange.getIn().getHeader(Exchange.HTTP_URI);
if (uri instanceof String str) {
- return str;
+ return URISupport.sanitizeUri(str);
} else {
// Try to obtain from endpoint
- int index = endpoint.getEndpointUri().lastIndexOf("http:");
- if (index != -1) {
- return endpoint.getEndpointUri().substring(index);
- }
+ return URISupport.sanitizeUri(getHttpAddress(endpoint));
+ }
+ }
+ }
+
+ /**
+ * The HTTP address the endpoint sends to, without the endpoint options.
+ */
+ private static String getHttpAddress(Endpoint endpoint) {
+ // the service url of an HTTP endpoint is its HTTP address with the
query parameters that are sent
+ if (endpoint instanceof EndpointServiceLocation esl) {
+ String url = esl.getServiceUrl();
+ if (isHttpAddress(url)) {
+ return url;
}
}
- return null;
+ // otherwise take the endpoint uri, without the component scheme in
front of the HTTP address
+ // (such as netty-http:http://host or vertx-http://https://host) and
without the endpoint options
+ String uri = endpoint.getEndpointUri();
+ if (!isHttpAddress(uri)) {
+ uri = StringHelper.after(uri, ":");
+ if (uri != null && uri.startsWith("//")) {
+ uri = uri.substring(2);
+ }
+ }
+ return isHttpAddress(uri) ? URISupport.stripQuery(uri) : null;
+ }
+
+ private static boolean isHttpAddress(String uri) {
+ return uri != null && (uri.startsWith("http://") ||
uri.startsWith("https://"));
}
@Override
diff --git
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractSpanDecorator.java
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractSpanDecorator.java
index 352b3974fd4c..4cba91594b27 100644
---
a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractSpanDecorator.java
+++
b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/decorators/AbstractSpanDecorator.java
@@ -89,6 +89,22 @@ public abstract class AbstractSpanDecorator implements
SpanDecorator {
return Collections.emptyMap();
}
+ /**
+ * The path of the endpoint URI without the scheme, the user info in front
of the host and the options.
+ */
+ private static String getUrlPath(Endpoint endpoint) {
+ String path = stripSchemeAndOptions(endpoint);
+ // the user info ends at the last @ before the first /
+ int colon = path.indexOf(':');
+ int slash = path.indexOf('/');
+ int at = slash == -1 ? path.lastIndexOf('@') : path.lastIndexOf('@',
slash);
+ if (colon != -1 && colon < at) {
+ path = path.substring(at + 1);
+ }
+ // presented the same way as the camel.uri tag, for a path that is
another uri (such as netty-http:http://host)
+ return URISupport.sanitizeUri(path);
+ }
+
private static String getComponentName(Endpoint endpoint) {
String answer = endpoint.getComponent() != null ?
endpoint.getComponent().getDefaultName() : null;
if (answer == null) {
@@ -123,7 +139,7 @@ public abstract class AbstractSpanDecorator implements
SpanDecorator {
// have been provided, for subsequent analysis
String uri = endpoint.toString(); // toString will sanitize
span.setTag("camel.uri", uri);
- span.setTag(TagConstants.URL_PATH, stripSchemeAndOptions(endpoint));
+ span.setTag(TagConstants.URL_PATH, getUrlPath(endpoint));
String query = URISupport.extractQuery(uri);
if (query != null) {
span.setTag(TagConstants.URL_QUERY, query);
@@ -133,7 +149,8 @@ public abstract class AbstractSpanDecorator implements
SpanDecorator {
if (endpoint instanceof EndpointServiceLocation ela) {
String adr = ela.getServiceUrl();
if (adr != null) {
- span.setTag(TagConstants.SERVER_ADDRESS, adr);
+ // the address is presented the same way as the camel.uri tag
+ span.setTag(TagConstants.SERVER_ADDRESS,
URISupport.sanitizeUri(adr));
}
String ap = ela.getServiceProtocol();
if (ap != null) {
diff --git
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecoratorTest.java
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecoratorTest.java
index 9e7314b4e255..6b05fed0994c 100644
---
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecoratorTest.java
+++
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractHttpSpanDecoratorTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.telemetry.decorators;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
+import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.telemetry.TagConstants;
import org.apache.camel.telemetry.mock.MockSpanAdapter;
import org.junit.jupiter.api.BeforeEach;
@@ -150,9 +151,9 @@ public class AbstractHttpSpanDecoratorTest {
Exchange exchange = Mockito.mock(Exchange.class);
Message message = Mockito.mock(Message.class);
- Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("http://localhost:8080/endpoint");
Mockito.when(exchange.getIn()).thenReturn(message);
- Mockito.when(message.getHeader(Exchange.HTTP_URI,
String.class)).thenReturn(TEST_URI);
+
Mockito.when(message.getHeader(Exchange.HTTP_URI)).thenReturn(TEST_URI);
MockSpanAdapter span = new MockSpanAdapter();
@@ -168,10 +169,10 @@ public class AbstractHttpSpanDecoratorTest {
Exchange exchange = Mockito.mock(Exchange.class);
Message message = Mockito.mock(Message.class);
- Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("http://localhost:8080/endpoint");
Mockito.when(exchange.getIn()).thenReturn(message);
- Mockito.when(message.getHeader(Exchange.HTTP_URI,
String.class)).thenReturn("Another URL");
- Mockito.when(message.getHeader(Exchange.HTTP_URL,
String.class)).thenReturn(TEST_URI);
+ Mockito.when(message.getHeader(Exchange.HTTP_URI)).thenReturn("Another
URL");
+
Mockito.when(message.getHeader(Exchange.HTTP_URL)).thenReturn(TEST_URI);
assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
}
@@ -182,13 +183,26 @@ public class AbstractHttpSpanDecoratorTest {
Exchange exchange = Mockito.mock(Exchange.class);
Message message = Mockito.mock(Message.class);
- Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("http://localhost:8080/endpoint");
Mockito.when(exchange.getIn()).thenReturn(message);
- Mockito.when(message.getHeader(Exchange.HTTP_URI,
String.class)).thenReturn(TEST_URI);
+
Mockito.when(message.getHeader(Exchange.HTTP_URI)).thenReturn(TEST_URI);
assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
}
+ @Test
+ public void testGetHttpURLFromHeaderUrlPresentedLikeCamelUri() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
Mockito.when(message.getHeader(Exchange.HTTP_URL)).thenReturn("http://scott:tiger@localhost:8080/test");
+
+ assertEquals("http://scott:xxxxxx@localhost:8080/test",
decorator.getHttpURL(exchange, endpoint));
+ }
+
@Test
public void testGetHttpURLFromEndpointUri() {
Endpoint endpoint = Mockito.mock(Endpoint.class);
@@ -213,6 +227,73 @@ public class AbstractHttpSpanDecoratorTest {
assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
}
+ @Test
+ public void testGetHttpURLFromEndpointUriWithoutEndpointOptions() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI +
"?connectTimeout=5000&throwExceptionOnFailure=false");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void
testGetHttpURLFromEndpointUriWithComponentSchemeAndHttpsAddress() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("vertx-http://https://localhost:8443/test?connectTimeout=5000");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals("https://localhost:8443/test",
decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void testGetHttpURLFromServiceUrl() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("https://localhost:8443/test?q=1&connectTimeout=5000");
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("https://localhost:8443/test?q=1");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals("https://localhost:8443/test?q=1",
decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void testGetHttpURLFromEndpointUriWhenServiceUrlIsNotHttpAddress() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn("netty-http:" +
TEST_URI);
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("http:localhost:8080");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void testPreHttpsEndpoint() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("https://localhost:8443/test?connectTimeout=5000");
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("https://localhost:8443/test");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ MockSpanAdapter span = new MockSpanAdapter();
+
+ decorator.beforeTracingEvent(span, exchange, endpoint);
+
+ assertEquals("https://localhost:8443/test",
span.tags().get(TagConstants.HTTP_URL));
+ }
+
@Test
public void testPostResponseCode() {
Exchange exchange = Mockito.mock(Exchange.class);
diff --git
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractSpanDecoratorTest.java
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractSpanDecoratorTest.java
index 5bcf53a26b91..5fb9154abbc5 100644
---
a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractSpanDecoratorTest.java
+++
b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/decorators/AbstractSpanDecoratorTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.telemetry.decorators;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
+import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.telemetry.SpanDecorator;
import org.apache.camel.telemetry.TagConstants;
import org.apache.camel.telemetry.mock.MockSpanAdapter;
@@ -85,6 +86,61 @@ public class AbstractSpanDecoratorTest {
assertEquals("myRouteId", span.tags().get(TagConstants.ROUTE_ID));
}
+ @Test
+ public void testPreUrlPathWithoutUserInfo() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("ftp://scott:tiger@localhost:2121/inbox?binary=true");
+
Mockito.when(endpoint.toString()).thenReturn("ftp://scott:xxxxxx@localhost:2121/inbox?binary=true");
+
+ SpanDecorator decorator = new AbstractSpanDecorator() {
+ @Override
+ public String getComponent() {
+ return null;
+ }
+
+ @Override
+ public String getComponentClassName() {
+ return null;
+ }
+ };
+
+ MockSpanAdapter span = new MockSpanAdapter();
+
+ decorator.beforeTracingEvent(span, exchange, endpoint);
+
+ assertEquals("localhost:2121/inbox",
span.tags().get(TagConstants.URL_PATH));
+ assertEquals("binary=true", span.tags().get(TagConstants.URL_QUERY));
+ }
+
+ @Test
+ public void testPreServerAddressPresentedLikeCamelUri() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn("amqp:queue:foo");
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("amqp://scott:tiger@localhost:5672");
+
+ SpanDecorator decorator = new AbstractSpanDecorator() {
+ @Override
+ public String getComponent() {
+ return null;
+ }
+
+ @Override
+ public String getComponentClassName() {
+ return null;
+ }
+ };
+
+ MockSpanAdapter span = new MockSpanAdapter();
+
+ decorator.beforeTracingEvent(span, exchange, endpoint);
+
+ assertEquals("amqp://scott:xxxxxx@localhost:5672",
span.tags().get(TagConstants.SERVER_ADDRESS));
+ }
+
@Test
public void testPostExchangeFailed() {
Exchange exchange = Mockito.mock(Exchange.class);
diff --git
a/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecorator.java
b/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecorator.java
index 3f2468138fc3..d864456bb38f 100644
---
a/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecorator.java
+++
b/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecorator.java
@@ -19,8 +19,11 @@ package org.apache.camel.tracing.decorators;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
+import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.tracing.SpanAdapter;
import org.apache.camel.tracing.TagConstants;
+import org.apache.camel.util.StringHelper;
+import org.apache.camel.util.URISupport;
@Deprecated(since = "4.19.0")
public abstract class AbstractHttpSpanDecorator extends AbstractSpanDecorator {
@@ -76,22 +79,46 @@ public abstract class AbstractHttpSpanDecorator extends
AbstractSpanDecorator {
}
protected String getHttpURL(Exchange exchange, Endpoint endpoint) {
+ // the url is presented the same way as the camel.uri tag
Object url = exchange.getIn().getHeader(Exchange.HTTP_URL);
if (url instanceof String) {
- return (String) url;
+ return URISupport.sanitizeUri((String) url);
} else {
Object uri = exchange.getIn().getHeader(Exchange.HTTP_URI);
if (uri instanceof String) {
- return (String) uri;
+ return URISupport.sanitizeUri((String) uri);
} else {
// Try to obtain from endpoint
- int index = endpoint.getEndpointUri().lastIndexOf("http:");
- if (index != -1) {
- return endpoint.getEndpointUri().substring(index);
- }
+ return URISupport.sanitizeUri(getHttpAddress(endpoint));
}
}
- return null;
+ }
+
+ /**
+ * The HTTP address the endpoint sends to, without the endpoint options.
+ */
+ private static String getHttpAddress(Endpoint endpoint) {
+ // the service url of an HTTP endpoint is its HTTP address with the
query parameters that are sent
+ if (endpoint instanceof EndpointServiceLocation esl) {
+ String url = esl.getServiceUrl();
+ if (isHttpAddress(url)) {
+ return url;
+ }
+ }
+ // otherwise take the endpoint uri, without the component scheme in
front of the HTTP address
+ // (such as netty-http:http://host or vertx-http://https://host) and
without the endpoint options
+ String uri = endpoint.getEndpointUri();
+ if (!isHttpAddress(uri)) {
+ uri = StringHelper.after(uri, ":");
+ if (uri != null && uri.startsWith("//")) {
+ uri = uri.substring(2);
+ }
+ }
+ return isHttpAddress(uri) ? URISupport.stripQuery(uri) : null;
+ }
+
+ private static boolean isHttpAddress(String uri) {
+ return uri != null && (uri.startsWith("http://") ||
uri.startsWith("https://"));
}
@Override
diff --git
a/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractSpanDecorator.java
b/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractSpanDecorator.java
index 70b8c41b4960..9439027741f3 100644
---
a/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractSpanDecorator.java
+++
b/components/camel-tracing/src/main/java/org/apache/camel/tracing/decorators/AbstractSpanDecorator.java
@@ -88,6 +88,22 @@ public abstract class AbstractSpanDecorator implements
SpanDecorator {
return Collections.emptyMap();
}
+ /**
+ * The path of the endpoint URI without the scheme, the user info in front
of the host and the options.
+ */
+ private static String getUrlPath(Endpoint endpoint) {
+ String path = stripSchemeAndOptions(endpoint);
+ // the user info ends at the last @ before the first /
+ int colon = path.indexOf(':');
+ int slash = path.indexOf('/');
+ int at = slash == -1 ? path.lastIndexOf('@') : path.lastIndexOf('@',
slash);
+ if (colon != -1 && colon < at) {
+ path = path.substring(at + 1);
+ }
+ // presented the same way as the camel.uri tag, for a path that is
another uri (such as netty-http:http://host)
+ return URISupport.sanitizeUri(path);
+ }
+
private static String getComponentName(Endpoint endpoint) {
String answer = endpoint.getComponent() != null ?
endpoint.getComponent().getDefaultName() : null;
if (answer == null) {
@@ -129,7 +145,7 @@ public abstract class AbstractSpanDecorator implements
SpanDecorator {
// have been provided, for subsequent analysis
String uri = endpoint.toString(); // toString will sanitize
span.setTag("camel.uri", uri);
- span.setTag(TagConstants.URL_PATH, stripSchemeAndOptions(endpoint));
+ span.setTag(TagConstants.URL_PATH, getUrlPath(endpoint));
String query = URISupport.extractQuery(uri);
if (query != null) {
span.setTag(TagConstants.URL_QUERY, query);
@@ -139,7 +155,8 @@ public abstract class AbstractSpanDecorator implements
SpanDecorator {
if (endpoint instanceof EndpointServiceLocation ela) {
String adr = ela.getServiceUrl();
if (adr != null) {
- span.setTag(TagConstants.SERVER_ADDRESS, adr);
+ // the address is presented the same way as the camel.uri tag
+ span.setTag(TagConstants.SERVER_ADDRESS,
URISupport.sanitizeUri(adr));
}
String ap = ela.getServiceProtocol();
if (ap != null) {
diff --git
a/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecoratorTest.java
b/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecoratorTest.java
index 04b00e2e897d..a00e9976ceaa 100644
---
a/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecoratorTest.java
+++
b/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractHttpSpanDecoratorTest.java
@@ -19,6 +19,7 @@ package org.apache.camel.tracing.decorators;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
+import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.tracing.MockSpanAdapter;
import org.apache.camel.tracing.TagConstants;
import org.junit.jupiter.api.BeforeEach;
@@ -153,9 +154,9 @@ public class AbstractHttpSpanDecoratorTest {
Exchange exchange = Mockito.mock(Exchange.class);
Message message = Mockito.mock(Message.class);
- Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("http://localhost:8080/endpoint");
Mockito.when(exchange.getIn()).thenReturn(message);
- Mockito.when(message.getHeader(Exchange.HTTP_URI,
String.class)).thenReturn(TEST_URI);
+
Mockito.when(message.getHeader(Exchange.HTTP_URI)).thenReturn(TEST_URI);
MockSpanAdapter span = new MockSpanAdapter();
@@ -171,10 +172,10 @@ public class AbstractHttpSpanDecoratorTest {
Exchange exchange = Mockito.mock(Exchange.class);
Message message = Mockito.mock(Message.class);
- Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("http://localhost:8080/endpoint");
Mockito.when(exchange.getIn()).thenReturn(message);
- Mockito.when(message.getHeader(Exchange.HTTP_URI,
String.class)).thenReturn("Another URL");
- Mockito.when(message.getHeader(Exchange.HTTP_URL,
String.class)).thenReturn(TEST_URI);
+ Mockito.when(message.getHeader(Exchange.HTTP_URI)).thenReturn("Another
URL");
+
Mockito.when(message.getHeader(Exchange.HTTP_URL)).thenReturn(TEST_URI);
assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
}
@@ -185,13 +186,26 @@ public class AbstractHttpSpanDecoratorTest {
Exchange exchange = Mockito.mock(Exchange.class);
Message message = Mockito.mock(Message.class);
- Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("http://localhost:8080/endpoint");
Mockito.when(exchange.getIn()).thenReturn(message);
- Mockito.when(message.getHeader(Exchange.HTTP_URI,
String.class)).thenReturn(TEST_URI);
+
Mockito.when(message.getHeader(Exchange.HTTP_URI)).thenReturn(TEST_URI);
assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
}
+ @Test
+ public void testGetHttpURLFromHeaderUrlPresentedLikeCamelUri() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
Mockito.when(message.getHeader(Exchange.HTTP_URL)).thenReturn("http://scott:tiger@localhost:8080/test");
+
+ assertEquals("http://scott:xxxxxx@localhost:8080/test",
decorator.getHttpURL(exchange, endpoint));
+ }
+
@Test
public void testGetHttpURLFromEndpointUri() {
Endpoint endpoint = Mockito.mock(Endpoint.class);
@@ -216,6 +230,73 @@ public class AbstractHttpSpanDecoratorTest {
assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
}
+ @Test
+ public void testGetHttpURLFromEndpointUriWithoutEndpointOptions() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn(TEST_URI +
"?connectTimeout=5000&throwExceptionOnFailure=false");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void
testGetHttpURLFromEndpointUriWithComponentSchemeAndHttpsAddress() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("vertx-http://https://localhost:8443/test?connectTimeout=5000");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals("https://localhost:8443/test",
decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void testGetHttpURLFromServiceUrl() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("https://localhost:8443/test?q=1&connectTimeout=5000");
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("https://localhost:8443/test?q=1");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals("https://localhost:8443/test?q=1",
decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void testGetHttpURLFromEndpointUriWhenServiceUrlIsNotHttpAddress() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn("netty-http:" +
TEST_URI);
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("http:localhost:8080");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ assertEquals(TEST_URI, decorator.getHttpURL(exchange, endpoint));
+ }
+
+ @Test
+ public void testPreHttpsEndpoint() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("https://localhost:8443/test?connectTimeout=5000");
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("https://localhost:8443/test");
+ Mockito.when(exchange.getIn()).thenReturn(message);
+
+ MockSpanAdapter span = new MockSpanAdapter();
+
+ decorator.pre(span, exchange, endpoint);
+
+ assertEquals("https://localhost:8443/test",
span.tags().get(TagConstants.HTTP_URL));
+ }
+
@Test
public void testPostResponseCode() {
Exchange exchange = Mockito.mock(Exchange.class);
diff --git
a/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractSpanDecoratorTest.java
b/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractSpanDecoratorTest.java
index 318c4e9e24bf..05ce0ed75850 100644
---
a/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractSpanDecoratorTest.java
+++
b/components/camel-tracing/src/test/java/org/apache/camel/tracing/decorators/AbstractSpanDecoratorTest.java
@@ -18,6 +18,7 @@ package org.apache.camel.tracing.decorators;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
+import org.apache.camel.spi.EndpointServiceLocation;
import org.apache.camel.tracing.MockSpanAdapter;
import org.apache.camel.tracing.SpanDecorator;
import org.apache.camel.tracing.TagConstants;
@@ -87,6 +88,61 @@ public class AbstractSpanDecoratorTest {
assertEquals("myRouteId", span.tags().get(TagConstants.ROUTE_ID));
}
+ @Test
+ public void testPreUrlPathWithoutUserInfo() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class);
+ Exchange exchange = Mockito.mock(Exchange.class);
+
+
Mockito.when(endpoint.getEndpointUri()).thenReturn("ftp://scott:tiger@localhost:2121/inbox?binary=true");
+
Mockito.when(endpoint.toString()).thenReturn("ftp://scott:xxxxxx@localhost:2121/inbox?binary=true");
+
+ SpanDecorator decorator = new AbstractSpanDecorator() {
+ @Override
+ public String getComponent() {
+ return null;
+ }
+
+ @Override
+ public String getComponentClassName() {
+ return null;
+ }
+ };
+
+ MockSpanAdapter span = new MockSpanAdapter();
+
+ decorator.pre(span, exchange, endpoint);
+
+ assertEquals("localhost:2121/inbox",
span.tags().get(TagConstants.URL_PATH));
+ assertEquals("binary=true", span.tags().get(TagConstants.URL_QUERY));
+ }
+
+ @Test
+ public void testPreServerAddressPresentedLikeCamelUri() {
+ Endpoint endpoint = Mockito.mock(Endpoint.class,
Mockito.withSettings().extraInterfaces(EndpointServiceLocation.class));
+ Exchange exchange = Mockito.mock(Exchange.class);
+
+ Mockito.when(endpoint.getEndpointUri()).thenReturn("amqp:queue:foo");
+ Mockito.when(((EndpointServiceLocation)
endpoint).getServiceUrl()).thenReturn("amqp://scott:tiger@localhost:5672");
+
+ SpanDecorator decorator = new AbstractSpanDecorator() {
+ @Override
+ public String getComponent() {
+ return null;
+ }
+
+ @Override
+ public String getComponentClassName() {
+ return null;
+ }
+ };
+
+ MockSpanAdapter span = new MockSpanAdapter();
+
+ decorator.pre(span, exchange, endpoint);
+
+ assertEquals("amqp://scott:xxxxxx@localhost:5672",
span.tags().get(TagConstants.SERVER_ADDRESS));
+ }
+
@Test
public void testPostExchangeFailed() {
Exchange exchange = Mockito.mock(Exchange.class);
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index 17bb72c75f9b..7affa39a05c1 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -651,6 +651,23 @@ by the wrong events, and with a `recipientList` or
`enrich` to such a route some
This is the tree of Camel 4.16 and older, so there is no option to keep the
4.17 tree. A dashboard that read the time of
the rest of the route from the span of the asynchronous step can use the route
span instead.
+=== camel-telemetry, camel-tracing - the http.url, url.path and server.address
span attributes are presented like camel.uri
+
+This applies to `camel-opentelemetry2`, `camel-micrometer-observability`,
`camel-telemetry-dev`, `camel-opentelemetry`
+and `camel-observation`. The `http.url`, `url.path` and `server.address`
attributes of a span are now presented the same
+way as the `camel.uri` attribute, which shows the endpoint URI as
`Endpoint.toString()` does:
+
+* `http.url`, when the message has neither a `CamelHttpUrl` nor a
`CamelHttpUri` header, is now the HTTP address the
+ endpoint sends to, with the query parameters it sends but without the Camel
endpoint options. Before, it was the
+ endpoint URI from the last `http:` onwards, with all the endpoint options. A
`camel-http` endpoint with an `https`
+ address now sets the attribute as well, and for a `camel-vertx-http`
endpoint with an `https` address the value no
+ longer starts with `http://https://`.
+* `url.path` no longer includes the user info in front of the host of the
endpoint URI.
+* `server.address`, and `http.url` taken from the `CamelHttpUrl` or
`CamelHttpUri` header, are presented as `camel.uri`
+ is.
+
+Dashboards or queries that use the old values may need a change.
+
=== camel-oaipmh - the CamelOaimphOnlyFirst and CamelOaimphIgnoreSSLWarnings
headers apply to their message only
The `CamelOaimphOnlyFirst` and `CamelOaimphIgnoreSSLWarnings` headers now
apply only to the message that has them.