Skip to content

Commit ad809ee

Browse files
authored
Merge branch 'main' into test-native
2 parents 474c57b + 6d6915e commit ad809ee

File tree

31 files changed

+492
-154
lines changed

31 files changed

+492
-154
lines changed

benchmark-overhead/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plugins {
22
id("java")
3-
id("com.diffplug.spotless") version "8.0.0"
3+
id("com.diffplug.spotless") version "8.1.0"
44
}
55

66
spotless {

conventions/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
plugins {
22
`kotlin-dsl`
33
// When updating, update below in dependencies too
4-
id("com.diffplug.spotless") version "8.0.0"
4+
id("com.diffplug.spotless") version "8.1.0"
55
}
66

77
spotless {
@@ -54,7 +54,7 @@ dependencies {
5454
implementation("org.apache.maven:maven-aether-provider:3.3.9")
5555

5656
// When updating, update above in plugins too
57-
implementation("com.diffplug.spotless:spotless-plugin-gradle:8.0.0")
57+
implementation("com.diffplug.spotless:spotless-plugin-gradle:8.1.0")
5858
implementation("com.google.guava:guava:33.5.0-jre")
5959
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.2.2")
6060
implementation("org.apache.httpcomponents:httpclient:4.5.14")

examples/distro/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ buildscript {
1212
}
1313
}
1414
dependencies {
15-
classpath "com.diffplug.spotless:spotless-plugin-gradle:8.0.0"
15+
classpath "com.diffplug.spotless:spotless-plugin-gradle:8.1.0"
1616
classpath "com.gradleup.shadow:shadow-gradle-plugin:9.2.2"
1717
classpath "io.opentelemetry.instrumentation:gradle-plugins:2.22.0-alpha-SNAPSHOT"
1818
}

examples/extension/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ plugins {
1111
See https://imperceptiblethoughts.com/shadow/ for more details about Shadow plugin.
1212
*/
1313
id "com.gradleup.shadow" version "9.2.2"
14-
id "com.diffplug.spotless" version "8.0.0"
14+
id "com.diffplug.spotless" version "8.1.0"
1515

1616
id "io.opentelemetry.instrumentation.muzzle-generation" version "2.22.0-alpha-SNAPSHOT"
1717
id "io.opentelemetry.instrumentation.muzzle-check" version "2.22.0-alpha-SNAPSHOT"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
plugins {
2+
id("otel.javaagent-testing")
3+
}
4+
5+
dependencies {
6+
testInstrumentation(project(":instrumentation:http-url-connection:javaagent"))
7+
8+
testImplementation(project(":testing-common"))
9+
}
10+
11+
tasks {
12+
test {
13+
jvmArgs(
14+
"-Dotel.experimental.config.file=$projectDir/src/test/resources/declarative-config.yaml"
15+
)
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.incubator.semconv.http;
7+
8+
import static io.opentelemetry.semconv.incubating.UrlIncubatingAttributes.URL_TEMPLATE;
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
11+
import io.opentelemetry.api.trace.SpanKind;
12+
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
13+
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
14+
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestServer;
15+
import io.opentelemetry.sdk.trace.data.StatusData;
16+
import java.net.HttpURLConnection;
17+
import java.net.URI;
18+
import org.junit.jupiter.api.AfterAll;
19+
import org.junit.jupiter.api.BeforeAll;
20+
import org.junit.jupiter.api.Test;
21+
import org.junit.jupiter.api.extension.RegisterExtension;
22+
23+
class HttpClientUrlTemplateCustomizerTest {
24+
private static HttpClientTestServer server;
25+
26+
@RegisterExtension
27+
static InstrumentationExtension testing = AgentInstrumentationExtension.create();
28+
29+
@BeforeAll
30+
static void setUp() {
31+
server = new HttpClientTestServer(testing.getOpenTelemetry());
32+
server.start();
33+
}
34+
35+
@AfterAll
36+
static void tearDown() {
37+
server.stop();
38+
}
39+
40+
@Test
41+
void test() throws Exception {
42+
URI uri = URI.create("http://localhost:" + server.httpPort() + "/hello/world");
43+
HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
44+
connection.getInputStream().close();
45+
int responseCode = connection.getResponseCode();
46+
connection.disconnect();
47+
48+
assertThat(responseCode).isEqualTo(200);
49+
50+
testing.waitAndAssertTraces(
51+
trace ->
52+
trace.hasSpansSatisfyingExactly(
53+
span ->
54+
span.hasName("GET /hello/*")
55+
.hasNoParent()
56+
.hasKind(SpanKind.CLIENT)
57+
.hasAttribute(URL_TEMPLATE, "/hello/*")
58+
.hasStatus(StatusData.unset()),
59+
span ->
60+
span.hasName("test-http-server")
61+
.hasParent(trace.getSpan(0))
62+
.hasKind(SpanKind.SERVER)));
63+
}
64+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
file_format: "1.0-rc.1"
2+
propagator:
3+
composite_list: "tracecontext"
4+
instrumentation/development:
5+
java:
6+
http:
7+
client:
8+
emit_experimental_telemetry: true
9+
url_template_rules:
10+
- pattern: "http://localhost:.*/hello/.*"
11+
template: "/hello/*"

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/builder/internal/DefaultHttpClientInstrumenterBuilder.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
import io.opentelemetry.context.Context;
1212
import io.opentelemetry.context.propagation.TextMapSetter;
1313
import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig;
14-
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalAttributesGetter;
1514
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics;
1615
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor;
17-
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientUrlTemplate;
1816
import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpExperimentalAttributesExtractor;
17+
import io.opentelemetry.instrumentation.api.incubator.semconv.http.internal.HttpClientUrlTemplateUtil;
1918
import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver;
2019
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
2120
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
@@ -37,7 +36,6 @@
3736
import java.util.List;
3837
import java.util.Objects;
3938
import java.util.function.Consumer;
40-
import java.util.function.Function;
4139
import java.util.function.Supplier;
4240
import java.util.function.UnaryOperator;
4341
import javax.annotation.Nullable;
@@ -222,19 +220,11 @@ public DefaultHttpClientInstrumenterBuilder<REQUEST, RESPONSE> setBuilderCustomi
222220

223221
public Instrumenter<REQUEST, RESPONSE> build() {
224222
if (emitExperimentalHttpClientTelemetry) {
225-
Function<REQUEST, String> urlTemplateExtractorFunction = unused -> null;
226-
if (attributesGetter instanceof HttpClientExperimentalAttributesGetter) {
227-
HttpClientExperimentalAttributesGetter<REQUEST, RESPONSE> experimentalAttributesGetter =
228-
(HttpClientExperimentalAttributesGetter<REQUEST, RESPONSE>) attributesGetter;
229-
urlTemplateExtractorFunction = experimentalAttributesGetter::getUrlTemplate;
230-
}
231-
Function<REQUEST, String> urlTemplateExtractor = urlTemplateExtractorFunction;
232223
Experimental.setUrlTemplateExtractor(
233224
httpSpanNameExtractorBuilder,
234-
request -> {
235-
String urlTemplate = HttpClientUrlTemplate.get(Context.current());
236-
return urlTemplate != null ? urlTemplate : urlTemplateExtractor.apply(request);
237-
});
225+
request ->
226+
HttpClientUrlTemplateUtil.getUrlTemplate(
227+
Context.current(), request, attributesGetter));
238228
}
239229
SpanNameExtractor<? super REQUEST> spanNameExtractor =
240230
spanNameExtractorTransformer.apply(httpSpanNameExtractorBuilder.build());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.incubator.semconv.http;
7+
8+
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter;
9+
import javax.annotation.Nullable;
10+
11+
/** A service provider interface (SPI) for customizing http client url template. */
12+
public interface HttpClientUrlTemplateCustomizer {
13+
14+
/**
15+
* Customize url template for given request. Typically, the customizer will extract full url from
16+
* the request and apply some logic (e.g. regex matching) to generate url template. The customizer
17+
* can choose to override existing url template or skip customization when a url template is
18+
* already set.
19+
*
20+
* @param urlTemplate existing url template, can be null
21+
* @param request current request
22+
* @param getter request attributes getter
23+
* @return customized url template, or null
24+
*/
25+
@Nullable
26+
<REQUEST> String customize(
27+
@Nullable String urlTemplate, REQUEST request, HttpClientAttributesGetter<REQUEST, ?> getter);
28+
}

instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/http/HttpExperimentalAttributesExtractor.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.opentelemetry.api.common.AttributeKey;
1111
import io.opentelemetry.api.common.AttributesBuilder;
1212
import io.opentelemetry.context.Context;
13+
import io.opentelemetry.instrumentation.api.incubator.semconv.http.internal.HttpClientUrlTemplateUtil;
1314
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1415
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesGetter;
1516
import io.opentelemetry.instrumentation.api.semconv.http.HttpCommonAttributesGetter;
@@ -47,7 +48,15 @@ private HttpExperimentalAttributesExtractor(
4748
}
4849

4950
@Override
50-
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {}
51+
public void onStart(AttributesBuilder attributes, Context parentContext, REQUEST request) {
52+
if (getter instanceof HttpClientAttributesGetter) {
53+
HttpClientAttributesGetter<REQUEST, RESPONSE> clientGetter =
54+
(HttpClientAttributesGetter<REQUEST, RESPONSE>) getter;
55+
String urlTemplate =
56+
HttpClientUrlTemplateUtil.getUrlTemplate(parentContext, request, clientGetter);
57+
internalSet(attributes, URL_TEMPLATE, urlTemplate);
58+
}
59+
}
5160

5261
@Override
5362
public void onEnd(
@@ -64,15 +73,6 @@ public void onEnd(
6473
Long responseBodySize = responseBodySize(request, response);
6574
internalSet(attributes, HTTP_RESPONSE_BODY_SIZE, responseBodySize);
6675
}
67-
68-
String urlTemplate = HttpClientUrlTemplate.get(context);
69-
if (urlTemplate != null) {
70-
internalSet(attributes, URL_TEMPLATE, urlTemplate);
71-
} else if (getter instanceof HttpClientExperimentalAttributesGetter) {
72-
HttpClientExperimentalAttributesGetter<REQUEST, RESPONSE> experimentalGetter =
73-
(HttpClientExperimentalAttributesGetter<REQUEST, RESPONSE>) getter;
74-
internalSet(attributes, URL_TEMPLATE, experimentalGetter.getUrlTemplate(request));
75-
}
7676
}
7777

7878
@Nullable

0 commit comments

Comments
 (0)