diff --git a/instrumentation-api-incubator/build.gradle.kts b/instrumentation-api-incubator/build.gradle.kts index 3db18fcaf65c..f08df015a3b2 100644 --- a/instrumentation-api-incubator/build.gradle.kts +++ b/instrumentation-api-incubator/build.gradle.kts @@ -86,13 +86,13 @@ tasks { val testStableSemconv by registering(Test::class) { testClassesDirs = sourceSets.test.get().output.classesDirs classpath = sourceSets.test.get().runtimeClasspath - jvmArgs("-Dotel.semconv-stability.opt-in=database,code") + jvmArgs("-Dotel.semconv-stability.opt-in=database,code,rpc") } val testBothSemconv by registering(Test::class) { testClassesDirs = sourceSets.test.get().output.classesDirs classpath = sourceSets.test.get().runtimeClasspath - jvmArgs("-Dotel.semconv-stability.opt-in=database/dup,code/dup") + jvmArgs("-Dotel.semconv-stability.opt-in=database/dup,code/dup,rpc/dup") } check { diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcAttributesGetter.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcAttributesGetter.java index 0da544340f6b..f3ddc224c8c7 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcAttributesGetter.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcAttributesGetter.java @@ -34,4 +34,24 @@ default Long getRequestSize(REQUEST request) { default Long getResponseSize(REQUEST request) { return null; } + + /** + * Returns the fully-qualified RPC method name for stable semconv. + * + *
The default implementation concatenates service + "/" + method. Framework implementations
+ * can override for efficiency if they already have the fully-qualified name available.
+ *
+ * @param request the request object
+ * @return the fully-qualified RPC method name (e.g., "my.Service/Method"), or null if service or
+ * method is unavailable
+ */
+ @Nullable
+ default String getFullMethod(REQUEST request) {
+ String service = getService(request);
+ String method = getMethod(request);
+ if (service == null || method == null) {
+ return null;
+ }
+ return service + "/" + method;
+ }
}
diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcClientMetrics.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcClientMetrics.java
index 0135bd20f799..bf686c7ec5a4 100644
--- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcClientMetrics.java
+++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcClientMetrics.java
@@ -19,8 +19,10 @@
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
import io.opentelemetry.instrumentation.api.internal.OperationMetricsUtil;
+import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
+import javax.annotation.Nullable;
/**
* {@link OperationListener} which keeps track of RPC_CLIENT_REQUEST_METRICS_STATE =
ContextKey.named("rpc-client-request-metrics-state");
private static final Logger logger = Logger.getLogger(RpcClientMetrics.class.getName());
- private final DoubleHistogram clientDurationHistogram;
- private final LongHistogram clientRequestSize;
- private final LongHistogram clientResponseSize;
+ @Nullable private final DoubleHistogram oldClientDurationHistogram;
+ @Nullable private final DoubleHistogram stableClientDurationHistogram;
+ private final LongHistogram oldClientRequestSize;
+ private final LongHistogram oldClientResponseSize;
private RpcClientMetrics(Meter meter) {
- DoubleHistogramBuilder durationBuilder =
- meter
- .histogramBuilder("rpc.client.duration")
- .setDescription("The duration of an outbound RPC invocation.")
- .setUnit("ms");
- RpcMetricsAdvice.applyClientDurationAdvice(durationBuilder);
- clientDurationHistogram = durationBuilder.build();
+ // Old metric (milliseconds)
+ if (SemconvStability.emitOldRpcSemconv()) {
+ DoubleHistogramBuilder oldDurationBuilder =
+ meter
+ .histogramBuilder("rpc.client.duration")
+ .setDescription("The duration of an outbound RPC invocation.")
+ .setUnit("ms");
+ RpcMetricsAdvice.applyClientDurationAdvice(oldDurationBuilder, false);
+ oldClientDurationHistogram = oldDurationBuilder.build();
+ } else {
+ oldClientDurationHistogram = null;
+ }
+
+ // Stable metric (seconds)
+ if (SemconvStability.emitStableRpcSemconv()) {
+ DoubleHistogramBuilder stableDurationBuilder =
+ meter
+ .histogramBuilder("rpc.client.call.duration")
+ .setDescription("The duration of an outbound RPC invocation.")
+ .setUnit("s");
+ RpcMetricsAdvice.applyClientDurationAdvice(stableDurationBuilder, true);
+ stableClientDurationHistogram = stableDurationBuilder.build();
+ } else {
+ stableClientDurationHistogram = null;
+ }
LongHistogramBuilder requestSizeBuilder =
meter
@@ -55,8 +77,8 @@ private RpcClientMetrics(Meter meter) {
.setUnit("By")
.setDescription("Measures the size of RPC request messages (uncompressed).")
.ofLongs();
- RpcMetricsAdvice.applyClientRequestSizeAdvice(requestSizeBuilder);
- clientRequestSize = requestSizeBuilder.build();
+ RpcMetricsAdvice.applyDeprecatedClientRequestSizeAdvice(requestSizeBuilder);
+ oldClientRequestSize = requestSizeBuilder.build();
LongHistogramBuilder responseSizeBuilder =
meter
@@ -64,8 +86,8 @@ private RpcClientMetrics(Meter meter) {
.setUnit("By")
.setDescription("Measures the size of RPC response messages (uncompressed).")
.ofLongs();
- RpcMetricsAdvice.applyClientRequestSizeAdvice(responseSizeBuilder);
- clientResponseSize = responseSizeBuilder.build();
+ RpcMetricsAdvice.applyDeprecatedClientRequestSizeAdvice(responseSizeBuilder);
+ oldClientResponseSize = responseSizeBuilder.build();
}
/**
@@ -95,17 +117,37 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
return;
}
Attributes attributes = state.startAttributes().toBuilder().putAll(endAttributes).build();
- clientDurationHistogram.record(
- (endNanos - state.startTimeNanos()) / NANOS_PER_MS, attributes, context);
+ double durationNanos = (endNanos - state.startTimeNanos());
+
+ // Record to old histogram (milliseconds)
+ if (oldClientDurationHistogram != null) {
+ oldClientDurationHistogram.record(
+ durationNanos / NANOS_PER_MS,
+ SemconvStability.getOldRpcMetricAttributes(attributes),
+ context);
+ }
- Long rpcClientRequestBodySize = attributes.get(RpcSizeAttributesExtractor.RPC_REQUEST_SIZE);
- if (rpcClientRequestBodySize != null) {
- clientRequestSize.record(rpcClientRequestBodySize, attributes, context);
+ // Record to stable histogram (seconds)
+ if (stableClientDurationHistogram != null) {
+ stableClientDurationHistogram.record(durationNanos / NANOS_PER_S, attributes, context);
}
- Long rpcClientResponseBodySize = attributes.get(RpcSizeAttributesExtractor.RPC_RESPONSE_SIZE);
- if (rpcClientResponseBodySize != null) {
- clientResponseSize.record(rpcClientResponseBodySize, attributes, context);
+ if (SemconvStability.emitOldRpcSemconv()) {
+ Long rpcClientRequestBodySize = attributes.get(RpcSizeAttributesExtractor.RPC_REQUEST_SIZE);
+ if (rpcClientRequestBodySize != null) {
+ oldClientRequestSize.record(
+ rpcClientRequestBodySize,
+ SemconvStability.getOldRpcMetricAttributes(attributes),
+ context);
+ }
+
+ Long rpcClientResponseBodySize = attributes.get(RpcSizeAttributesExtractor.RPC_RESPONSE_SIZE);
+ if (rpcClientResponseBodySize != null) {
+ oldClientResponseSize.record(
+ rpcClientResponseBodySize,
+ SemconvStability.getOldRpcMetricAttributes(attributes),
+ context);
+ }
}
}
diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcCommonAttributesExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcCommonAttributesExtractor.java
index f731e703586c..d844d887e1a3 100644
--- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcCommonAttributesExtractor.java
+++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/rpc/RpcCommonAttributesExtractor.java
@@ -6,19 +6,27 @@
package io.opentelemetry.instrumentation.api.incubator.semconv.rpc;
import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet;
+import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
+import io.opentelemetry.instrumentation.api.internal.SemconvStability;
import javax.annotation.Nullable;
abstract class RpcCommonAttributesExtractor