This is an automated email from the ASF dual-hosted git repository.
ritesh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new daeb18bf53 HDDS-9717. Add P99 quantiles and Min/Max Metrics for S3G
Performance Metrics (#5627)
daeb18bf53 is described below
commit daeb18bf53c445e79853d7c017c22bc3949a29c9
Author: XiChen <[email protected]>
AuthorDate: Fri Jan 12 05:23:00 2024 +0800
HDDS-9717. Add P99 quantiles and Min/Max Metrics for S3G Performance
Metrics (#5627)
---
.../java/org/apache/hadoop/util/MetricUtil.java | 36 ++++++++
.../java/org/apache/hadoop/util/MutableMinMax.java | 93 +++++++++++++++++++++
.../org/apache/hadoop/util/PerformanceMetrics.java | 97 ++++++++++++++++++++++
.../hadoop/util/PerformanceMetricsInitializer.java | 83 ++++++++++++++++++
.../common/src/main/resources/ozone-default.xml | 8 ++
.../hadoop/ozone/TestMultipartObjectGet.java | 2 +
.../java/org/apache/hadoop/ozone/s3/Gateway.java | 2 +-
.../hadoop/ozone/s3/S3GatewayConfigKeys.java | 3 +
.../hadoop/ozone/s3/endpoint/EndpointBase.java | 2 +-
.../ozone/s3/endpoint/ObjectEndpointStreaming.java | 12 ++-
.../hadoop/ozone/s3/metrics/S3GatewayMetrics.java | 96 +++++++++++----------
.../hadoop/ozone/client/OzoneClientStub.java | 4 +
.../ozone/s3/endpoint/TestPermissionCheck.java | 2 +
13 files changed, 388 insertions(+), 52 deletions(-)
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MetricUtil.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MetricUtil.java
index 879f8ed0cc..381314e69c 100644
--- a/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MetricUtil.java
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MetricUtil.java
@@ -17,12 +17,18 @@
*/
package org.apache.hadoop.util;
+import org.apache.hadoop.metrics2.lib.MetricsRegistry;
+import org.apache.hadoop.metrics2.lib.MutableQuantiles;
import org.apache.hadoop.metrics2.lib.MutableRate;
import org.apache.ratis.util.function.CheckedRunnable;
import org.apache.ratis.util.function.CheckedSupplier;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Encloses helpers to deal with metrics.
@@ -63,4 +69,34 @@ public final class MetricUtil {
latencySetter.accept(Time.monotonicNowNanos() - start);
}
}
+
+ /**
+ * Creates MutableQuantiles metrics with one or multiple intervals.
+ *
+ * @param registry The MetricsRegistry to register the new
MutableQuantiles
+ * instances.
+ * @param name The base name of the metric.
+ * @param description The description of the metric.
+ * @param sampleName of the metric (e.g., "Ops")
+ * @param valueName of the metric (e.g., "Time" or "Latency")
+ * @param intervals An array of intervals for the quantiles.
+ * @return A list of created MutableQuantiles instances.
+ */
+ public static List<MutableQuantiles> createQuantiles(MetricsRegistry
registry,
+ String name, String description, String sampleName, String valueName,
+ int... intervals) {
+ if (intervals == null) {
+ throw new IllegalArgumentException(
+ "At least one interval should be provided.");
+ }
+ if (intervals.length == 0) {
+ return new ArrayList<>();
+ }
+
+ return Arrays.stream(intervals).mapToObj(interval -> {
+ String quantileName = name + interval + "s";
+ return registry.newQuantiles(quantileName, description,
+ sampleName, valueName, interval);
+ }).collect(Collectors.toList());
+ }
}
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MutableMinMax.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MutableMinMax.java
new file mode 100644
index 0000000000..1f056ed742
--- /dev/null
+++ b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/MutableMinMax.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.util;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.metrics2.MetricsInfo;
+import org.apache.hadoop.metrics2.MetricsRecordBuilder;
+import org.apache.hadoop.metrics2.lib.MetricsRegistry;
+import org.apache.hadoop.metrics2.lib.MutableMetric;
+import org.apache.hadoop.metrics2.util.SampleStat.MinMax;
+import org.apache.commons.lang3.StringUtils;
+
+import static org.apache.hadoop.metrics2.lib.Interns.info;
+
+/**
+ * A mutable metric that tracks the minimum and maximum
+ * values of a dataset over time.
+ */
[email protected]
[email protected]
+public class MutableMinMax extends MutableMetric {
+ private final MinMax intervalMinMax = new MinMax();
+ private final MinMax prevMinMax = new MinMax();
+ private final MetricsInfo iMinInfo;
+ private final MetricsInfo iMaxInfo;
+
+ /**
+ * Construct a minMax metric.
+ * @param registry MetricsRegistry of the metric
+ * @param name of the metric
+ * @param description of the metric
+ * @param valueName of the metric (e.g. "Time", "Latency")
+ */
+ public MutableMinMax(MetricsRegistry registry,
+ String name, String description, String valueName) {
+ String ucName = StringUtils.capitalize(name);
+ String desc = StringUtils.uncapitalize(description);
+ String uvName = StringUtils.capitalize(valueName);
+ String lvName = StringUtils.uncapitalize(valueName);
+ iMinInfo = info(ucName + "IMin" + uvName,
+ "Min " + lvName + " for " + desc + "in the last reporting interval");
+ iMaxInfo = info(ucName + "IMax" + uvName,
+ "Max " + lvName + " for " + desc + "in the last reporting interval");
+ // hadoop.metrics2 only supports standard types of Metrics registered
+ // with annotations, but not custom types of metrics.
+ // Registering here is for compatibility with metric classes
+ // that are only registered with annotations and do not override
getMetrics.
+ registry.newGauge(iMinInfo, 0);
+ registry.newGauge(iMaxInfo, 0);
+ }
+
+ /**
+ * Add a snapshot to the metric.
+ * @param value of the metric
+ */
+ public synchronized void add(long value) {
+ intervalMinMax.add(value);
+ setChanged();
+ }
+
+ private MinMax lastMinMax() {
+ return changed() ? intervalMinMax : prevMinMax;
+ }
+
+ @Override
+ public synchronized void snapshot(MetricsRecordBuilder builder, boolean all)
{
+ if (all || this.changed()) {
+ builder.addGauge(iMinInfo, lastMinMax().min());
+ builder.addGauge(iMaxInfo, lastMinMax().max());
+ if (changed()) {
+ prevMinMax.reset(intervalMinMax);
+ intervalMinMax.reset();
+ clearChanged();
+ }
+ }
+ }
+}
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/PerformanceMetrics.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/PerformanceMetrics.java
new file mode 100644
index 0000000000..a470ff9657
--- /dev/null
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/PerformanceMetrics.java
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.util;
+
+import org.apache.hadoop.metrics2.MetricsRecordBuilder;
+import org.apache.hadoop.metrics2.lib.MetricsRegistry;
+import org.apache.hadoop.metrics2.lib.MutableQuantiles;
+import org.apache.hadoop.metrics2.lib.MutableStat;
+
+import java.util.List;
+
+/**
+ * The {@code PerformanceMetrics} class encapsulates a collection of related
+ * metrics including a MutableStat, MutableQuantiles, and a MutableMinMax.
+ * This class provides methods to update these metrics and to
+ * snapshot their values for reporting.
+ */
+public class PerformanceMetrics {
+ private final MutableStat stat;
+ private final List<MutableQuantiles> quantiles;
+ private final MutableMinMax minMax;
+
+ /**
+ * Initializes aggregated metrics for the specified metrics source.
+ *
+ * @param source the metrics source
+ * @param registry the metrics registry
+ * @param intervals the intervals for quantiles computation. Note, each
+ * interval in 'intervals' increases memory usage, as it corresponds
+ * to a separate quantile calculator.
+ */
+ public static synchronized <T> void initializeMetrics(T source,
+ MetricsRegistry registry, String sampleName, String valueName,
+ int[] intervals) {
+ try {
+ PerformanceMetricsInitializer.initialize(
+ source, registry, sampleName, valueName, intervals);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Failed to initialize PerformanceMetrics", e);
+ }
+ }
+
+ /**
+ * Construct an instance of PerformanceMetrics with the specified
MutableStat,
+ * MutableQuantiles, and MutableMinMax.
+ *
+ * @param stat the stat metric
+ * @param quantiles the quantiles metrics
+ * @param minMax the min/max tracker
+ */
+ public PerformanceMetrics(MutableStat stat,
+ List<MutableQuantiles> quantiles, MutableMinMax minMax) {
+ this.stat = stat;
+ this.quantiles = quantiles;
+ this.minMax = minMax;
+ }
+
+ /**
+ * Adds a value to all the aggregated metrics.
+ *
+ * @param value the value to add
+ */
+ public void add(long value) {
+ this.stat.add(value);
+ this.quantiles.forEach(quantile -> quantile.add(value));
+ this.minMax.add(value);
+ }
+
+ /**
+ * Snapshots the values of all the aggregated metrics for reporting.
+ *
+ * @param recordBuilder the metrics record builder
+ * @param all flag to indicate whether to snapshot all metrics or only
changed
+ */
+ public void snapshot(MetricsRecordBuilder recordBuilder, boolean all) {
+ this.stat.snapshot(recordBuilder, all);
+ this.quantiles.forEach(quantile -> quantile.snapshot(recordBuilder, all));
+ this.minMax.snapshot(recordBuilder, all);
+ }
+
+}
+
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/PerformanceMetricsInitializer.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/PerformanceMetricsInitializer.java
new file mode 100644
index 0000000000..83d61cab68
--- /dev/null
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/util/PerformanceMetricsInitializer.java
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.util;
+
+import org.apache.hadoop.metrics2.annotation.Metric;
+import org.apache.hadoop.metrics2.lib.MetricsRegistry;
+
+import java.lang.reflect.Field;
+
+/**
+ * Utility class for initializing PerformanceMetrics in a MetricsSource.
+ */
+public final class PerformanceMetricsInitializer {
+ private PerformanceMetricsInitializer() { }
+
+ /**
+ * Initializes aggregated metrics in the given metrics source.
+ *
+ * @param source the metrics source
+ * @param registry the metrics registry
+ * @param sampleName sample name
+ * @param valueName value name
+ * @param intervals intervals for quantiles
+ * @throws IllegalAccessException if unable to access the field
+ */
+ public static <T> void initialize(T source, MetricsRegistry registry,
+ String sampleName, String valueName, int[] intervals)
+ throws IllegalAccessException {
+ Field[] fields = source.getClass().getDeclaredFields();
+
+ for (Field field : fields) {
+ if (field.getType() == PerformanceMetrics.class) {
+ Metric annotation = field.getAnnotation(Metric.class);
+ if (annotation != null) {
+ String description = annotation.about();
+ String name = field.getName();
+ PerformanceMetrics performanceMetrics =
+ getMetrics(registry, name, description,
+ sampleName, valueName, intervals);
+ field.setAccessible(true);
+ field.set(source, performanceMetrics);
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper method to create PerformanceMetrics.
+ *
+ * @param registry the metrics registry
+ * @param name metric name
+ * @param description metric description
+ * @param sampleName sample name
+ * @param valueName value name
+ * @param intervals intervals for quantiles
+ * @return an instance of PerformanceMetrics
+ */
+ private static PerformanceMetrics getMetrics(
+ MetricsRegistry registry, String name, String description,
+ String sampleName, String valueName, int[] intervals) {
+ return new PerformanceMetrics(
+ registry.newStat(
+ name, description, sampleName, valueName, false),
+ MetricUtil.createQuantiles(
+ registry, name, description, sampleName, valueName, intervals),
+ new MutableMinMax(registry, name, description, valueName));
+ }
+}
diff --git a/hadoop-hdds/common/src/main/resources/ozone-default.xml
b/hadoop-hdds/common/src/main/resources/ozone-default.xml
index 079362f916..f7a1e7ef66 100644
--- a/hadoop-hdds/common/src/main/resources/ozone-default.xml
+++ b/hadoop-hdds/common/src/main/resources/ozone-default.xml
@@ -1876,6 +1876,14 @@
will be used for http authentication.
</description>
</property>
+ <property>
+ <name>ozone.s3g.metrics.percentiles.intervals.seconds</name>
+ <value>60</value>
+ <tag>S3GATEWAY, PERFORMANCE</tag>
+ <description>Specifies the interval in seconds for the rollover of
MutableQuantiles metrics.
+ Setting this interval equal to the metrics sampling time ensures more
detailed metrics.
+ </description>
+ </property>
<property>
<name>ozone.om.save.metrics.interval</name>
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestMultipartObjectGet.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestMultipartObjectGet.java
index c3e6c288d7..cec90067da 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestMultipartObjectGet.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestMultipartObjectGet.java
@@ -27,6 +27,7 @@ import
org.apache.hadoop.ozone.s3.endpoint.CompleteMultipartUploadResponse;
import org.apache.hadoop.ozone.s3.endpoint.MultipartUploadInitiateResponse;
import org.apache.hadoop.ozone.s3.endpoint.ObjectEndpoint;
import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.apache.hadoop.ozone.s3.metrics.S3GatewayMetrics;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -101,6 +102,7 @@ public class TestMultipartObjectGet {
REST.setClient(client);
REST.setOzoneConfiguration(conf);
REST.setContext(context);
+ S3GatewayMetrics.create(conf);
}
private static void startCluster()
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/Gateway.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/Gateway.java
index 6fc55ac012..cfbcb51d26 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/Gateway.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/Gateway.java
@@ -79,7 +79,7 @@ public class Gateway extends GenericCli {
loginS3GUser(ozoneConfiguration);
setHttpBaseDir(ozoneConfiguration);
httpServer = new S3GatewayHttpServer(ozoneConfiguration, "s3gateway");
- metrics = S3GatewayMetrics.create();
+ metrics = S3GatewayMetrics.create(ozoneConfiguration);
start();
ShutdownHookManager.get().addShutdownHook(() -> {
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/S3GatewayConfigKeys.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/S3GatewayConfigKeys.java
index 179c5eeee7..a058e413b9 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/S3GatewayConfigKeys.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/S3GatewayConfigKeys.java
@@ -81,6 +81,9 @@ public final class S3GatewayConfigKeys {
public static final boolean OZONE_S3G_LIST_KEYS_SHALLOW_ENABLED_DEFAULT =
true;
+ public static final String
OZONE_S3G_METRICS_PERCENTILES_INTERVALS_SECONDS_KEY
+ = "ozone.s3g.metrics.percentiles.intervals.seconds";
+
/**
* Never constructed.
*/
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
index 6f0f3c4847..5694d6f9f4 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/EndpointBase.java
@@ -387,7 +387,7 @@ public abstract class EndpointBase implements Auditor {
@VisibleForTesting
public S3GatewayMetrics getMetrics() {
- return S3GatewayMetrics.create();
+ return S3GatewayMetrics.getMetrics();
}
protected Map<String, String> getAuditParameters() {
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpointStreaming.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpointStreaming.java
index dbc7f374a9..e509acb05b 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpointStreaming.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpointStreaming.java
@@ -52,6 +52,7 @@ final class ObjectEndpointStreaming {
private static final Logger LOG =
LoggerFactory.getLogger(ObjectEndpointStreaming.class);
+ private static final S3GatewayMetrics METRICS =
S3GatewayMetrics.getMetrics();
private ObjectEndpointStreaming() {
}
@@ -99,13 +100,12 @@ final class ObjectEndpointStreaming {
Map<String, String> keyMetadata,
DigestInputStream body, PerformanceStringBuilder perf)
throws IOException {
- S3GatewayMetrics metrics = S3GatewayMetrics.create();
long startNanos = Time.monotonicNowNanos();
long writeLen;
String eTag;
try (OzoneDataStreamOutput streamOutput = bucket.createStreamKey(keyPath,
length, replicationConfig, keyMetadata)) {
- long metadataLatencyNs = metrics.updatePutKeyMetadataStats(startNanos);
+ long metadataLatencyNs = METRICS.updatePutKeyMetadataStats(startNanos);
writeLen = writeToStreamOutput(streamOutput, body, bufferSize, length);
eTag = DatatypeConverter.printHexBinary(body.getMessageDigest().digest())
.toLowerCase();
@@ -126,11 +126,10 @@ final class ObjectEndpointStreaming {
InputStream body, PerformanceStringBuilder perf, long startNanos)
throws IOException {
long writeLen = 0;
- S3GatewayMetrics metrics = S3GatewayMetrics.create();
try (OzoneDataStreamOutput streamOutput = bucket.createStreamKey(keyPath,
length, replicationConfig, keyMetadata)) {
long metadataLatencyNs =
- metrics.updateCopyKeyMetadataStats(startNanos);
+ METRICS.updateCopyKeyMetadataStats(startNanos);
perf.appendMetaLatencyNanos(metadataLatencyNs);
writeLen = writeToStreamOutput(streamOutput, body, bufferSize, length);
}
@@ -162,7 +161,6 @@ final class ObjectEndpointStreaming {
throws IOException, OS3Exception {
long startNanos = Time.monotonicNowNanos();
String eTag;
- S3GatewayMetrics metrics = S3GatewayMetrics.create();
// OmMultipartCommitUploadPartInfo can only be gotten after the
// OzoneDataStreamOutput is closed, so we need to save the
// KeyDataStreamOutput in the OzoneDataStreamOutput and use it to get the
@@ -171,13 +169,13 @@ final class ObjectEndpointStreaming {
try {
try (OzoneDataStreamOutput streamOutput = ozoneBucket
.createMultipartStreamKey(key, length, partNumber, uploadID)) {
- long metadataLatencyNs = metrics.updatePutKeyMetadataStats(startNanos);
+ long metadataLatencyNs = METRICS.updatePutKeyMetadataStats(startNanos);
long putLength =
writeToStreamOutput(streamOutput, body, chunkSize, length);
eTag = DatatypeConverter.printHexBinary(
body.getMessageDigest().digest()).toLowerCase();
((KeyMetadataAware)streamOutput).getMetadata().put("ETag", eTag);
- metrics.incPutKeySuccessLength(putLength);
+ METRICS.incPutKeySuccessLength(putLength);
perf.appendMetaLatencyNanos(metadataLatencyNs);
perf.appendSizeBytes(putLength);
keyDataStreamOutput = streamOutput.getKeyDataStreamOutput();
diff --git
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/metrics/S3GatewayMetrics.java
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/metrics/S3GatewayMetrics.java
index 10b7b167b9..ef7df24fec 100644
---
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/metrics/S3GatewayMetrics.java
+++
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/metrics/S3GatewayMetrics.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.ozone.s3.metrics;
import org.apache.hadoop.hdds.annotation.InterfaceAudience;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import org.apache.hadoop.metrics2.MetricsCollector;
import org.apache.hadoop.metrics2.MetricsRecordBuilder;
import org.apache.hadoop.metrics2.MetricsSource;
@@ -27,8 +28,9 @@ import org.apache.hadoop.metrics2.annotation.Metrics;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.lib.MetricsRegistry;
import org.apache.hadoop.metrics2.lib.MutableCounterLong;
-import org.apache.hadoop.metrics2.lib.MutableRate;
import org.apache.hadoop.ozone.OzoneConsts;
+import org.apache.hadoop.ozone.s3.S3GatewayConfigKeys;
+import org.apache.hadoop.util.PerformanceMetrics;
import org.apache.hadoop.util.Time;
/**
@@ -95,156 +97,160 @@ public final class S3GatewayMetrics implements
MetricsSource {
@Metric(about = "Latency for successfully retrieving an S3 bucket in " +
"nanoseconds")
- private MutableRate getBucketSuccessLatencyNs;
+ private PerformanceMetrics getBucketSuccessLatencyNs;
@Metric(about = "Latency for failing to retrieve an S3 bucket in
nanoseconds")
- private MutableRate getBucketFailureLatencyNs;
+ private PerformanceMetrics getBucketFailureLatencyNs;
@Metric(about = "Latency for successfully creating an S3 bucket in " +
"nanoseconds")
- private MutableRate createBucketSuccessLatencyNs;
+ private PerformanceMetrics createBucketSuccessLatencyNs;
@Metric(about = "Latency for failing to create an S3 bucket in nanoseconds")
- private MutableRate createBucketFailureLatencyNs;
+ private PerformanceMetrics createBucketFailureLatencyNs;
@Metric(about = "Latency for successfully checking the existence of an " +
"S3 bucket in nanoseconds")
- private MutableRate headBucketSuccessLatencyNs;
+ private PerformanceMetrics headBucketSuccessLatencyNs;
@Metric(about = "Latency for successfully deleting an S3 bucket in " +
"nanoseconds")
- private MutableRate deleteBucketSuccessLatencyNs;
+ private PerformanceMetrics deleteBucketSuccessLatencyNs;
@Metric(about = "Latency for failing to delete an S3 bucket in nanoseconds")
- private MutableRate deleteBucketFailureLatencyNs;
+ private PerformanceMetrics deleteBucketFailureLatencyNs;
@Metric(about = "Latency for successfully retrieving an S3 bucket ACL " +
"in nanoseconds")
- private MutableRate getAclSuccessLatencyNs;
+ private PerformanceMetrics getAclSuccessLatencyNs;
@Metric(about = "Latency for failing to retrieve an S3 bucket ACL " +
"in nanoseconds")
- private MutableRate getAclFailureLatencyNs;
+ private PerformanceMetrics getAclFailureLatencyNs;
@Metric(about = "Latency for successfully setting an S3 bucket ACL " +
"in nanoseconds")
- private MutableRate putAclSuccessLatencyNs;
+ private PerformanceMetrics putAclSuccessLatencyNs;
@Metric(about = "Latency for failing to set an S3 bucket ACL " +
"in nanoseconds")
- private MutableRate putAclFailureLatencyNs;
+ private PerformanceMetrics putAclFailureLatencyNs;
@Metric(about = "Latency for successfully listing multipart uploads " +
"in nanoseconds")
- private MutableRate listMultipartUploadsSuccessLatencyNs;
+ private PerformanceMetrics listMultipartUploadsSuccessLatencyNs;
@Metric(about = "Latency for failing to list multipart uploads " +
"in nanoseconds")
- private MutableRate listMultipartUploadsFailureLatencyNs;
+ private PerformanceMetrics listMultipartUploadsFailureLatencyNs;
// RootEndpoint
@Metric(about = "Latency for successfully listing S3 buckets " +
"in nanoseconds")
- private MutableRate listS3BucketsSuccessLatencyNs;
+ private PerformanceMetrics listS3BucketsSuccessLatencyNs;
@Metric(about = "Latency for failing to list S3 buckets " +
"in nanoseconds")
- private MutableRate listS3BucketsFailureLatencyNs;
+ private PerformanceMetrics listS3BucketsFailureLatencyNs;
// ObjectEndpoint
@Metric(about = "Latency for successfully creating a multipart object key " +
"in nanoseconds")
- private MutableRate createMultipartKeySuccessLatencyNs;
+ private PerformanceMetrics createMultipartKeySuccessLatencyNs;
@Metric(about = "Latency for failing to create a multipart object key in " +
"nanoseconds")
- private MutableRate createMultipartKeyFailureLatencyNs;
+ private PerformanceMetrics createMultipartKeyFailureLatencyNs;
@Metric(about = "Latency for successfully copying an S3 object in " +
"nanoseconds")
- private MutableRate copyObjectSuccessLatencyNs;
+ private PerformanceMetrics copyObjectSuccessLatencyNs;
@Metric(about = "Latency for failing to copy an S3 object in nanoseconds")
- private MutableRate copyObjectFailureLatencyNs;
+ private PerformanceMetrics copyObjectFailureLatencyNs;
@Metric(about = "Latency for successfully creating an S3 object key in " +
"nanoseconds")
- private MutableRate createKeySuccessLatencyNs;
+ private PerformanceMetrics createKeySuccessLatencyNs;
@Metric(about = "Latency for failing to create an S3 object key in " +
"nanoseconds")
- private MutableRate createKeyFailureLatencyNs;
+ private PerformanceMetrics createKeyFailureLatencyNs;
@Metric(about = "Latency for successfully listing parts of a multipart " +
"upload in nanoseconds")
- private MutableRate listPartsSuccessLatencyNs;
+ private PerformanceMetrics listPartsSuccessLatencyNs;
@Metric(about = "Latency for failing to list parts of a multipart upload " +
"in nanoseconds")
- private MutableRate listPartsFailureLatencyNs;
+ private PerformanceMetrics listPartsFailureLatencyNs;
@Metric(about = "Latency for successfully retrieving an S3 object in " +
"nanoseconds")
- private MutableRate getKeySuccessLatencyNs;
+ private PerformanceMetrics getKeySuccessLatencyNs;
@Metric(about = "Latency for failing to retrieve an S3 object in
nanoseconds")
- private MutableRate getKeyFailureLatencyNs;
+ private PerformanceMetrics getKeyFailureLatencyNs;
@Metric(about = "Latency for successfully retrieving metadata for an S3 " +
"object in nanoseconds")
- private MutableRate headKeySuccessLatencyNs;
+ private PerformanceMetrics headKeySuccessLatencyNs;
@Metric(about = "Latency for failing to retrieve metadata for an S3 object "
+
"in nanoseconds")
- private MutableRate headKeyFailureLatencyNs;
+ private PerformanceMetrics headKeyFailureLatencyNs;
@Metric(about = "Latency for successfully initiating a multipart upload in "
+
"nanoseconds")
- private MutableRate initMultipartUploadSuccessLatencyNs;
+ private PerformanceMetrics initMultipartUploadSuccessLatencyNs;
@Metric(about = "Latency for failing to initiate a multipart upload in " +
"nanoseconds")
- private MutableRate initMultipartUploadFailureLatencyNs;
+ private PerformanceMetrics initMultipartUploadFailureLatencyNs;
@Metric(about = "Latency for successfully completing a multipart upload in "
+
"nanoseconds")
- private MutableRate completeMultipartUploadSuccessLatencyNs;
+ private PerformanceMetrics completeMultipartUploadSuccessLatencyNs;
@Metric(about = "Latency for failing to complete a multipart upload in " +
"nanoseconds")
- private MutableRate completeMultipartUploadFailureLatencyNs;
+ private PerformanceMetrics completeMultipartUploadFailureLatencyNs;
@Metric(about = "Latency for successfully aborting a multipart upload in " +
"nanoseconds")
- private MutableRate abortMultipartUploadSuccessLatencyNs;
+ private PerformanceMetrics abortMultipartUploadSuccessLatencyNs;
@Metric(about = "Latency for failing to abort a multipart upload in " +
"nanoseconds")
- private MutableRate abortMultipartUploadFailureLatencyNs;
+ private PerformanceMetrics abortMultipartUploadFailureLatencyNs;
@Metric(about = "Latency for successfully deleting an S3 object in " +
"nanoseconds")
- private MutableRate deleteKeySuccessLatencyNs;
+ private PerformanceMetrics deleteKeySuccessLatencyNs;
@Metric(about = "Latency for failing to delete an S3 object in nanoseconds")
- private MutableRate deleteKeyFailureLatencyNs;
+ private PerformanceMetrics deleteKeyFailureLatencyNs;
@Metric(about = "Latency for put metadata of an key in nanoseconds")
- private MutableRate putKeyMetadataLatencyNs;
+ private PerformanceMetrics putKeyMetadataLatencyNs;
@Metric(about = "Latency for get metadata of an key in nanoseconds")
- private MutableRate getKeyMetadataLatencyNs;
+ private PerformanceMetrics getKeyMetadataLatencyNs;
@Metric(about = "Latency for copy metadata of an key in nanoseconds")
- private MutableRate copyKeyMetadataLatencyNs;
+ private PerformanceMetrics copyKeyMetadataLatencyNs;
/**
* Private constructor.
*/
- private S3GatewayMetrics() {
+ private S3GatewayMetrics(OzoneConfiguration conf) {
this.registry = new MetricsRegistry(SOURCE_NAME);
+ int[] intervals = conf.getInts(S3GatewayConfigKeys
+ .OZONE_S3G_METRICS_PERCENTILES_INTERVALS_SECONDS_KEY);
+ PerformanceMetrics.initializeMetrics(
+ this, registry, "Ops", "Time", intervals);
}
/**
@@ -252,13 +258,13 @@ public final class S3GatewayMetrics implements
MetricsSource {
*
* @return S3GatewayMetrics
*/
- public static synchronized S3GatewayMetrics create() {
+ public static synchronized S3GatewayMetrics create(OzoneConfiguration conf) {
if (instance != null) {
return instance;
}
MetricsSystem ms = DefaultMetricsSystem.instance();
instance = ms.register(SOURCE_NAME, "S3 Gateway Metrics",
- new S3GatewayMetrics());
+ new S3GatewayMetrics(conf));
return instance;
}
@@ -719,9 +725,13 @@ public final class S3GatewayMetrics implements
MetricsSource {
return listS3BucketsFailure.value();
}
- private long updateAndGetStats(MutableRate metric, long startNanos) {
+ private long updateAndGetStats(PerformanceMetrics metric, long startNanos) {
long value = Time.monotonicNowNanos() - startNanos;
metric.add(value);
return value;
}
+
+ public static synchronized S3GatewayMetrics getMetrics() {
+ return instance;
+ }
}
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneClientStub.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneClientStub.java
index 64f515060b..2ca712ae94 100644
---
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneClientStub.java
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/client/OzoneClientStub.java
@@ -19,6 +19,9 @@
*/
package org.apache.hadoop.ozone.client;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.s3.metrics.S3GatewayMetrics;
+
/**
* In-memory OzoneClient for testing.
*/
@@ -29,6 +32,7 @@ public class OzoneClientStub extends OzoneClient {
public OzoneClientStub(ObjectStoreStub objectStoreStub) {
super(objectStoreStub, new ClientProtocolStub(objectStoreStub));
+ S3GatewayMetrics.create(new OzoneConfiguration());
}
@Override
diff --git
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
index 2eb572f6b9..92bcec5c6e 100644
---
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
+++
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestPermissionCheck.java
@@ -28,6 +28,7 @@ import org.apache.hadoop.ozone.client.OzoneVolume;
import org.apache.hadoop.ozone.client.protocol.ClientProtocol;
import org.apache.hadoop.ozone.om.exceptions.OMException;
import org.apache.hadoop.ozone.s3.exception.OS3Exception;
+import org.apache.hadoop.ozone.s3.metrics.S3GatewayMetrics;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -84,6 +85,7 @@ public class TestPermissionCheck {
when(client.getConfiguration()).thenReturn(conf);
headers = mock(HttpHeaders.class);
clientProtocol = mock(ClientProtocol.class);
+ S3GatewayMetrics.create(conf);
when(client.getProxy()).thenReturn(clientProtocol);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]