You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by ad...@apache.org on 2023/04/18 06:39:55 UTC

[ozone] branch master updated: HDDS-8147. Introduce latency metrics for S3 Gateway operations (#4383)

This is an automated email from the ASF dual-hosted git repository.

adoroszlai 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 600bbd5ced HDDS-8147. Introduce latency metrics for S3 Gateway operations (#4383)
600bbd5ced is described below

commit 600bbd5ced05f07dd1071b80dad725b42cb95829
Author: tanvipenumudy <46...@users.noreply.github.com>
AuthorDate: Tue Apr 18 12:09:48 2023 +0530

    HDDS-8147. Introduce latency metrics for S3 Gateway operations (#4383)
---
 .../hadoop/ozone/s3/endpoint/BucketEndpoint.java   |  42 ++-
 .../hadoop/ozone/s3/endpoint/EndpointBase.java     |   4 +-
 .../hadoop/ozone/s3/endpoint/ObjectEndpoint.java   |  68 ++--
 .../hadoop/ozone/s3/endpoint/RootEndpoint.java     |   6 +-
 .../hadoop/ozone/s3/metrics/S3GatewayMetrics.java  | 377 ++++++++++++++++-----
 5 files changed, 369 insertions(+), 128 deletions(-)

diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
index 81a1cea265..095b160c8e 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
@@ -40,6 +40,7 @@ import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
 import org.apache.hadoop.ozone.s3.util.ContinueToken;
 import org.apache.hadoop.ozone.s3.util.S3StorageType;
 import org.apache.hadoop.ozone.security.acl.IAccessAuthorizer;
+import org.apache.hadoop.util.Time;
 import org.apache.http.HttpStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -102,6 +103,7 @@ public class BucketEndpoint extends EndpointBase {
       @QueryParam("uploads") String uploads,
       @QueryParam("acl") String aclMarker,
       @Context HttpHeaders hh) throws OS3Exception, IOException {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.GET_BUCKET;
     Iterator<? extends OzoneKey> ozoneKeyIterator;
     ContinueToken decodedToken =
@@ -111,7 +113,7 @@ public class BucketEndpoint extends EndpointBase {
       if (aclMarker != null) {
         s3GAction = S3GAction.GET_ACL;
         S3BucketAcl result = getAcl(bucketName);
-        getMetrics().incGetAclSuccess();
+        getMetrics().updateGetAclSuccessStats(startNanos);
         AUDIT.logReadSuccess(
             buildAuditMessageForSuccess(s3GAction, getAuditParameters()));
         return Response.ok(result, MediaType.APPLICATION_XML_TYPE).build();
@@ -130,7 +132,7 @@ public class BucketEndpoint extends EndpointBase {
       if (startAfter == null && marker != null) {
         startAfter = marker;
       }
-      
+
       OzoneBucket bucket = getBucket(bucketName);
       if (startAfter != null && continueToken != null) {
         // If continuation token and start after both are provided, then we
@@ -146,14 +148,14 @@ public class BucketEndpoint extends EndpointBase {
     } catch (OMException ex) {
       AUDIT.logReadFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
-      getMetrics().incGetBucketFailure();
+      getMetrics().updateGetBucketFailureStats(startNanos);
       if (isAccessDenied(ex)) {
         throw newError(S3ErrorTable.ACCESS_DENIED, bucketName, ex);
       } else {
         throw ex;
       }
     } catch (Exception ex) {
-      getMetrics().incGetBucketFailure();
+      getMetrics().updateGetBucketFailureStats(startNanos);
       AUDIT.logReadFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
       throw ex;
@@ -247,7 +249,7 @@ public class BucketEndpoint extends EndpointBase {
 
     AUDIT.logReadSuccess(buildAuditMessageForSuccess(s3GAction,
         getAuditParameters()));
-    getMetrics().incGetBucketSuccess();
+    getMetrics().updateGetBucketSuccessStats(startNanos);
     response.setKeyCount(
         response.getCommonPrefixes().size() + response.getContents().size());
     return Response.ok(response).build();
@@ -258,6 +260,7 @@ public class BucketEndpoint extends EndpointBase {
                       @QueryParam("acl") String aclMarker,
                       @Context HttpHeaders httpHeaders,
                       InputStream body) throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.CREATE_BUCKET;
 
     try {
@@ -271,12 +274,12 @@ public class BucketEndpoint extends EndpointBase {
       String location = createS3Bucket(bucketName);
       AUDIT.logWriteSuccess(
           buildAuditMessageForSuccess(s3GAction, getAuditParameters()));
-      getMetrics().incCreateBucketSuccess();
+      getMetrics().updateCreateBucketSuccessStats(startNanos);
       return Response.status(HttpStatus.SC_OK).header("Location", location)
           .build();
     } catch (OMException exception) {
       auditWriteFailure(s3GAction, exception);
-      getMetrics().incCreateBucketFailure();
+      getMetrics().updateCreateBucketFailureStats(startNanos);
       if (exception.getResult() == ResultCodes.INVALID_BUCKET_NAME) {
         throw newError(S3ErrorTable.INVALID_BUCKET_NAME, bucketName, exception);
       }
@@ -292,6 +295,7 @@ public class BucketEndpoint extends EndpointBase {
       @PathParam("bucket") String bucketName,
       @QueryParam("prefix") String prefix)
       throws OS3Exception, IOException {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.LIST_MULTIPART_UPLOAD;
 
     OzoneBucket bucket = getBucket(bucketName);
@@ -312,13 +316,13 @@ public class BucketEndpoint extends EndpointBase {
           )));
       AUDIT.logReadSuccess(buildAuditMessageForSuccess(s3GAction,
           getAuditParameters()));
-      getMetrics().incListMultipartUploadsSuccess();
+      getMetrics().updateListMultipartUploadsSuccessStats(startNanos);
       return Response.ok(result).build();
     } catch (OMException exception) {
       AUDIT.logReadFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(),
               exception));
-      getMetrics().incListMultipartUploadsFailure();
+      getMetrics().updateListMultipartUploadsFailureStats(startNanos);
       if (isAccessDenied(exception)) {
         throw newError(S3ErrorTable.ACCESS_DENIED, prefix, exception);
       }
@@ -339,12 +343,13 @@ public class BucketEndpoint extends EndpointBase {
   @HEAD
   public Response head(@PathParam("bucket") String bucketName)
       throws OS3Exception, IOException {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.HEAD_BUCKET;
     try {
       getBucket(bucketName);
       AUDIT.logReadSuccess(
           buildAuditMessageForSuccess(s3GAction, getAuditParameters()));
-      getMetrics().incHeadBucketSuccess();
+      getMetrics().updateHeadBucketSuccessStats(startNanos);
       return Response.ok().build();
     } catch (Exception e) {
       AUDIT.logReadFailure(
@@ -362,6 +367,7 @@ public class BucketEndpoint extends EndpointBase {
   @DELETE
   public Response delete(@PathParam("bucket") String bucketName)
       throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.DELETE_BUCKET;
 
     try {
@@ -369,7 +375,7 @@ public class BucketEndpoint extends EndpointBase {
     } catch (OMException ex) {
       AUDIT.logWriteFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
-      getMetrics().incDeleteBucketFailure();
+      getMetrics().updateDeleteBucketFailureStats(startNanos);
       if (ex.getResult() == ResultCodes.BUCKET_NOT_EMPTY) {
         throw newError(S3ErrorTable.BUCKET_NOT_EMPTY, bucketName, ex);
       } else if (ex.getResult() == ResultCodes.BUCKET_NOT_FOUND) {
@@ -387,7 +393,7 @@ public class BucketEndpoint extends EndpointBase {
 
     AUDIT.logWriteSuccess(buildAuditMessageForSuccess(s3GAction,
         getAuditParameters()));
-    getMetrics().incDeleteBucketSuccess();
+    getMetrics().updateDeleteBucketSuccessStats(startNanos);
     return Response
         .status(HttpStatus.SC_NO_CONTENT)
         .build();
@@ -454,6 +460,7 @@ public class BucketEndpoint extends EndpointBase {
    */
   public S3BucketAcl getAcl(String bucketName)
       throws OS3Exception, IOException {
+    long startNanos = Time.monotonicNowNanos();
     S3BucketAcl result = new S3BucketAcl();
     try {
       OzoneBucket bucket = getBucket(bucketName);
@@ -478,7 +485,7 @@ public class BucketEndpoint extends EndpointBase {
           new S3BucketAcl.AccessControlList(grantList));
       return result;
     } catch (OMException ex) {
-      getMetrics().incGetAclFailure();
+      getMetrics().updateGetAclFailureStats(startNanos);
       auditReadFailure(S3GAction.GET_ACL, ex);
       if (ex.getResult() == ResultCodes.BUCKET_NOT_FOUND) {
         throw newError(S3ErrorTable.NO_SUCH_BUCKET, bucketName, ex);
@@ -488,7 +495,7 @@ public class BucketEndpoint extends EndpointBase {
         throw newError(S3ErrorTable.INTERNAL_ERROR, bucketName, ex);
       }
     } catch (OS3Exception ex) {
-      getMetrics().incGetAclFailure();
+      getMetrics().updateGetAclFailureStats(startNanos);
       throw ex;
     }
   }
@@ -500,6 +507,7 @@ public class BucketEndpoint extends EndpointBase {
    */
   public Response putAcl(String bucketName, HttpHeaders httpHeaders,
                          InputStream body) throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     String grantReads = httpHeaders.getHeaderString(S3Acl.GRANT_READ);
     String grantWrites = httpHeaders.getHeaderString(S3Acl.GRANT_WRITE);
     String grantReadACP = httpHeaders.getHeaderString(S3Acl.GRANT_READ_CAP);
@@ -580,7 +588,7 @@ public class BucketEndpoint extends EndpointBase {
         volume.addAcl(acl);
       }
     } catch (OMException exception) {
-      getMetrics().incPutAclFailure();
+      getMetrics().updatePutAclFailureStats(startNanos);
       auditWriteFailure(S3GAction.PUT_ACL, exception);
       if (exception.getResult() == ResultCodes.BUCKET_NOT_FOUND) {
         throw newError(S3ErrorTable.NO_SUCH_BUCKET, bucketName, exception);
@@ -589,10 +597,10 @@ public class BucketEndpoint extends EndpointBase {
       }
       throw exception;
     } catch (OS3Exception ex) {
-      getMetrics().incPutAclFailure();
+      getMetrics().updatePutAclFailureStats(startNanos);
       throw ex;
     }
-    getMetrics().incPutAclSuccess();
+    getMetrics().updatePutAclSuccessStats(startNanos);
     return Response.status(HttpStatus.SC_OK).build();
   }
 
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 77b7211a3a..6063d8bc5b 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
@@ -58,6 +58,7 @@ import com.google.common.annotations.VisibleForTesting;
 
 import org.apache.hadoop.ozone.s3.metrics.S3GatewayMetrics;
 import org.apache.hadoop.ozone.s3.util.AuditUtils;
+import org.apache.hadoop.util.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -159,10 +160,11 @@ public abstract class EndpointBase implements Auditor {
    */
   protected String createS3Bucket(String bucketName) throws
       IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     try {
       client.getObjectStore().createS3Bucket(bucketName);
     } catch (OMException ex) {
-      getMetrics().incCreateBucketFailure();
+      getMetrics().updateCreateBucketFailureStats(startNanos);
       if (ex.getResult() == ResultCodes.PERMISSION_DENIED) {
         throw newError(S3ErrorTable.ACCESS_DENIED, bucketName, ex);
       } else if (ex.getResult() == ResultCodes.INVALID_TOKEN) {
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
index 200989a247..d88c61b795 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java
@@ -177,7 +177,7 @@ public class ObjectEndpoint extends EndpointBase {
       @QueryParam("partNumber")  int partNumber,
       @QueryParam("uploadId") @DefaultValue("") String uploadID,
       InputStream body) throws IOException, OS3Exception {
-
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.CREATE_KEY;
 
     boolean auditSuccess = true;
@@ -238,16 +238,16 @@ public class ObjectEndpoint extends EndpointBase {
           keyPath, length, replicationConfig, customMetadata);
       IOUtils.copy(body, output);
 
-      getMetrics().incCreateKeySuccess();
+      getMetrics().updateCreateKeySuccessStats(startNanos);
       return Response.ok().status(HttpStatus.SC_OK)
           .build();
     } catch (OMException ex) {
       auditSuccess = false;
       auditWriteFailure(s3GAction, ex);
       if (copyHeader != null) {
-        getMetrics().incCopyObjectFailure();
+        getMetrics().updateCopyObjectFailureStats(startNanos);
       } else {
-        getMetrics().incCreateKeyFailure();
+        getMetrics().updateCreateKeyFailureStats(startNanos);
       }
       if (ex.getResult() == ResultCodes.NOT_A_FILE) {
         OS3Exception os3Exception = newError(INVALID_REQUEST, keyPath, ex);
@@ -269,9 +269,9 @@ public class ObjectEndpoint extends EndpointBase {
       auditSuccess = false;
       auditWriteFailure(s3GAction, ex);
       if (copyHeader != null) {
-        getMetrics().incCopyObjectFailure();
+        getMetrics().updateCopyObjectFailureStats(startNanos);
       } else {
-        getMetrics().incCreateKeyFailure();
+        getMetrics().updateCreateKeyFailureStats(startNanos);
       }
       throw ex;
     } finally {
@@ -302,7 +302,7 @@ public class ObjectEndpoint extends EndpointBase {
       @QueryParam("max-parts") @DefaultValue("1000") int maxParts,
       @QueryParam("part-number-marker") String partNumberMarker)
       throws IOException, OS3Exception {
-
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.GET_KEY;
     boolean auditSuccess = true;
 
@@ -399,7 +399,7 @@ public class ObjectEndpoint extends EndpointBase {
         }
       }
       addLastModifiedDate(responseBuilder, keyDetails);
-      getMetrics().incGetKeySuccess();
+      getMetrics().updateGetKeySuccessStats(startNanos);
       return responseBuilder.build();
     } catch (OMException ex) {
       auditSuccess = false;
@@ -407,9 +407,9 @@ public class ObjectEndpoint extends EndpointBase {
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex)
       );
       if (uploadId != null) {
-        getMetrics().incListPartsFailure();
+        getMetrics().updateListPartsFailureStats(startNanos);
       } else {
-        getMetrics().incGetKeyFailure();
+        getMetrics().updateGetKeyFailureStats(startNanos);
       }
       if (ex.getResult() == ResultCodes.KEY_NOT_FOUND) {
         throw newError(S3ErrorTable.NO_SUCH_KEY, keyPath, ex);
@@ -456,7 +456,7 @@ public class ObjectEndpoint extends EndpointBase {
   public Response head(
       @PathParam("bucket") String bucketName,
       @PathParam("path") String keyPath) throws IOException, OS3Exception {
-
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.HEAD_KEY;
 
     OzoneKey key;
@@ -466,7 +466,7 @@ public class ObjectEndpoint extends EndpointBase {
     } catch (OMException ex) {
       AUDIT.logReadFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
-      getMetrics().incHeadKeyFailure();
+      getMetrics().updateHeadKeyFailureStats(startNanos);
       if (ex.getResult() == ResultCodes.KEY_NOT_FOUND) {
         // Just return 404 with no content
         return Response.status(Status.NOT_FOUND).build();
@@ -489,7 +489,7 @@ public class ObjectEndpoint extends EndpointBase {
         .header("Content-Type", "binary/octet-stream");
     addLastModifiedDate(response, key);
     addCustomMetadataHeaders(response, key);
-    getMetrics().incHeadKeySuccess();
+    getMetrics().updateHeadKeySuccessStats(startNanos);
     AUDIT.logReadSuccess(buildAuditMessageForSuccess(s3GAction,
         getAuditParameters()));
     return response.build();
@@ -507,6 +507,7 @@ public class ObjectEndpoint extends EndpointBase {
   private Response abortMultipartUpload(OzoneVolume volume, String bucket,
                                         String key, String uploadId)
       throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     try {
       getClientProtocol().abortMultipartUpload(volume.getName(), bucket,
           key, uploadId);
@@ -518,7 +519,7 @@ public class ObjectEndpoint extends EndpointBase {
       }
       throw ex;
     }
-    getMetrics().incAbortMultiPartUploadSuccess();
+    getMetrics().updateAbortMultipartUploadSuccessStats(startNanos);
     return Response
         .status(Status.NO_CONTENT)
         .build();
@@ -540,7 +541,7 @@ public class ObjectEndpoint extends EndpointBase {
       @PathParam("path") String keyPath,
       @QueryParam("uploadId") @DefaultValue("") String uploadId) throws
       IOException, OS3Exception {
-
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.DELETE_KEY;
 
     try {
@@ -555,9 +556,9 @@ public class ObjectEndpoint extends EndpointBase {
       AUDIT.logWriteFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
       if (uploadId != null && !uploadId.equals("")) {
-        getMetrics().incAbortMultiPartUploadFailure();
+        getMetrics().updateAbortMultipartUploadFailureStats(startNanos);
       } else {
-        getMetrics().incDeleteKeyFailure();
+        getMetrics().updateDeleteKeyFailureStats(startNanos);
       }
       if (ex.getResult() == ResultCodes.BUCKET_NOT_FOUND) {
         throw newError(S3ErrorTable.NO_SUCH_BUCKET, bucketName, ex);
@@ -578,13 +579,13 @@ public class ObjectEndpoint extends EndpointBase {
       AUDIT.logWriteFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
       if (uploadId != null && !uploadId.equals("")) {
-        getMetrics().incAbortMultiPartUploadFailure();
+        getMetrics().updateAbortMultipartUploadFailureStats(startNanos);
       } else {
-        getMetrics().incDeleteKeyFailure();
+        getMetrics().updateDeleteKeyFailureStats(startNanos);
       }
       throw ex;
     }
-    getMetrics().incDeleteKeySuccess();
+    getMetrics().updateDeleteKeySuccessStats(startNanos);
     AUDIT.logWriteSuccess(buildAuditMessageForSuccess(s3GAction,
         getAuditParameters()));
     return Response
@@ -605,6 +606,7 @@ public class ObjectEndpoint extends EndpointBase {
       @PathParam("path") String key
   )
       throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.INIT_MULTIPART_UPLOAD;
 
     try {
@@ -626,12 +628,12 @@ public class ObjectEndpoint extends EndpointBase {
 
       AUDIT.logWriteSuccess(
           buildAuditMessageForSuccess(s3GAction, getAuditParameters()));
-      getMetrics().incInitMultiPartUploadSuccess();
+      getMetrics().updateInitMultipartUploadSuccessStats(startNanos);
       return Response.status(Status.OK).entity(
           multipartUploadInitiateResponse).build();
     } catch (OMException ex) {
       auditWriteFailure(s3GAction, ex);
-      getMetrics().incInitMultiPartUploadFailure();
+      getMetrics().updateInitMultipartUploadFailureStats(startNanos);
       if (isAccessDenied(ex)) {
         throw newError(S3ErrorTable.ACCESS_DENIED, key, ex);
       }
@@ -639,7 +641,7 @@ public class ObjectEndpoint extends EndpointBase {
     } catch (Exception ex) {
       AUDIT.logWriteFailure(
           buildAuditMessageForFailure(s3GAction, getAuditParameters(), ex));
-      getMetrics().incInitMultiPartUploadFailure();
+      getMetrics().updateInitMultipartUploadFailureStats(startNanos);
       throw ex;
     }
   }
@@ -672,6 +674,7 @@ public class ObjectEndpoint extends EndpointBase {
       @QueryParam("uploadId") @DefaultValue("") String uploadID,
       CompleteMultipartUploadRequest multipartUploadRequest)
       throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     S3GAction s3GAction = S3GAction.COMPLETE_MULTIPART_UPLOAD;
     OzoneVolume volume = getVolume();
     // Using LinkedHashMap to preserve ordering of parts list.
@@ -701,12 +704,12 @@ public class ObjectEndpoint extends EndpointBase {
       completeMultipartUploadResponse.setLocation(bucket);
       AUDIT.logWriteSuccess(
           buildAuditMessageForSuccess(s3GAction, getAuditParameters()));
-      getMetrics().incCompleteMultiPartUploadSuccess();
+      getMetrics().updateCompleteMultipartUploadSuccessStats(startNanos);
       return Response.status(Status.OK).entity(completeMultipartUploadResponse)
           .build();
     } catch (OMException ex) {
       auditWriteFailure(s3GAction, ex);
-      getMetrics().incCompleteMultiPartUploadFailure();
+      getMetrics().updateCompleteMultipartUploadFailureStats(startNanos);
       if (ex.getResult() == ResultCodes.INVALID_PART) {
         throw newError(S3ErrorTable.INVALID_PART, key, ex);
       } else if (ex.getResult() == ResultCodes.INVALID_PART_ORDER) {
@@ -743,6 +746,7 @@ public class ObjectEndpoint extends EndpointBase {
                                       String key, long length, int partNumber,
                                       String uploadID, InputStream body)
       throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     try {
       String copyHeader;
       OzoneOutputStream ozoneOutputStream = null;
@@ -810,7 +814,7 @@ public class ObjectEndpoint extends EndpointBase {
           ozoneOutputStream.getCommitUploadPartInfo();
       String eTag = omMultipartCommitUploadPartInfo.getPartName();
 
-      getMetrics().incCreateMultipartKeySuccess();
+      getMetrics().updateCreateMultipartKeySuccessStats(startNanos);
       if (copyHeader != null) {
         return Response.ok(new CopyPartResult(eTag)).build();
       } else {
@@ -819,7 +823,7 @@ public class ObjectEndpoint extends EndpointBase {
       }
 
     } catch (OMException ex) {
-      getMetrics().incCreateMultipartKeyFailure();
+      getMetrics().updateCreateMultipartKeyFailureStats(startNanos);
       if (ex.getResult() == ResultCodes.NO_SUCH_MULTIPART_UPLOAD_ERROR) {
         throw newError(NO_SUCH_UPLOAD, uploadID, ex);
       } else if (isAccessDenied(ex)) {
@@ -843,6 +847,7 @@ public class ObjectEndpoint extends EndpointBase {
    */
   private Response listParts(String bucket, String key, String uploadID,
       int partNumberMarker, int maxParts) throws IOException, OS3Exception {
+    long startNanos = Time.monotonicNowNanos();
     ListPartsResponse listPartsResponse = new ListPartsResponse();
     try {
       OzoneBucket ozoneBucket = getBucket(bucket);
@@ -874,9 +879,8 @@ public class ObjectEndpoint extends EndpointBase {
             partInfo.getModificationTime()));
         listPartsResponse.addPart(part);
       });
-
     } catch (OMException ex) {
-      getMetrics().incListPartsFailure();
+      getMetrics().updateListPartsFailureStats(startNanos);
       if (ex.getResult() == ResultCodes.NO_SUCH_MULTIPART_UPLOAD_ERROR) {
         throw newError(NO_SUCH_UPLOAD, uploadID, ex);
       } else if (isAccessDenied(ex)) {
@@ -885,7 +889,7 @@ public class ObjectEndpoint extends EndpointBase {
       }
       throw ex;
     }
-    getMetrics().incListPartsSuccess();
+    getMetrics().updateListPartsSuccessStats(startNanos);
     return Response.status(Status.OK).entity(listPartsResponse).build();
   }
 
@@ -918,7 +922,7 @@ public class ObjectEndpoint extends EndpointBase {
                                         ReplicationConfig replicationConfig,
                                         boolean storageTypeDefault)
       throws OS3Exception, IOException {
-
+    long startNanos = Time.monotonicNowNanos();
     Pair<String, String> result = parseSourceHeader(copyHeader);
 
     String sourceBucket = result.getLeft();
@@ -964,7 +968,7 @@ public class ObjectEndpoint extends EndpointBase {
       final OzoneKeyDetails destKeyDetails = getClientProtocol().getKeyDetails(
           volume.getName(), destBucket, destkey);
 
-      getMetrics().incCopyObjectSuccess();
+      getMetrics().updateCopyObjectSuccessStats(startNanos);
       CopyObjectResponse copyObjectResponse = new CopyObjectResponse();
       copyObjectResponse.setETag(OzoneUtils.getRequestID());
       copyObjectResponse.setLastModified(destKeyDetails.getModificationTime());
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java
index 57d0d12cfa..09360b6395 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/RootEndpoint.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.s3.commontypes.BucketMetadata;
 import org.apache.hadoop.ozone.s3.exception.OS3Exception;
 
+import org.apache.hadoop.util.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,6 +51,7 @@ public class RootEndpoint extends EndpointBase {
   @GET
   public Response get()
       throws OS3Exception, IOException {
+    long startNanos = Time.monotonicNowNanos();
     boolean auditSuccess = true;
     try {
       ListBucketResponse response = new ListBucketResponse();
@@ -58,7 +60,7 @@ public class RootEndpoint extends EndpointBase {
       try {
         bucketIterator = listS3Buckets(null);
       } catch (Exception e) {
-        getMetrics().incListS3BucketsFailure();
+        getMetrics().updateListS3BucketsFailureStats(startNanos);
         throw e;
       }
 
@@ -70,7 +72,7 @@ public class RootEndpoint extends EndpointBase {
         response.addBucket(bucketMetadata);
       }
 
-      getMetrics().incListS3BucketsSuccess();
+      getMetrics().updateListS3BucketsSuccessStats(startNanos);
       return Response.ok(response).build();
     } catch (Exception ex) {
       auditSuccess = false;
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 05388d659e..4eb2ab2af1 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
@@ -27,7 +27,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.util.Time;
 
 /**
  * This class maintains S3 Gateway related metrics.
@@ -74,15 +76,155 @@ public final class S3GatewayMetrics implements MetricsSource {
   private @Metric MutableCounterLong getKeyFailure;
   private @Metric MutableCounterLong headKeySuccess;
   private @Metric MutableCounterLong headKeyFailure;
-  private @Metric MutableCounterLong initMultiPartUploadSuccess;
-  private @Metric MutableCounterLong initMultiPartUploadFailure;
-  private @Metric MutableCounterLong completeMultiPartUploadSuccess;
-  private @Metric MutableCounterLong completeMultiPartUploadFailure;
-  private @Metric MutableCounterLong abortMultiPartUploadSuccess;
-  private @Metric MutableCounterLong abortMultiPartUploadFailure;
+  private @Metric MutableCounterLong initMultipartUploadSuccess;
+  private @Metric MutableCounterLong initMultipartUploadFailure;
+  private @Metric MutableCounterLong completeMultipartUploadSuccess;
+  private @Metric MutableCounterLong completeMultipartUploadFailure;
+  private @Metric MutableCounterLong abortMultipartUploadSuccess;
+  private @Metric MutableCounterLong abortMultipartUploadFailure;
   private @Metric MutableCounterLong deleteKeySuccess;
   private @Metric MutableCounterLong deleteKeyFailure;
 
+  // S3 Gateway Latency Metrics
+  // BucketEndpoint
+
+  @Metric(about = "Latency for successfully retrieving an S3 bucket in " +
+      "nanoseconds")
+  private MutableRate getBucketSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to retrieve an S3 bucket in nanoseconds")
+  private MutableRate getBucketFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully creating an S3 bucket in " +
+      "nanoseconds")
+  private MutableRate createBucketSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to create an S3 bucket in nanoseconds")
+  private MutableRate createBucketFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully checking the existence of an " +
+      "S3 bucket in nanoseconds")
+  private MutableRate headBucketSuccessLatencyNs;
+
+  @Metric(about = "Latency for successfully deleting an S3 bucket in " +
+      "nanoseconds")
+  private MutableRate deleteBucketSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to delete an S3 bucket in nanoseconds")
+  private MutableRate deleteBucketFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully retrieving an S3 bucket ACL " +
+      "in nanoseconds")
+  private MutableRate getAclSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to retrieve an S3 bucket ACL " +
+      "in nanoseconds")
+  private MutableRate getAclFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully setting an S3 bucket ACL " +
+      "in nanoseconds")
+  private MutableRate putAclSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to set an S3 bucket ACL " +
+      "in nanoseconds")
+  private MutableRate putAclFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully listing multipart uploads " +
+      "in nanoseconds")
+  private MutableRate listMultipartUploadsSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to list multipart uploads " +
+      "in nanoseconds")
+  private MutableRate listMultipartUploadsFailureLatencyNs;
+
+  // RootEndpoint
+
+  @Metric(about = "Latency for successfully listing S3 buckets " +
+      "in nanoseconds")
+  private MutableRate listS3BucketsSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to list S3 buckets " +
+      "in nanoseconds")
+  private MutableRate listS3BucketsFailureLatencyNs;
+
+  // ObjectEndpoint
+
+  @Metric(about = "Latency for successfully creating a multipart object key " +
+      "in nanoseconds")
+  private MutableRate createMultipartKeySuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to create a multipart object key in " +
+      "nanoseconds")
+  private MutableRate createMultipartKeyFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully copying an S3 object in " +
+      "nanoseconds")
+  private MutableRate copyObjectSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to copy an S3 object in nanoseconds")
+  private MutableRate copyObjectFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully creating an S3 object key in " +
+      "nanoseconds")
+  private MutableRate createKeySuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to create an S3 object key in " +
+      "nanoseconds")
+  private MutableRate createKeyFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully listing parts of a multipart " +
+      "upload in nanoseconds")
+  private MutableRate listPartsSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to list parts of a multipart upload " +
+      "in nanoseconds")
+  private MutableRate listPartsFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully retrieving an S3 object in " +
+      "nanoseconds")
+  private MutableRate getKeySuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to retrieve an S3 object in nanoseconds")
+  private MutableRate getKeyFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully retrieving metadata for an S3 " +
+      "object in nanoseconds")
+  private MutableRate headKeySuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to retrieve metadata for an S3 object " +
+      "in nanoseconds")
+  private MutableRate headKeyFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully initiating a multipart upload in " +
+      "nanoseconds")
+  private MutableRate initMultipartUploadSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to initiate a multipart upload in " +
+      "nanoseconds")
+  private MutableRate initMultipartUploadFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully completing a multipart upload in " +
+      "nanoseconds")
+  private MutableRate completeMultipartUploadSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to complete a multipart upload in " +
+      "nanoseconds")
+  private MutableRate completeMultipartUploadFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully aborting a multipart upload in " +
+      "nanoseconds")
+  private MutableRate abortMultipartUploadSuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to abort a multipart upload in " +
+      "nanoseconds")
+  private MutableRate abortMultipartUploadFailureLatencyNs;
+
+  @Metric(about = "Latency for successfully deleting an S3 object in " +
+      "nanoseconds")
+  private MutableRate deleteKeySuccessLatencyNs;
+
+  @Metric(about = "Latency for failing to delete an S3 object in nanoseconds")
+  private MutableRate deleteKeyFailureLatencyNs;
 
   /**
    * Private constructor.
@@ -121,188 +263,271 @@ public final class S3GatewayMetrics implements MetricsSource {
 
     // BucketEndpoint
     getBucketSuccess.snapshot(recordBuilder, true);
+    getBucketSuccessLatencyNs.snapshot(recordBuilder, true);
     getBucketFailure.snapshot(recordBuilder, true);
+    getBucketFailureLatencyNs.snapshot(recordBuilder, true);
     createBucketSuccess.snapshot(recordBuilder, true);
+    createBucketSuccessLatencyNs.snapshot(recordBuilder, true);
     createBucketFailure.snapshot(recordBuilder, true);
+    createBucketFailureLatencyNs.snapshot(recordBuilder, true);
     headBucketSuccess.snapshot(recordBuilder, true);
+    headBucketSuccessLatencyNs.snapshot(recordBuilder, true);
     deleteBucketSuccess.snapshot(recordBuilder, true);
+    deleteBucketSuccessLatencyNs.snapshot(recordBuilder, true);
     deleteBucketFailure.snapshot(recordBuilder, true);
+    deleteBucketFailureLatencyNs.snapshot(recordBuilder, true);
     getAclSuccess.snapshot(recordBuilder, true);
+    getAclSuccessLatencyNs.snapshot(recordBuilder, true);
     getAclFailure.snapshot(recordBuilder, true);
+    getAclFailureLatencyNs.snapshot(recordBuilder, true);
     putAclSuccess.snapshot(recordBuilder, true);
+    putAclSuccessLatencyNs.snapshot(recordBuilder, true);
     putAclFailure.snapshot(recordBuilder, true);
+    putAclFailureLatencyNs.snapshot(recordBuilder, true);
     listMultipartUploadsSuccess.snapshot(recordBuilder, true);
+    listMultipartUploadsSuccessLatencyNs.snapshot(recordBuilder, true);
     listMultipartUploadsFailure.snapshot(recordBuilder, true);
+    listMultipartUploadsFailureLatencyNs.snapshot(recordBuilder, true);
 
     // RootEndpoint
     listS3BucketsSuccess.snapshot(recordBuilder, true);
+    listS3BucketsSuccessLatencyNs.snapshot(recordBuilder, true);
     listS3BucketsFailure.snapshot(recordBuilder, true);
+    listS3BucketsFailureLatencyNs.snapshot(recordBuilder, true);
 
     // ObjectEndpoint
     createMultipartKeySuccess.snapshot(recordBuilder, true);
+    createMultipartKeySuccessLatencyNs.snapshot(recordBuilder, true);
     createMultipartKeyFailure.snapshot(recordBuilder, true);
+    createMultipartKeyFailureLatencyNs.snapshot(recordBuilder, true);
     copyObjectSuccess.snapshot(recordBuilder, true);
+    copyObjectSuccessLatencyNs.snapshot(recordBuilder, true);
     copyObjectFailure.snapshot(recordBuilder, true);
+    copyObjectFailureLatencyNs.snapshot(recordBuilder, true);
     createKeySuccess.snapshot(recordBuilder, true);
+    createKeySuccessLatencyNs.snapshot(recordBuilder, true);
     createKeyFailure.snapshot(recordBuilder, true);
+    createKeyFailureLatencyNs.snapshot(recordBuilder, true);
     listPartsSuccess.snapshot(recordBuilder, true);
+    listPartsSuccessLatencyNs.snapshot(recordBuilder, true);
     listPartsFailure.snapshot(recordBuilder, true);
+    listPartsFailureLatencyNs.snapshot(recordBuilder, true);
     getKeySuccess.snapshot(recordBuilder, true);
+    getKeySuccessLatencyNs.snapshot(recordBuilder, true);
     getKeyFailure.snapshot(recordBuilder, true);
+    getKeyFailureLatencyNs.snapshot(recordBuilder, true);
     headKeySuccess.snapshot(recordBuilder, true);
+    headKeySuccessLatencyNs.snapshot(recordBuilder, true);
     headKeyFailure.snapshot(recordBuilder, true);
-    initMultiPartUploadSuccess.snapshot(recordBuilder, true);
-    initMultiPartUploadFailure.snapshot(recordBuilder, true);
-    completeMultiPartUploadSuccess.snapshot(recordBuilder, true);
-    completeMultiPartUploadFailure.snapshot(recordBuilder, true);
-    abortMultiPartUploadSuccess.snapshot(recordBuilder, true);
-    abortMultiPartUploadFailure.snapshot(recordBuilder, true);
+    headKeyFailureLatencyNs.snapshot(recordBuilder, true);
+    initMultipartUploadSuccess.snapshot(recordBuilder, true);
+    initMultipartUploadSuccessLatencyNs.snapshot(recordBuilder, true);
+    initMultipartUploadFailure.snapshot(recordBuilder, true);
+    initMultipartUploadFailureLatencyNs.snapshot(recordBuilder, true);
+    completeMultipartUploadSuccess.snapshot(recordBuilder, true);
+    completeMultipartUploadSuccessLatencyNs.snapshot(recordBuilder, true);
+    completeMultipartUploadFailure.snapshot(recordBuilder, true);
+    completeMultipartUploadFailureLatencyNs.snapshot(recordBuilder, true);
+    abortMultipartUploadSuccess.snapshot(recordBuilder, true);
+    abortMultipartUploadSuccessLatencyNs.snapshot(recordBuilder, true);
+    abortMultipartUploadFailure.snapshot(recordBuilder, true);
+    abortMultipartUploadFailureLatencyNs.snapshot(recordBuilder, true);
     deleteKeySuccess.snapshot(recordBuilder, true);
+    deleteKeySuccessLatencyNs.snapshot(recordBuilder, true);
     deleteKeyFailure.snapshot(recordBuilder, true);
+    deleteKeyFailureLatencyNs.snapshot(recordBuilder, true);
   }
 
-  // INC
-  public void incGetBucketSuccess() {
+  // INC and UPDATE
+  // BucketEndpoint
+
+  public void updateGetBucketSuccessStats(long startNanos) {
     getBucketSuccess.incr();
+    getBucketSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incGetBucketFailure() {
+  public void updateGetBucketFailureStats(long startNanos) {
     getBucketFailure.incr();
+    getBucketFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incListS3BucketsSuccess() {
-    listS3BucketsSuccess.incr();
+  public void updateCreateBucketSuccessStats(long startNanos) {
+    createBucketSuccess.incr();
+    createBucketSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-
-  public void incListS3BucketsFailure() {
-    listS3BucketsFailure.incr();
+  public void updateCreateBucketFailureStats(long startNanos) {
+    createBucketFailure.incr();
+    createBucketFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
+  public void updateHeadBucketSuccessStats(long startNanos) {
+    headBucketSuccess.incr();
+    headBucketSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
+  }
 
-  public void incCreateBucketSuccess() {
-    createBucketSuccess.incr();
+  public void updateDeleteBucketSuccessStats(long startNanos) {
+    deleteBucketSuccess.incr();
+    deleteBucketSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCreateBucketFailure() {
-    createBucketFailure.incr();
+  public void updateDeleteBucketFailureStats(long startNanos) {
+    deleteBucketFailure.incr();
+    deleteBucketFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incPutAclSuccess() {
-    putAclSuccess.incr();
+  public void updateGetAclSuccessStats(long startNanos) {
+    getAclSuccess.incr();
+    getAclSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incPutAclFailure() {
-    putAclFailure.incr();
+  public void updateGetAclFailureStats(long startNanos) {
+    getAclFailure.incr();
+    getAclFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incGetAclSuccess() {
-    getAclSuccess.incr();
+  public void updatePutAclSuccessStats(long startNanos) {
+    putAclSuccess.incr();
+    putAclSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incGetAclFailure() {
-    getAclFailure.incr();
+  public void updatePutAclFailureStats(long startNanos) {
+    putAclFailure.incr();
+    putAclFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incListMultipartUploadsSuccess() {
+  public void updateListMultipartUploadsSuccessStats(long startNanos) {
     listMultipartUploadsSuccess.incr();
+    listMultipartUploadsSuccessLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incListMultipartUploadsFailure() {
+  public void updateListMultipartUploadsFailureStats(long startNanos) {
     listMultipartUploadsFailure.incr();
+    listMultipartUploadsFailureLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incHeadBucketSuccess() {
-    headBucketSuccess.incr();
-  }
-
+  // RootEndpoint
 
-  public void incDeleteBucketSuccess() {
-    deleteBucketSuccess.incr();
+  public void updateListS3BucketsSuccessStats(long startNanos) {
+    listS3BucketsSuccess.incr();
+    listS3BucketsSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incDeleteBucketFailure() {
-    deleteBucketFailure.incr();
+  public void updateListS3BucketsFailureStats(long startNanos) {
+    listS3BucketsFailure.incr();
+    listS3BucketsFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCreateMultipartKeySuccess() {
+  // ObjectEndpoint
+
+  public void updateCreateMultipartKeySuccessStats(long startNanos) {
     createMultipartKeySuccess.incr();
+    createMultipartKeySuccessLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCreateMultipartKeyFailure() {
+  public void updateCreateMultipartKeyFailureStats(long startNanos) {
     createMultipartKeyFailure.incr();
+    createMultipartKeyFailureLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCopyObjectSuccess() {
+  public void updateCopyObjectSuccessStats(long startNanos) {
     copyObjectSuccess.incr();
+    copyObjectSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCopyObjectFailure() {
+  public void updateCopyObjectFailureStats(long startNanos) {
     copyObjectFailure.incr();
+    copyObjectFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCreateKeySuccess() {
+  public void updateCreateKeySuccessStats(long startNanos) {
     createKeySuccess.incr();
+    createKeySuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCreateKeyFailure() {
+  public void updateCreateKeyFailureStats(long startNanos) {
     createKeyFailure.incr();
+    createKeyFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incListPartsSuccess() {
+  public void updateListPartsSuccessStats(long startNanos) {
     listPartsSuccess.incr();
+    listPartsSuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incListPartsFailure() {
+  public void updateListPartsFailureStats(long startNanos) {
     listPartsFailure.incr();
+    listPartsFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incGetKeySuccess() {
+  public void updateGetKeySuccessStats(long startNanos) {
     getKeySuccess.incr();
+    getKeySuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incGetKeyFailure() {
+  public void updateGetKeyFailureStats(long startNanos) {
     getKeyFailure.incr();
+    getKeyFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incHeadKeySuccess() {
+  public void updateHeadKeySuccessStats(long startNanos) {
     headKeySuccess.incr();
+    headKeySuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incHeadKeyFailure() {
+  public void updateHeadKeyFailureStats(long startNanos) {
     headKeyFailure.incr();
+    headKeyFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incAbortMultiPartUploadSuccess() {
-    abortMultiPartUploadSuccess.incr();
+  public void updateInitMultipartUploadSuccessStats(long startNanos) {
+    initMultipartUploadSuccess.incr();
+    initMultipartUploadSuccessLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incAbortMultiPartUploadFailure() {
-    abortMultiPartUploadFailure.incr();
+  public void updateInitMultipartUploadFailureStats(long startNanos) {
+    initMultipartUploadFailure.incr();
+    initMultipartUploadFailureLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incDeleteKeySuccess() {
-    deleteKeySuccess.incr();
+  public void updateCompleteMultipartUploadSuccessStats(long startNanos) {
+    completeMultipartUploadSuccess.incr();
+    completeMultipartUploadSuccessLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incDeleteKeyFailure() {
-    deleteKeyFailure.incr();
+  public void updateCompleteMultipartUploadFailureStats(long startNanos) {
+    completeMultipartUploadFailure.incr();
+    completeMultipartUploadFailureLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incInitMultiPartUploadSuccess() {
-    initMultiPartUploadSuccess.incr();
+  public void updateAbortMultipartUploadSuccessStats(long startNanos) {
+    abortMultipartUploadSuccess.incr();
+    abortMultipartUploadSuccessLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incInitMultiPartUploadFailure() {
-    initMultiPartUploadFailure.incr();
+  public void updateAbortMultipartUploadFailureStats(long startNanos) {
+    abortMultipartUploadFailure.incr();
+    abortMultipartUploadFailureLatencyNs.add(
+        Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCompleteMultiPartUploadSuccess() {
-    completeMultiPartUploadSuccess.incr();
+  public void updateDeleteKeySuccessStats(long startNanos) {
+    deleteKeySuccess.incr();
+    deleteKeySuccessLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
-  public void incCompleteMultiPartUploadFailure() {
-    completeMultiPartUploadFailure.incr();
+  public void updateDeleteKeyFailureStats(long startNanos) {
+    deleteKeyFailure.incr();
+    deleteKeyFailureLatencyNs.add(Time.monotonicNowNanos() - startNanos);
   }
 
   // GET
@@ -375,11 +600,11 @@ public final class S3GatewayMetrics implements MetricsSource {
   }
 
   public long getCompleteMultiPartUploadSuccess() {
-    return completeMultiPartUploadSuccess.value();
+    return completeMultipartUploadSuccess.value();
   }
 
   public long getCompleteMultiPartUploadFailure() {
-    return completeMultiPartUploadFailure.value();
+    return completeMultipartUploadFailure.value();
   }
 
   public long getListPartsSuccess() {
@@ -407,11 +632,11 @@ public final class S3GatewayMetrics implements MetricsSource {
   }
 
   public long getInitMultiPartUploadSuccess() {
-    return initMultiPartUploadSuccess.value();
+    return initMultipartUploadSuccess.value();
   }
 
   public long getInitMultiPartUploadFailure() {
-    return initMultiPartUploadFailure.value();
+    return initMultipartUploadFailure.value();
   }
 
   public long getDeleteKeySuccess() {
@@ -431,11 +656,11 @@ public final class S3GatewayMetrics implements MetricsSource {
   }
 
   public long getAbortMultiPartUploadSuccess() {
-    return abortMultiPartUploadSuccess.value();
+    return abortMultipartUploadSuccess.value();
   }
 
   public long getAbortMultiPartUploadFailure() {
-    return abortMultiPartUploadFailure.value();
+    return abortMultipartUploadFailure.value();
   }
 
   public long getHeadKeyFailure() {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org