diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java
index 11f2702c3c..81386dcdac 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/DefaultDriverOption.java
@@ -988,7 +988,48 @@ public enum DefaultDriverOption implements DriverOption {
*
Value type: {@link java.util.List List}<{@link String}>
*/
LOAD_BALANCING_DC_FAILOVER_PREFERRED_REMOTE_DCS(
- "advanced.load-balancing-policy.dc-failover.preferred-remote-dcs");
+ "advanced.load-balancing-policy.dc-failover.preferred-remote-dcs"),
+
+ /**
+ * The largest latency that we expect to record for requests.
+ *
+ *
Value-type: {@link java.time.Duration Duration}
+ */
+ METRICS_SESSION_SEND_LATENCY_HIGHEST("advanced.metrics.session.send-latency.highest-latency"),
+ /**
+ * The shortest latency that we expect to record for requests.
+ *
+ *
Value-type: {@link java.time.Duration Duration}
+ */
+ METRICS_SESSION_SEND_LATENCY_LOWEST("advanced.metrics.session.send-latency.lowest-latency"),
+ /**
+ * The number of significant decimal digits to which internal structures will maintain for
+ * requests.
+ *
+ *
Value-type: int
+ */
+ METRICS_SESSION_SEND_LATENCY_DIGITS("advanced.metrics.session.send-latency.significant-digits"),
+ /**
+ * The interval at which percentile data is refreshed for requests.
+ *
+ *
Value-type: {@link java.time.Duration Duration}
+ */
+ METRICS_SESSION_SEND_LATENCY_INTERVAL("advanced.metrics.session.send-latency.refresh-interval"),
+ /**
+ * Optional service-level objectives to meet, as a list of latencies to track.
+ *
+ *
Value-type: List of {@link java.time.Duration Duration}
+ */
+ METRICS_SESSION_SEND_LATENCY_SLO("advanced.metrics.session.send-latency.slo"),
+ /**
+ * Optional list of percentiles to publish for send-latency metric. Produces an additional time
+ * series for each requested percentile. This percentile is computed locally, and so can't be
+ * aggregated with percentiles computed across other dimensions (e.g. in a different instance).
+ *
+ *
Value type: {@link java.util.List List}<{@link Double}>
+ */
+ METRICS_SESSION_SEND_LATENCY_PUBLISH_PERCENTILES(
+ "advanced.metrics.session.send-latency.publish-percentiles");
private final String path;
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java
index 98faf3e590..3baa537cf0 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/OptionsMap.java
@@ -312,6 +312,10 @@ protected static void fillWithDriverDefaults(OptionsMap map) {
map.put(TypedDriverOption.METRICS_SESSION_CQL_REQUESTS_LOWEST, Duration.ofMillis(1));
map.put(TypedDriverOption.METRICS_SESSION_CQL_REQUESTS_DIGITS, 3);
map.put(TypedDriverOption.METRICS_SESSION_CQL_REQUESTS_INTERVAL, Duration.ofMinutes(5));
+ map.put(TypedDriverOption.METRICS_SESSION_SEND_LATENCY_HIGHEST, Duration.ofSeconds(3));
+ map.put(TypedDriverOption.METRICS_SESSION_SEND_LATENCY_LOWEST, Duration.ofMillis(1));
+ map.put(TypedDriverOption.METRICS_SESSION_SEND_LATENCY_DIGITS, 3);
+ map.put(TypedDriverOption.METRICS_SESSION_SEND_LATENCY_INTERVAL, Duration.ofMinutes(5));
map.put(TypedDriverOption.METRICS_SESSION_THROTTLING_HIGHEST, Duration.ofSeconds(3));
map.put(TypedDriverOption.METRICS_SESSION_THROTTLING_LOWEST, Duration.ofMillis(1));
map.put(TypedDriverOption.METRICS_SESSION_THROTTLING_DIGITS, 3);
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java
index ca60b67f0b..0e0a1c265e 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/config/TypedDriverOption.java
@@ -902,6 +902,37 @@ public String toString() {
DefaultDriverOption.LOAD_BALANCING_DC_FAILOVER_PREFERRED_REMOTE_DCS,
GenericType.listOf(String.class));
+ /** The largest latency that we expect to record for requests. */
+ public static final TypedDriverOption METRICS_SESSION_SEND_LATENCY_HIGHEST =
+ new TypedDriverOption<>(
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_HIGHEST, GenericType.DURATION);
+ /** The shortest latency that we expect to record for requests. */
+ public static final TypedDriverOption METRICS_SESSION_SEND_LATENCY_LOWEST =
+ new TypedDriverOption<>(
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_LOWEST, GenericType.DURATION);
+ /** Optional service-level objectives to meet, as a list of latencies to track. */
+ public static final TypedDriverOption> METRICS_SESSION_SEND_LATENCY_SLO =
+ new TypedDriverOption<>(
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_SLO,
+ GenericType.listOf(GenericType.DURATION));
+ /** Optional pre-defined percentile of send-latency to publish, as a list of percentiles . */
+ public static final TypedDriverOption>
+ METRICS_SESSION_SEND_LATENCY_PUBLISH_PERCENTILES =
+ new TypedDriverOption<>(
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_PUBLISH_PERCENTILES,
+ GenericType.listOf(GenericType.DOUBLE));
+ /**
+ * The number of significant decimal digits to which internal structures will maintain for
+ * requests.
+ */
+ public static final TypedDriverOption METRICS_SESSION_SEND_LATENCY_DIGITS =
+ new TypedDriverOption<>(
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_DIGITS, GenericType.INTEGER);
+ /** The interval at which percentile data is refreshed for requests. */
+ public static final TypedDriverOption METRICS_SESSION_SEND_LATENCY_INTERVAL =
+ new TypedDriverOption<>(
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_INTERVAL, GenericType.DURATION);
+
private static Iterable> introspectBuiltInValues() {
try {
ImmutableList.Builder> result = ImmutableList.builder();
diff --git a/core/src/main/java/com/datastax/oss/driver/api/core/metrics/DefaultSessionMetric.java b/core/src/main/java/com/datastax/oss/driver/api/core/metrics/DefaultSessionMetric.java
index 63027a23fe..8739b2edc5 100644
--- a/core/src/main/java/com/datastax/oss/driver/api/core/metrics/DefaultSessionMetric.java
+++ b/core/src/main/java/com/datastax/oss/driver/api/core/metrics/DefaultSessionMetric.java
@@ -32,6 +32,7 @@ public enum DefaultSessionMetric implements SessionMetric {
THROTTLING_QUEUE_SIZE("throttling.queue-size"),
THROTTLING_ERRORS("throttling.errors"),
CQL_PREPARED_CACHE_SIZE("cql-prepared-cache-size"),
+ SEND_LATENCY("send-latency"),
;
private static final Map BY_PATH = sortByPath();
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/InFlightHandler.java b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/InFlightHandler.java
index 9060f80b7c..ec06e88648 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/InFlightHandler.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/InFlightHandler.java
@@ -150,6 +150,7 @@ private void write(ChannelHandlerContext ctx, RequestMessage message, ChannelPro
message.request);
inFlight.put(streamId, message.responseCallback);
+ message.responseCallback.onRequestSent(frame);
ChannelFuture writeFuture = ctx.write(frame, promise);
writeFuture.addListener(
future -> {
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ResponseCallback.java b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ResponseCallback.java
index 5a0e9e5eb8..f2b00770f9 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ResponseCallback.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/channel/ResponseCallback.java
@@ -48,6 +48,18 @@ public interface ResponseCallback {
*/
void onFailure(Throwable error);
+ /**
+ * Reports the request frame to be sent on the current connection.
+ *
+ * This is called every time just before the request is written to a connection (and therefore
+ * might multiple times in case of retries).
+ *
+ *
The default implementation does nothing.
+ */
+ default void onRequestSent(Frame frame) {
+ // nothing to do
+ }
+
/**
* Reports the stream id used for the request on the current connection.
*
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/cql/CqlRequestHandler.java b/core/src/main/java/com/datastax/oss/driver/internal/core/cql/CqlRequestHandler.java
index a1c6b0e546..bb413d4ad0 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/cql/CqlRequestHandler.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/cql/CqlRequestHandler.java
@@ -459,6 +459,7 @@ private class NodeResponseCallback
implements ResponseCallback, GenericFutureListener> {
private final long nodeStartTimeNanos = System.nanoTime();
+ private long sendStartTimeNanos = NANOTIME_NOT_MEASURED_YET;
private final Statement> statement;
private final Node node;
private final Queue queryPlan;
@@ -491,7 +492,15 @@ private NodeResponseCallback(
this.logPrefix = logPrefix + "|" + execution;
}
- // this gets invoked once the write completes.
+ @Override
+ public void onRequestSent(Frame frame) {
+ if (sessionMetricUpdater.isEnabled(
+ DefaultSessionMetric.SEND_LATENCY, executionProfile.getName())) {
+ sendStartTimeNanos = System.nanoTime();
+ }
+ }
+
+ // this gets invoked once the write request completes.
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
@@ -521,6 +530,14 @@ public void operationComplete(Future future) throws Exception {
}
} else {
LOG.trace("[{}] Request sent on {}", logPrefix, channel);
+ if (sendStartTimeNanos != NANOTIME_NOT_MEASURED_YET) {
+ // only if send latency metric is enabled
+ sessionMetricUpdater.updateTimer(
+ DefaultSessionMetric.SEND_LATENCY,
+ executionProfile.getName(),
+ System.nanoTime() - sendStartTimeNanos,
+ TimeUnit.NANOSECONDS);
+ }
if (result.isDone()) {
// If the handler completed since the last time we checked, cancel directly because we
// don't know if cancelScheduledTasks() has run yet
@@ -729,7 +746,7 @@ private void processErrorResponse(Error errorMessage) {
trackNodeError(node, illegalStateException, NANOTIME_NOT_MEASURED_YET);
setFinalError(statement, illegalStateException, node, execution);
}
- LOG.trace("[{}] Reprepare sucessful, retrying", logPrefix);
+ LOG.trace("[{}] Reprepare successful, retrying", logPrefix);
sendRequest(statement, node, queryPlan, execution, retryCount, false);
}
return null;
diff --git a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java
index 94e10ad693..1092846205 100644
--- a/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java
+++ b/core/src/main/java/com/datastax/oss/driver/internal/core/metrics/DropwizardSessionMetricUpdater.java
@@ -53,6 +53,12 @@ public DropwizardSessionMetricUpdater(
DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_HIGHEST,
DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_DIGITS,
DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_INTERVAL);
+ initializeHdrTimer(
+ DefaultSessionMetric.SEND_LATENCY,
+ profile,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_HIGHEST,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_DIGITS,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_INTERVAL);
initializeHdrTimer(
DefaultSessionMetric.THROTTLING_DELAY,
profile,
diff --git a/core/src/main/resources/reference.conf b/core/src/main/resources/reference.conf
index 7b1c43f8be..ff15506f02 100644
--- a/core/src/main/resources/reference.conf
+++ b/core/src/main/resources/reference.conf
@@ -1500,6 +1500,9 @@ datastax-java-driver {
# retry.
// cql-requests,
+ # The throughput and latency percentiles of requests sent over the network (exposed as a Timer).
+ // send-latency,
+
# The number of CQL requests that timed out -- that is, the session.execute() call failed
# with a DriverTimeoutException (exposed as a Counter).
// cql-client-timeouts,
@@ -1625,6 +1628,18 @@ datastax-java-driver {
// publish-percentiles = [ 0.75, 0.95, 0.99 ]
}
+ # Required: if the 'send-latency' metric is enabled, and Dropwizard or Micrometer is used.
+ # Modifiable at runtime: no
+ # Overridable in a profile: no
+ send-latency {
+ highest-latency = 3 seconds
+ lowest-latency = 1 millisecond
+ significant-digits = 3
+ refresh-interval = 5 minutes
+ // slo = [ 100 milliseconds, 500 milliseconds, 1 second ]
+ // publish-percentiles = [ 0.75, 0.95, 0.99 ]
+ }
+
# Required: if the 'throttling.delay' metric is enabled, and Dropwizard or Micrometer is used.
# Modifiable at runtime: no
# Overridable in a profile: no
diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/core/metrics/DropwizardMetricsIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/core/metrics/DropwizardMetricsIT.java
index e0184516e2..5e29615f56 100644
--- a/integration-tests/src/test/java/com/datastax/oss/driver/core/metrics/DropwizardMetricsIT.java
+++ b/integration-tests/src/test/java/com/datastax/oss/driver/core/metrics/DropwizardMetricsIT.java
@@ -97,6 +97,7 @@ protected void assertMetricsPresent(CqlSession session) {
assertThat((Integer) ((Gauge>) m).getValue()).isEqualTo(3);
break;
case CQL_REQUESTS:
+ case SEND_LATENCY:
assertThat(m).isInstanceOf(Timer.class);
await().untilAsserted(() -> assertThat(((Timer) m).getCount()).isEqualTo(30));
break;
diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/metrics/micrometer/MicrometerMetricsIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/metrics/micrometer/MicrometerMetricsIT.java
index c38df1e202..86f3c5e6f2 100644
--- a/integration-tests/src/test/java/com/datastax/oss/driver/metrics/micrometer/MicrometerMetricsIT.java
+++ b/integration-tests/src/test/java/com/datastax/oss/driver/metrics/micrometer/MicrometerMetricsIT.java
@@ -39,6 +39,7 @@
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
+import java.util.concurrent.TimeUnit;
import org.junit.ClassRule;
import org.junit.experimental.categories.Category;
@@ -77,6 +78,9 @@ protected void assertMetricsPresent(CqlSession session) {
MetricIdGenerator metricIdGenerator =
((InternalDriverContext) session.getContext()).getMetricIdGenerator();
+ double cqlRequestsTotal = 0;
+ double sendLatencyTotal = 0;
+
for (DefaultSessionMetric metric : ENABLED_SESSION_METRICS) {
MetricId id = metricIdGenerator.sessionMetricId(metric);
Iterable tags = MicrometerTags.toMicrometerTags(id.getTags());
@@ -89,7 +93,15 @@ protected void assertMetricsPresent(CqlSession session) {
break;
case CQL_REQUESTS:
assertThat(m).isInstanceOf(Timer.class);
- await().untilAsserted(() -> assertThat(((Timer) m).count()).isEqualTo(30));
+ Timer tr = (Timer) m;
+ await().untilAsserted(() -> assertThat(tr.count()).isEqualTo(30));
+ cqlRequestsTotal = tr.totalTime(TimeUnit.NANOSECONDS);
+ break;
+ case SEND_LATENCY:
+ assertThat(m).isInstanceOf(Timer.class);
+ Timer tl = (Timer) m;
+ await().untilAsserted(() -> assertThat(tl.count()).isEqualTo(30));
+ sendLatencyTotal = tl.totalTime(TimeUnit.NANOSECONDS);
break;
case CQL_PREPARED_CACHE_SIZE:
assertThat(m).isInstanceOf(Gauge.class);
@@ -116,6 +128,8 @@ protected void assertMetricsPresent(CqlSession session) {
}
}
+ assertThat(sendLatencyTotal).isLessThanOrEqualTo(cqlRequestsTotal);
+
for (Node node : session.getMetadata().getNodes().values()) {
for (DefaultNodeMetric metric : ENABLED_NODE_METRICS) {
diff --git a/integration-tests/src/test/java/com/datastax/oss/driver/metrics/microprofile/MicroProfileMetricsIT.java b/integration-tests/src/test/java/com/datastax/oss/driver/metrics/microprofile/MicroProfileMetricsIT.java
index aa04c058a4..039d0eec7a 100644
--- a/integration-tests/src/test/java/com/datastax/oss/driver/metrics/microprofile/MicroProfileMetricsIT.java
+++ b/integration-tests/src/test/java/com/datastax/oss/driver/metrics/microprofile/MicroProfileMetricsIT.java
@@ -33,6 +33,7 @@
import com.datastax.oss.driver.internal.metrics.microprofile.MicroProfileTags;
import com.datastax.oss.simulacron.common.cluster.ClusterSpec;
import io.smallrye.metrics.MetricsRegistryImpl;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.microprofile.metrics.Counter;
@@ -81,6 +82,9 @@ protected void assertMetricsPresent(CqlSession session) {
MetricIdGenerator metricIdGenerator =
((InternalDriverContext) session.getContext()).getMetricIdGenerator();
+ Duration cqlRequestsDuration = null;
+ Duration sendLatencyDuration = null;
+
for (DefaultSessionMetric metric : ENABLED_SESSION_METRICS) {
MetricId metricId = metricIdGenerator.sessionMetricId(metric);
Tag[] tags = MicroProfileTags.toMicroProfileTags(metricId.getTags());
@@ -94,7 +98,15 @@ protected void assertMetricsPresent(CqlSession session) {
break;
case CQL_REQUESTS:
assertThat(m).isInstanceOf(Timer.class);
- await().untilAsserted(() -> assertThat(((Timer) m).getCount()).isEqualTo(30));
+ Timer tr = (Timer) m;
+ await().untilAsserted(() -> assertThat(tr.getCount()).isEqualTo(30));
+ cqlRequestsDuration = tr.getElapsedTime();
+ break;
+ case SEND_LATENCY:
+ assertThat(m).isInstanceOf(Timer.class);
+ Timer tl = (Timer) m;
+ await().untilAsserted(() -> assertThat(tl.getCount()).isEqualTo(30));
+ sendLatencyDuration = tl.getElapsedTime();
break;
case CQL_PREPARED_CACHE_SIZE:
assertThat(m).isInstanceOf(Gauge.class);
@@ -121,6 +133,10 @@ protected void assertMetricsPresent(CqlSession session) {
}
}
+ assertThat(sendLatencyDuration).isNotNull();
+ assertThat(cqlRequestsDuration).isNotNull();
+ assertThat(sendLatencyDuration.toNanos()).isLessThanOrEqualTo(cqlRequestsDuration.toNanos());
+
for (Node node : session.getMetadata().getNodes().values()) {
for (DefaultNodeMetric metric : ENABLED_NODE_METRICS) {
diff --git a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java
index 559054ab51..06d9025a51 100644
--- a/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java
+++ b/metrics/micrometer/src/main/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdater.java
@@ -53,6 +53,7 @@ public MicrometerSessionMetricUpdater(
initializeTimer(DefaultSessionMetric.CQL_REQUESTS, profile);
initializeTimer(DefaultSessionMetric.THROTTLING_DELAY, profile);
+ initializeTimer(DefaultSessionMetric.SEND_LATENCY, profile);
initializeTimer(DseSessionMetric.CONTINUOUS_CQL_REQUESTS, profile);
initializeTimer(DseSessionMetric.GRAPH_REQUESTS, profile);
}
@@ -149,6 +150,25 @@ protected Timer.Builder configureTimer(Timer.Builder builder, SessionMetric metr
configurePercentilesPublishIfDefined(
builder, profile, DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_PUBLISH_PERCENTILES);
+ } else if (metric == DefaultSessionMetric.SEND_LATENCY) {
+ builder
+ .minimumExpectedValue(
+ profile.getDuration(DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_LOWEST))
+ .maximumExpectedValue(
+ profile.getDuration(DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_HIGHEST))
+ .serviceLevelObjectives(
+ profile.isDefined(DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_SLO)
+ ? profile
+ .getDurationList(DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_SLO)
+ .toArray(new Duration[0])
+ : null)
+ .percentilePrecision(
+ profile.isDefined(DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_DIGITS)
+ ? profile.getInt(DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_DIGITS)
+ : null);
+
+ configurePercentilesPublishIfDefined(
+ builder, profile, DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_PUBLISH_PERCENTILES);
}
return builder;
}
diff --git a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java
index 0deb377457..2eca55af48 100644
--- a/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java
+++ b/metrics/micrometer/src/test/java/com/datastax/oss/driver/internal/metrics/micrometer/MicrometerSessionMetricUpdaterTest.java
@@ -169,6 +169,14 @@ public static Object[][] timerMetrics() {
DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_SLO,
DefaultDriverOption.METRICS_SESSION_CQL_REQUESTS_PUBLISH_PERCENTILES,
},
+ {
+ DefaultSessionMetric.SEND_LATENCY,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_LOWEST,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_HIGHEST,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_DIGITS,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_SLO,
+ DefaultDriverOption.METRICS_SESSION_SEND_LATENCY_PUBLISH_PERCENTILES,
+ },
{
DseSessionMetric.GRAPH_REQUESTS,
DseDriverOption.METRICS_SESSION_GRAPH_REQUESTS_LOWEST,
diff --git a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java
index f3c906e442..6c0899f34e 100644
--- a/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java
+++ b/metrics/microprofile/src/main/java/com/datastax/oss/driver/internal/metrics/microprofile/MicroProfileSessionMetricUpdater.java
@@ -49,6 +49,7 @@ public MicroProfileSessionMetricUpdater(
initializeTimer(DefaultSessionMetric.CQL_REQUESTS, profile);
initializeTimer(DefaultSessionMetric.THROTTLING_DELAY, profile);
+ initializeTimer(DefaultSessionMetric.SEND_LATENCY, profile);
initializeTimer(DseSessionMetric.CONTINUOUS_CQL_REQUESTS, profile);
initializeTimer(DseSessionMetric.GRAPH_REQUESTS, profile);
}