From 6dd1af9ab32a85b28b94a6079cb50f23607ebd51 Mon Sep 17 00:00:00 2001 From: Vikas Kumar Date: Sun, 5 Jan 2025 12:32:05 +0530 Subject: [PATCH] RANGER-4388: KMS metrics - Implementing best practices (#494) --- .../hadoop/crypto/key/kms/server/KMS.java | 161 +++++------------- .../collector/KMSMetricsCollector.java | 64 ++++++- 2 files changed, 99 insertions(+), 126 deletions(-) diff --git a/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java b/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java index 857ebb04aa..f90864907a 100644 --- a/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java +++ b/kms/src/main/java/org/apache/hadoop/crypto/key/kms/server/KMS.java @@ -36,6 +36,7 @@ import org.apache.ranger.kms.metrics.KMSMetricWrapper; import org.apache.ranger.kms.metrics.KMSMetrics; import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector; +import org.apache.ranger.kms.metrics.collector.KMSMetricsCollector.APIMetric; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,8 +63,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -100,10 +99,7 @@ public KMS() throws Exception { public Response createKey(Map jsonKey, @Context HttpServletRequest request) throws Exception { LOG.debug("==> createKey()"); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.KEY_CREATE_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.KEY_CREATE_COUNT, KMSMetrics.KMSMetric.KEY_CREATE_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); final UserGroupInformation user = HttpUserGroupInformation.get(); @@ -175,8 +171,6 @@ public Response createKey(Map jsonKey, @Context HttpServletRequest request) thro throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.KEY_CREATE_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== createKey()"); } } @@ -186,10 +180,7 @@ public Response createKey(Map jsonKey, @Context HttpServletRequest request) thro public Response deleteKey(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception { LOG.debug("==> deleteKey({})", name); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.DELETE_KEY_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.DELETE_KEY_COUNT, KMSMetrics.KMSMetric.DELETE_KEY_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -214,8 +205,6 @@ public Response deleteKey(@PathParam("name") final String name, @Context HttpSer throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.DELETE_KEY_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== deleteKey({})", name); } } @@ -227,10 +216,7 @@ public Response deleteKey(@PathParam("name") final String name, @Context HttpSer public Response rolloverKey(@PathParam("name") final String name, Map jsonMaterial, @Context HttpServletRequest request) throws Exception { LOG.debug("==> rolloverKey({})", name); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.ROLL_NEW_VERSION_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.ROLL_NEW_VERSION_COUNT, KMSMetrics.KMSMetric.ROLL_NEW_VERSION_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -273,8 +259,6 @@ public Response rolloverKey(@PathParam("name") final String name, Map jsonMateri throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.ROLL_NEW_VERSION_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== rolloverKey({})", name); } } @@ -284,10 +268,7 @@ public Response rolloverKey(@PathParam("name") final String name, Map jsonMateri public Response invalidateCache(@PathParam("name") final String name) throws Exception { LOG.debug("==> invalidateCache({})", name); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.INVALIDATE_CACHE_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.INVALIDATE_CACHE_COUNT, KMSMetrics.KMSMetric.INVALIDATE_CACHE_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); checkNotEmpty(name, "name"); @@ -312,8 +293,6 @@ public Response invalidateCache(@PathParam("name") final String name) throws Exc throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.INVALIDATE_CACHE_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== invalidateCache({})", name); } } @@ -324,10 +303,7 @@ public Response invalidateCache(@PathParam("name") final String name) throws Exc public Response getKeysMetadata(@QueryParam(KMSRESTConstants.KEY) List keyNamesList, @Context HttpServletRequest request) throws Exception { LOG.debug("==> getKeysMetadata()"); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.GET_KEYS_METADATA_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEYS_METADATA_COUNT, KMSMetrics.KMSMetric.GET_KEYS_METADATA_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); final UserGroupInformation user = HttpUserGroupInformation.get(); @@ -348,8 +324,6 @@ public Response getKeysMetadata(@QueryParam(KMSRESTConstants.KEY) List k throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_KEYS_METADATA_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== getKeysMetadata()"); } } @@ -360,10 +334,7 @@ public Response getKeysMetadata(@QueryParam(KMSRESTConstants.KEY) List k public Response getKeyNames(@Context HttpServletRequest request) throws Exception { LOG.debug("==> getKeyNames()"); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.GET_KEYS_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEYS_COUNT, KMSMetrics.KMSMetric.GET_KEYS_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -380,8 +351,6 @@ public Response getKeyNames(@Context HttpServletRequest request) throws Exceptio throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_KEYS_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== getKeyNames()"); } } @@ -408,10 +377,7 @@ public Response getKey(@PathParam("name") String name, @Context HttpServletReque public Response getMetadata(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception { LOG.debug("==> getMetadata({})", name); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.GET_METADATA_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_METADATA_COUNT, KMSMetrics.KMSMetric.GET_METADATA_ELAPSED_TIME)) { KMSWebApp.getAdminCallsMeter().mark(); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -431,8 +397,6 @@ public Response getMetadata(@PathParam("name") final String name, @Context HttpS throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_METADATA_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== getMetadata({})", name); } } @@ -443,10 +407,7 @@ public Response getMetadata(@PathParam("name") final String name, @Context HttpS public Response getCurrentVersion(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception { LOG.debug("==> getCurrentVersion({})", name); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.GET_CURRENT_KEY_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_CURRENT_KEY_COUNT, KMSMetrics.KMSMetric.GET_CURRENT_KEY_ELAPSED_TIME)) { KMSWebApp.getKeyCallsMeter().mark(); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -466,8 +427,6 @@ public Response getCurrentVersion(@PathParam("name") final String name, @Context throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_CURRENT_KEY_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== getCurrentVersion({})", name); } } @@ -478,10 +437,7 @@ public Response getCurrentVersion(@PathParam("name") final String name, @Context public Response getKeyVersion(@PathParam("versionName") final String versionName, @Context HttpServletRequest request) throws Exception { LOG.debug("==> getKeyVersion({})", versionName); - Stopwatch sw = Stopwatch.createStarted(); - - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.GET_KEY_VERSION_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEY_VERSION_COUNT, KMSMetrics.KMSMetric.GET_KEY_VERSION_ELAPSED_TIME)) { KMSWebApp.getKeyCallsMeter().mark(); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -504,8 +460,6 @@ public Response getKeyVersion(@PathParam("versionName") final String versionName throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_KEY_VERSION_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== getKeyVersion({})", versionName); } } @@ -516,39 +470,33 @@ public Response getKeyVersion(@PathParam("versionName") final String versionName public Response generateDataKey(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception { LOG.debug("==> generateDataKey(name={}", name); - Stopwatch sw = Stopwatch.createStarted(); - try { UserGroupInformation user = HttpUserGroupInformation.get(); checkNotEmpty(name, "name"); - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT); - - assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, request.getRemoteAddr()); - - EncryptedKeyVersion encryptedKeyVersion = user.doAs((PrivilegedExceptionAction) () -> provider.generateEncryptedKey(name)); - - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - - kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, "generateDataKey execution"); - - sw.reset(); - sw.start(); + EncryptedKeyVersion encryptedKeyVersion = null; + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT, KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME)) { + assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, request.getRemoteAddr()); - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT); - assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, name, request.getRemoteAddr()); + encryptedKeyVersion = user.doAs((PrivilegedExceptionAction) () -> provider.generateEncryptedKey(name)); + kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, "generateDataKey execution"); + } - KeyVersion retKeyVersion = user.doAs((PrivilegedExceptionAction) () -> { - KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(encryptedKeyVersion.getEncryptionKeyName(), encryptedKeyVersion.getEncryptionKeyVersionName(), - encryptedKeyVersion.getEncryptedKeyIv(), KeyProviderCryptoExtension.EEK, encryptedKeyVersion.getEncryptedKeyVersion().getMaterial()); + KeyVersion retKeyVersion = null; + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT, KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME)) { + assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, name, request.getRemoteAddr()); - return provider.decryptEncryptedKey(ekv); - }); + EncryptedKeyVersion finalEncryptedKeyVersion = encryptedKeyVersion; + retKeyVersion = user.doAs((PrivilegedExceptionAction) () -> { + KMSEncryptedKeyVersion ekv = new KMSEncryptedKeyVersion(finalEncryptedKeyVersion.getEncryptionKeyName(), finalEncryptedKeyVersion.getEncryptionKeyVersionName(), + finalEncryptedKeyVersion.getEncryptedKeyIv(), KeyProviderCryptoExtension.EEK, finalEncryptedKeyVersion.getEncryptedKeyVersion().getMaterial()); - kmsAudit.ok(user, KMSOp.DECRYPT_EEK, name, "generateDataKey execution"); + return provider.decryptEncryptedKey(ekv); + }); - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); + kmsAudit.ok(user, KMSOp.DECRYPT_EEK, name, "generateDataKey execution"); + } Map response = new HashMap<>(); @@ -573,9 +521,7 @@ public Response generateEncryptedKeys(@PathParam("name") final String name, @Que @DefaultValue("1") @QueryParam(KMSRESTConstants.EEK_NUM_KEYS) final int numKeys, @Context HttpServletRequest request) throws Exception { LOG.debug("==> generateEncryptedKeys(name={}, eekOp={}, numKeys={})", name, edekOp, numKeys); - Stopwatch sw = Stopwatch.createStarted(); - - try { + try (APIMetric apiElapsedMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT, KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME)) { UserGroupInformation user = HttpUserGroupInformation.get(); checkNotEmpty(name, "name"); @@ -585,13 +531,10 @@ public Response generateEncryptedKeys(@PathParam("name") final String name, @Que Object retJSON; if (edekOp.equals(KMSRESTConstants.EEK_GENERATE)) { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.EEK_GENERATE_COUNT); - - assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, request.getRemoteAddr()); - final List retEdeks = new LinkedList<>(); try { + assertAccess(Type.GENERATE_EEK, user, KMSOp.GENERATE_EEK, name, request.getRemoteAddr()); user.doAs((PrivilegedExceptionAction) () -> { for (int i = 0; i < numKeys; i++) { retEdeks.add(provider.generateEncryptedKey(name)); @@ -599,20 +542,18 @@ public Response generateEncryptedKeys(@PathParam("name") final String name, @Que return null; }); - } catch (Exception e) { - LOG.error("Exception in generateEncryptedKeys:", e); - throw new IOException(e); - } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.EEK_GENERATE_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - } + kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, ""); - kmsAudit.ok(user, KMSOp.GENERATE_EEK, name, ""); + retJSON = new ArrayList(); - retJSON = new ArrayList(); + for (EncryptedKeyVersion edek : retEdeks) { + ((ArrayList) retJSON).add(KMSUtil.toJSON(edek)); + } + } catch (Exception e) { + LOG.error("Exception in generateEncryptedKeys:", e); - for (EncryptedKeyVersion edek : retEdeks) { - ((ArrayList) retJSON).add(KMSUtil.toJSON(edek)); + throw new IOException(e); } } else { StringBuilder error = new StringBuilder("IllegalArgumentException Wrong "); @@ -633,7 +574,6 @@ public Response generateEncryptedKeys(@PathParam("name") final String name, @Que return Response.ok().type(MediaType.APPLICATION_JSON).entity(retJSON).build(); } catch (Exception e) { LOG.error("Exception in generateEncryptedKeys.", e); - throw e; } finally { LOG.debug("<== generateEncryptedKeys(name={}, eekOp={}, numKeys={})", name, edekOp, numKeys); @@ -650,8 +590,7 @@ public Response reencryptEncryptedKeys(@PathParam("name") final String name, fin final Stopwatch sw = Stopwatch.createStarted(); - try { - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_COUNT); + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_COUNT, KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_ELAPSED_TIME)) { KMSWebApp.getReencryptEEKBatchCallsMeter().mark(); checkNotEmpty(name, "name"); @@ -697,8 +636,6 @@ public Response reencryptEncryptedKeys(@PathParam("name") final String name, fin throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.REENCRYPT_EEK_BATCH_ELAPSED_TIME, sw.elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== reencryptEncryptedKeys(name={}, count={})", name, (jsonPayload != null ? jsonPayload.size() : 0)); } } @@ -710,10 +647,7 @@ public Response reencryptEncryptedKeys(@PathParam("name") final String name, fin public Response handleEncryptedKeyOp(@PathParam("versionName") final String versionName, @QueryParam(KMSRESTConstants.EEK_OP) String eekOp, Map jsonPayload, @Context HttpServletRequest request) throws Exception { LOG.debug("==> handleEncryptedKeyOp(versionName={}, eekOp={})", versionName, eekOp); - Optional oprCode = Optional.empty(); - final Stopwatch sw = Stopwatch.createStarted(); - - try { + try (APIMetric apiMetric = kmsMetricsCollector.captureElapsedTime()) { UserGroupInformation user = HttpUserGroupInformation.get(); checkNotEmpty(versionName, "versionName"); @@ -734,10 +668,8 @@ public Response handleEncryptedKeyOp(@PathParam("versionName") final String vers Object retJSON; if (eekOp.equals(KMSRESTConstants.EEK_DECRYPT)) { - oprCode = Optional.of(KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME); - KMSWebApp.getDecryptEEKCallsMeter().mark(); - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT); + apiMetric.setMetrics(KMSMetrics.KMSMetric.EEK_DECRYPT_COUNT, KMSMetrics.KMSMetric.EEK_DECRYPT_ELAPSED_TIME); assertAccess(Type.DECRYPT_EEK, user, KMSOp.DECRYPT_EEK, keyName, request.getRemoteAddr()); @@ -751,10 +683,8 @@ public Response handleEncryptedKeyOp(@PathParam("versionName") final String vers kmsAudit.ok(user, KMSOp.DECRYPT_EEK, keyName, ""); } else if (eekOp.equals(KMSRESTConstants.EEK_REENCRYPT)) { - oprCode = Optional.of(KMSMetrics.KMSMetric.EEK_REENCRYPT_ELAPSED_TIME); - KMSWebApp.getReencryptEEKCallsMeter().mark(); - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.EEK_REENCRYPT_COUNT); + apiMetric.setMetrics(KMSMetrics.KMSMetric.EEK_REENCRYPT_COUNT, KMSMetrics.KMSMetric.EEK_REENCRYPT_ELAPSED_TIME); assertAccess(Type.GENERATE_EEK, user, KMSOp.REENCRYPT_EEK, keyName); @@ -787,8 +717,6 @@ public Response handleEncryptedKeyOp(@PathParam("versionName") final String vers throw e; } finally { - oprCode.ifPresent(metric -> this.kmsMetricsCollector.updateMetric(metric, sw.stop().elapsed(TimeUnit.MILLISECONDS))); - LOG.debug("<== handleEncryptedKeyOp(versionName={}, eekOp={})", versionName, eekOp); } } @@ -799,11 +727,8 @@ public Response handleEncryptedKeyOp(@PathParam("versionName") final String vers public Response getKeyVersions(@PathParam("name") final String name, @Context HttpServletRequest request) throws Exception { LOG.debug("==> getKeyVersions({})", name); - Stopwatch sw = Stopwatch.createStarted(); - - try { + try (APIMetric apiMetric = kmsMetricsCollector.createAPIMetric(KMSMetrics.KMSMetric.GET_KEY_VERSIONS_COUNT, KMSMetrics.KMSMetric.GET_KEY_VERSIONS_ELAPSED_TIME)) { KMSWebApp.getKeyCallsMeter().mark(); - this.kmsMetricsCollector.incrementCounter(KMSMetrics.KMSMetric.GET_KEY_VERSIONS_COUNT); UserGroupInformation user = HttpUserGroupInformation.get(); @@ -822,8 +747,6 @@ public Response getKeyVersions(@PathParam("name") final String name, @Context Ht throw e; } finally { - this.kmsMetricsCollector.updateMetric(KMSMetrics.KMSMetric.GET_KEY_VERSIONS_ELAPSED_TIME, sw.stop().elapsed(TimeUnit.MILLISECONDS)); - LOG.debug("<== getKeyVersions({})", name); } } diff --git a/kms/src/main/java/org/apache/ranger/kms/metrics/collector/KMSMetricsCollector.java b/kms/src/main/java/org/apache/ranger/kms/metrics/collector/KMSMetricsCollector.java index 778cb1300d..aba4a7d475 100644 --- a/kms/src/main/java/org/apache/ranger/kms/metrics/collector/KMSMetricsCollector.java +++ b/kms/src/main/java/org/apache/ranger/kms/metrics/collector/KMSMetricsCollector.java @@ -18,6 +18,7 @@ package org.apache.ranger.kms.metrics.collector; +import org.apache.hadoop.thirdparty.com.google.common.base.Stopwatch; import org.apache.ranger.kms.metrics.KMSMetrics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,6 +26,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; public class KMSMetricsCollector { static final Logger logger = LoggerFactory.getLogger(KMSMetricsCollector.class); @@ -39,20 +41,20 @@ private KMSMetricsCollector(boolean isCollectionThreadSafe) { } public static KMSMetricsCollector getInstance(boolean isCollectionThreadSafe) { - KMSMetricsCollector me = kmsMetricsCollector; + KMSMetricsCollector metricsCollector = kmsMetricsCollector; - if (me == null) { + if (metricsCollector == null) { synchronized (KMSMetricsCollector.class) { - me = kmsMetricsCollector; + metricsCollector = kmsMetricsCollector; - if (me == null) { - me = new KMSMetricsCollector(isCollectionThreadSafe); - kmsMetricsCollector = me; + if (metricsCollector == null) { + metricsCollector = new KMSMetricsCollector(isCollectionThreadSafe); + kmsMetricsCollector = metricsCollector; } } } - return me; + return metricsCollector; } public boolean isCollectionThreadSafe() { @@ -82,4 +84,52 @@ public void updateMetric(KMSMetrics.KMSMetric metric, long val) { this.metrics.compute(metric, (k, v) -> null == v ? val : v + val); } } + + public APIMetric createAPIMetric(KMSMetrics.KMSMetric counter, KMSMetrics.KMSMetric elapsedTime) { + return new APIMetric(counter, elapsedTime); + } + + /** + * This method starts the Stopwatch to capture the elapsed time but KMSMetrics is not yet set. + * It may be used to address the use cases where exact metric name would be known after some processing, + * in such cases, Initially StopWatch can be started and specific metric can be set once known. + * + * If metric is not set, this StopWatch will be stopped and ignored. A warn log message will be logged. + * @return : APIMetric + */ + public APIMetric captureElapsedTime() { + return new APIMetric(); + } + + public class APIMetric implements AutoCloseable { + private KMSMetrics.KMSMetric counter; + private KMSMetrics.KMSMetric elapsedTime; + private final Stopwatch sw; + + private APIMetric(KMSMetrics.KMSMetric counter, KMSMetrics.KMSMetric elapsedTime) { + this(); + this.counter = counter; + this.elapsedTime = elapsedTime; + } + + private APIMetric() { + this.sw = Stopwatch.createStarted(); + } + + public void setMetrics(KMSMetrics.KMSMetric counter, KMSMetrics.KMSMetric elapsedTime) { + this.counter = counter; + this.elapsedTime = elapsedTime; + } + + @Override + public void close() { + if (null != counter && null != elapsedTime) { + incrementCounter(counter); + updateMetric(elapsedTime, sw.stop().elapsed(TimeUnit.MILLISECONDS)); + } else { + long elapsedTime = sw.stop().elapsed(TimeUnit.MILLISECONDS); + logger.warn("API metric started to capture elapsed time but Elapsed metric was not set. Elapsed time(in MS) {}", elapsedTime); + } + } + } }