diff --git a/docs/instrumentation-list.yaml b/docs/instrumentation-list.yaml
index e78ac4009a86..c26a929d6547 100644
--- a/docs/instrumentation-list.yaml
+++ b/docs/instrumentation-list.yaml
@@ -7229,12 +7229,122 @@ libraries:
- io.ktor:ktor-client-core:3.0.0
kubernetes:
- name: kubernetes-client-7.0
+ display_name: Kubernetes Client
+ description: This instrumentation enables HTTP client spans and HTTP client metrics
+ for the Kubernetes Client for Java.
+ semantic_conventions:
+ - HTTP_CLIENT_SPANS
+ - HTTP_CLIENT_METRICS
+ library_link: https://github.com/kubernetes-client/java
source_path: instrumentation/kubernetes-client-7.0
scope:
name: io.opentelemetry.kubernetes-client-7.0
+ schema_url: https://opentelemetry.io/schemas/1.37.0
target_versions:
javaagent:
- io.kubernetes:client-java-api:[7.0.0,)
+ configurations:
+ - name: otel.instrumentation.kubernetes-client.experimental-span-attributes
+ description: |
+ Enables experimental span attributes `kubernetes-client.namespace` and `kubernetes-client.name` for Kubernetes API requests.
+ type: boolean
+ default: false
+ - name: otel.instrumentation.http.known-methods
+ description: |
+ Configures the instrumentation to recognize an alternative set of HTTP request methods. All other methods will be treated as `_OTHER`.
+ type: list
+ default: CONNECT,DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,TRACE
+ - name: otel.instrumentation.http.client.capture-request-headers
+ description: List of HTTP request headers to capture in HTTP client telemetry.
+ type: list
+ default: ''
+ - name: otel.instrumentation.http.client.capture-response-headers
+ description: List of HTTP response headers to capture in HTTP client telemetry.
+ type: list
+ default: ''
+ - name: otel.instrumentation.common.peer-service-mapping
+ description: Used to specify a mapping from host names or IP addresses to peer
+ services.
+ type: map
+ default: ''
+ - name: otel.instrumentation.http.client.emit-experimental-telemetry
+ description: |
+ Enable the capture of experimental HTTP client telemetry. Adds the `http.request.body.size` and `http.response.body.size` attributes to spans, and records `http.client.request.size` and `http.client.response.size` metrics.
+ type: boolean
+ default: false
+ - name: otel.instrumentation.http.client.experimental.redact-query-parameters
+ description: Redact sensitive URL parameters. See https://opentelemetry.io/docs/specs/semconv/http/http-spans.
+ type: boolean
+ default: true
+ telemetry:
+ - when: default
+ metrics:
+ - name: http.client.request.duration
+ description: Duration of HTTP client requests.
+ type: HISTOGRAM
+ unit: s
+ attributes:
+ - name: http.request.method
+ type: STRING
+ - name: http.response.status_code
+ type: LONG
+ - name: server.address
+ type: STRING
+ - name: server.port
+ type: LONG
+ spans:
+ - span_kind: CLIENT
+ attributes:
+ - name: error.type
+ type: STRING
+ - name: http.request.method
+ type: STRING
+ - name: http.response.status_code
+ type: LONG
+ - name: peer.service
+ type: STRING
+ - name: server.address
+ type: STRING
+ - name: server.port
+ type: LONG
+ - name: url.full
+ type: STRING
+ - when: otel.instrumentation.kubernetes-client.experimental-span-attributes=true
+ metrics:
+ - name: http.client.request.duration
+ description: Duration of HTTP client requests.
+ type: HISTOGRAM
+ unit: s
+ attributes:
+ - name: http.request.method
+ type: STRING
+ - name: http.response.status_code
+ type: LONG
+ - name: server.address
+ type: STRING
+ - name: server.port
+ type: LONG
+ spans:
+ - span_kind: CLIENT
+ attributes:
+ - name: error.type
+ type: STRING
+ - name: http.request.method
+ type: STRING
+ - name: http.response.status_code
+ type: LONG
+ - name: kubernetes-client.name
+ type: STRING
+ - name: kubernetes-client.namespace
+ type: STRING
+ - name: peer.service
+ type: STRING
+ - name: server.address
+ type: STRING
+ - name: server.port
+ type: LONG
+ - name: url.full
+ type: STRING
lettuce:
- name: lettuce-4.0
source_path: instrumentation/lettuce/lettuce-4.0
diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md
index 50a71271473b..2479eb4dc1a1 100644
--- a/docs/supported-libraries.md
+++ b/docs/supported-libraries.md
@@ -96,13 +96,13 @@ These are the supported libraries and frameworks:
| [JBoss Log Manager](https://github.com/jboss-logging/jboss-logmanager) | 1.1+ | N/A | none |
| [JDBC](https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html) | Java 8+ | [opentelemetry-jdbc](../instrumentation/jdbc/library) | [Database Client Spans], [Database Client Metrics] [6] |
| [Jedis](https://github.com/xetorthio/jedis) | 1.4+ | N/A | [Database Client Spans], [Database Client Metrics] [6] |
-| [JFinal](https://github.com/jfinal/jfinal) | 3.2+ | N/A | Provides `http.route` [2], Controller Spans [3] |
+| [JFinal](https://github.com/jfinal/jfinal) | 3.2+ | N/A | Provides `http.route` [2], Controller Spans [3] |
| [JMS](https://javaee.github.io/javaee-spec/javadocs/javax/jms/package-summary.html) | 1.1+ | N/A | [Messaging Spans] |
| [Jodd Http](https://http.jodd.org/) | 4.2+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
| [JSP](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/jsp/package-summary.html) | 2.3.x only | N/A | Controller Spans [3] |
| [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html) | 1.0+ | N/A | Context propagation |
| [Ktor](https://github.com/ktorio/ktor) | 1.0+ | [opentelemetry-ktor-1.0](../instrumentation/ktor/ktor-1.0/library),
[opentelemetry-ktor-2.0](../instrumentation/ktor/ktor-2.0/library),
[opentelemetry-ktor-3.0](../instrumentation/ktor/ktor-3.0/library) | [HTTP Client Spans], [HTTP Client Metrics], [HTTP Server Spans], [HTTP Server Metrics] |
-| [Kubernetes Client](https://github.com/kubernetes-client/java) | 7.0+ | N/A | [HTTP Client Spans] |
+| [Kubernetes Client](https://github.com/kubernetes-client/java) | 7.0+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
| [Lettuce](https://github.com/lettuce-io/lettuce-core) | 4.0+ | [opentelemetry-lettuce-5.1](../instrumentation/lettuce/lettuce-5.1/library) | [Database Client Spans], [Database Client Metrics] [6] |
| [Log4j 1](https://logging.apache.org/log4j/1.2/) | 1.2+ | N/A | none |
| [Log4j 2](https://logging.apache.org/log4j/2.x/) | 2.11+ | [opentelemetry-log4j-appender-2.17](../instrumentation/log4j/log4j-appender-2.17/library),
[opentelemetry-log4j-context-data-2.17-autoconfigure](../instrumentation/log4j/log4j-context-data/log4j-context-data-2.17/library-autoconfigure) | none |
diff --git a/instrumentation-docs/instrumentations.sh b/instrumentation-docs/instrumentations.sh
index c2e1c2d0d2ea..cea6a994eeeb 100755
--- a/instrumentation-docs/instrumentations.sh
+++ b/instrumentation-docs/instrumentations.sh
@@ -150,6 +150,8 @@ readonly INSTRUMENTATIONS=(
"jsp-2.3:javaagent:testExperimental"
"kafka:kafka-clients:kafka-clients-2.6:library:test"
"kafka:kafka-connect-2.6:testing:test"
+ "kubernetes-client-7.0:javaagent:test"
+ "kubernetes-client-7.0:javaagent:testExperimental"
"nats:nats-2.17:javaagent:test"
"nats:nats-2.17:javaagent:testExperimental"
"netty:netty-3.8:javaagent:test"
diff --git a/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts b/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts
index eb53c8f01a54..657ab4ef6557 100644
--- a/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts
+++ b/instrumentation/kubernetes-client-7.0/javaagent/build.gradle.kts
@@ -39,7 +39,20 @@ tasks {
}
}
-tasks.withType().configureEach {
- // TODO run tests both with and without experimental span attributes
- jvmArgs("-Dotel.instrumentation.kubernetes-client.experimental-span-attributes=true")
+tasks {
+ withType().configureEach {
+ systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false")
+ }
+
+ val testExperimental by registering(Test::class) {
+ testClassesDirs = sourceSets.test.get().output.classesDirs
+ classpath = sourceSets.test.get().runtimeClasspath
+
+ jvmArgs("-Dotel.instrumentation.kubernetes-client.experimental-span-attributes=true")
+ systemProperty("metadataConfig", "otel.instrumentation.kubernetes-client.experimental-span-attributes=true")
+ }
+
+ check {
+ dependsOn(testExperimental)
+ }
}
diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTest.java b/instrumentation/kubernetes-client-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTest.java
index 3dcdec9b92b8..033c22279f88 100644
--- a/instrumentation/kubernetes-client-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTest.java
+++ b/instrumentation/kubernetes-client-7.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientTest.java
@@ -5,7 +5,9 @@
package io.opentelemetry.javaagent.instrumentation.kubernetesclient;
+import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil.orderByRootSpanName;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
@@ -20,7 +22,6 @@
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
@@ -33,6 +34,7 @@
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -49,6 +51,14 @@ class KubernetesClientTest {
private CoreV1Api coreV1Api;
+ @Nullable
+ private static String experimental(String value) {
+ if (Boolean.getBoolean("otel.instrumentation.kubernetes-client.experimental-span-attributes")) {
+ return value;
+ }
+ return null;
+ }
+
@BeforeEach
void beforeEach() {
mockWebServer.start();
@@ -92,8 +102,23 @@ void synchronousCall() throws ApiException {
equalTo(SERVER_PORT, mockWebServer.httpPort()),
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name"))));
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name")))));
+
+ testing.waitAndAssertMetrics(
+ "io.opentelemetry.kubernetes-client-7.0",
+ "http.client.request.duration",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("Duration of HTTP client requests.")
+ .hasUnit("s")
+ .hasHistogramSatisfying(
+ histogram ->
+ histogram.hasPointsSatisfying(
+ point -> point.hasSumGreaterThan(0.0)))));
}
@Test
@@ -103,10 +128,7 @@ void handleErrorsInSyncCall() {
ApiException exception = null;
try {
testing.runWithSpan(
- "parent",
- () -> {
- coreV1Api.connectGetNamespacedPodProxy("name", "namespace", "path");
- });
+ "parent", () -> coreV1Api.connectGetNamespacedPodProxy("name", "namespace", "path"));
} catch (ApiException e) {
exception = e;
}
@@ -141,8 +163,9 @@ void handleErrorsInSyncCall() {
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(ERROR_TYPE, "451"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name"))));
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name")))));
}
@Test
@@ -154,21 +177,20 @@ void asynchronousCall() throws ApiException, InterruptedException {
testing.runWithSpan(
"parent",
- () -> {
- coreV1Api.connectGetNamespacedPodProxyAsync(
- "name",
- "namespace",
- "path",
- new ApiCallbackTemplate() {
- @Override
- public void onSuccess(
- String result, int statusCode, Map> responseHeaders) {
- responseBodyReference.set(result);
- countDownLatch.countDown();
- testing.runWithSpan("callback", () -> {});
- }
- });
- });
+ () ->
+ coreV1Api.connectGetNamespacedPodProxyAsync(
+ "name",
+ "namespace",
+ "path",
+ new ApiCallbackTemplate() {
+ @Override
+ public void onSuccess(
+ String result, int statusCode, Map> responseHeaders) {
+ responseBodyReference.set(result);
+ countDownLatch.countDown();
+ testing.runWithSpan("callback", () -> {});
+ }
+ }));
countDownLatch.await();
@@ -195,8 +217,9 @@ public void onSuccess(
equalTo(SERVER_PORT, mockWebServer.httpPort()),
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")),
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name"))),
span ->
span.hasName("callback")
.hasKind(SpanKind.INTERNAL)
@@ -214,21 +237,20 @@ void handleErrorsInAsynchronousCall() throws ApiException, InterruptedException
testing.runWithSpan(
"parent",
- () -> {
- coreV1Api.connectGetNamespacedPodProxyAsync(
- "name",
- "namespace",
- "path",
- new ApiCallbackTemplate() {
- @Override
- public void onFailure(
- ApiException e, int statusCode, Map> responseHeaders) {
- exceptionReference.set(e);
- countDownLatch.countDown();
- testing.runWithSpan("callback", () -> {});
- }
- });
- });
+ () ->
+ coreV1Api.connectGetNamespacedPodProxyAsync(
+ "name",
+ "namespace",
+ "path",
+ new ApiCallbackTemplate() {
+ @Override
+ public void onFailure(
+ ApiException e, int statusCode, Map> responseHeaders) {
+ exceptionReference.set(e);
+ countDownLatch.countDown();
+ testing.runWithSpan("callback", () -> {});
+ }
+ }));
countDownLatch.await();
@@ -258,8 +280,9 @@ public void onFailure(
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(ERROR_TYPE, "451"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")),
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name"))),
span ->
span.hasName("callback")
.hasKind(SpanKind.INTERNAL)
diff --git a/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java b/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java
index 0a89e46650ea..34d47e5e6cd8 100644
--- a/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java
+++ b/instrumentation/kubernetes-client-7.0/javaagent/src/version20Test/java/io/opentelemetry/javaagent/instrumentation/kubernetesclient/KubernetesClientVer20Test.java
@@ -5,7 +5,9 @@
package io.opentelemetry.javaagent.instrumentation.kubernetesclient;
+import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil.orderByRootSpanName;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
@@ -20,7 +22,6 @@
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
-import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
@@ -33,6 +34,7 @@
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -49,6 +51,14 @@ class KubernetesClientVer20Test {
private CoreV1Api coreV1Api;
+ @Nullable
+ private static String experimental(String value) {
+ if (Boolean.getBoolean("otel.instrumentation.kubernetes-client.experimental-span-attributes")) {
+ return value;
+ }
+ return null;
+ }
+
@BeforeEach
void beforeEach() {
mockWebServer.start();
@@ -96,8 +106,23 @@ void synchronousCall() throws ApiException {
equalTo(SERVER_PORT, mockWebServer.httpPort()),
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name"))));
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name")))));
+
+ testing.waitAndAssertMetrics(
+ "io.opentelemetry.kubernetes-client-7.0",
+ "http.client.request.duration",
+ metrics ->
+ metrics.anySatisfy(
+ metric ->
+ assertThat(metric)
+ .hasDescription("Duration of HTTP client requests.")
+ .hasUnit("s")
+ .hasHistogramSatisfying(
+ histogram ->
+ histogram.hasPointsSatisfying(
+ point -> point.hasSumGreaterThan(0.0)))));
}
@Test
@@ -108,9 +133,10 @@ void handleErrorsInSyncCall() {
try {
testing.runWithSpan(
"parent",
- () -> {
- coreV1Api.connectGetNamespacedPodProxyWithPath("name", "namespace", "path").execute();
- });
+ () ->
+ coreV1Api
+ .connectGetNamespacedPodProxyWithPath("name", "namespace", "path")
+ .execute());
} catch (ApiException e) {
exception = e;
}
@@ -145,8 +171,9 @@ void handleErrorsInSyncCall() {
equalTo(ERROR_TYPE, "451"),
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name"))));
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name")))));
}
@Test
@@ -158,20 +185,21 @@ void asynchronousCall() throws ApiException, InterruptedException {
testing.runWithSpan(
"parent",
- () -> {
- coreV1Api
- .connectGetNamespacedPodProxyWithPath("name", "namespace", "path")
- .executeAsync(
- new ApiCallbackTemplate() {
- @Override
- public void onSuccess(
- String result, int statusCode, Map> responseHeaders) {
- responseBodyReference.set(result);
- countDownLatch.countDown();
- testing.runWithSpan("callback", () -> {});
- }
- });
- });
+ () ->
+ coreV1Api
+ .connectGetNamespacedPodProxyWithPath("name", "namespace", "path")
+ .executeAsync(
+ new ApiCallbackTemplate() {
+ @Override
+ public void onSuccess(
+ String result,
+ int statusCode,
+ Map> responseHeaders) {
+ responseBodyReference.set(result);
+ countDownLatch.countDown();
+ testing.runWithSpan("callback", () -> {});
+ }
+ }));
countDownLatch.await();
@@ -198,8 +226,9 @@ public void onSuccess(
equalTo(SERVER_PORT, mockWebServer.httpPort()),
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")),
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name"))),
span ->
span.hasName("callback")
.hasKind(SpanKind.INTERNAL)
@@ -217,20 +246,21 @@ void handleErrorsInAsynchronousCall() throws ApiException, InterruptedException
testing.runWithSpan(
"parent",
- () -> {
- coreV1Api
- .connectGetNamespacedPodProxyWithPath("name", "namespace", "path")
- .executeAsync(
- new ApiCallbackTemplate() {
- @Override
- public void onFailure(
- ApiException e, int statusCode, Map> responseHeaders) {
- exceptionReference.set(e);
- countDownLatch.countDown();
- testing.runWithSpan("callback", () -> {});
- }
- });
- });
+ () ->
+ coreV1Api
+ .connectGetNamespacedPodProxyWithPath("name", "namespace", "path")
+ .executeAsync(
+ new ApiCallbackTemplate() {
+ @Override
+ public void onFailure(
+ ApiException e,
+ int statusCode,
+ Map> responseHeaders) {
+ exceptionReference.set(e);
+ countDownLatch.countDown();
+ testing.runWithSpan("callback", () -> {});
+ }
+ }));
countDownLatch.await();
@@ -260,8 +290,9 @@ public void onFailure(
equalTo(ERROR_TYPE, "451"),
equalTo(PEER_SERVICE, "test-peer-service"),
equalTo(
- AttributeKey.stringKey("kubernetes-client.namespace"), "namespace"),
- equalTo(AttributeKey.stringKey("kubernetes-client.name"), "name")),
+ stringKey("kubernetes-client.namespace"),
+ experimental("namespace")),
+ equalTo(stringKey("kubernetes-client.name"), experimental("name"))),
span ->
span.hasName("callback")
.hasKind(SpanKind.INTERNAL)
diff --git a/instrumentation/kubernetes-client-7.0/metadata.yaml b/instrumentation/kubernetes-client-7.0/metadata.yaml
new file mode 100644
index 000000000000..a6825eac17ea
--- /dev/null
+++ b/instrumentation/kubernetes-client-7.0/metadata.yaml
@@ -0,0 +1,42 @@
+description: This instrumentation enables HTTP client spans and HTTP client metrics for the Kubernetes Client for Java.
+display_name: Kubernetes Client
+semantic_conventions:
+ - HTTP_CLIENT_SPANS
+ - HTTP_CLIENT_METRICS
+library_link: https://github.com/kubernetes-client/java
+configurations:
+ - name: otel.instrumentation.kubernetes-client.experimental-span-attributes
+ description: >
+ Enables experimental span attributes `kubernetes-client.namespace` and
+ `kubernetes-client.name` for Kubernetes API requests.
+ type: boolean
+ default: false
+ - name: otel.instrumentation.http.known-methods
+ description: >
+ Configures the instrumentation to recognize an alternative set of HTTP request methods. All
+ other methods will be treated as `_OTHER`.
+ type: list
+ default: "CONNECT,DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT,TRACE"
+ - name: otel.instrumentation.http.client.capture-request-headers
+ description: List of HTTP request headers to capture in HTTP client telemetry.
+ type: list
+ default: ""
+ - name: otel.instrumentation.http.client.capture-response-headers
+ description: List of HTTP response headers to capture in HTTP client telemetry.
+ type: list
+ default: ""
+ - name: otel.instrumentation.common.peer-service-mapping
+ description: Used to specify a mapping from host names or IP addresses to peer services.
+ type: map
+ default: ""
+ - name: otel.instrumentation.http.client.emit-experimental-telemetry
+ description: >
+ Enable the capture of experimental HTTP client telemetry. Adds the `http.request.body.size`
+ and `http.response.body.size` attributes to spans, and records `http.client.request.size` and
+ `http.client.response.size` metrics.
+ type: boolean
+ default: false
+ - name: otel.instrumentation.http.client.experimental.redact-query-parameters
+ description: Redact sensitive URL parameters. See https://opentelemetry.io/docs/specs/semconv/http/http-spans.
+ type: boolean
+ default: true
\ No newline at end of file