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

sodonnell 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 0aabe8abb6 HDDS-7282. Add EstimatedKeyCount metrics for SCM DB (#3791)
0aabe8abb6 is described below

commit 0aabe8abb6db524dd59fe12b982149e622417fee
Author: Symious <[email protected]>
AuthorDate: Thu Oct 6 19:54:43 2022 +0800

    HDDS-7282. Add EstimatedKeyCount metrics for SCM DB (#3791)
---
 .../hdds/scm/metadata/SCMMetadataStoreImpl.java    |  51 ++++++---
 .../hdds/scm/metadata/SCMMetadataStoreMetrics.java | 116 +++++++++++++++++++++
 .../scm/metadata/TestSCMMetadataStoreImpl.java     |  77 ++++++++++++++
 3 files changed, 230 insertions(+), 14 deletions(-)

diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
index 3e14b0fa26..e71f6d7258 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreImpl.java
@@ -21,6 +21,8 @@ import java.io.File;
 import java.io.IOException;
 import java.math.BigInteger;
 import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import com.google.protobuf.ByteString;
 import org.apache.hadoop.hdds.conf.OzoneConfiguration;
@@ -100,6 +102,9 @@ public class SCMMetadataStoreImpl implements 
SCMMetadataStore {
   private DBStore store;
   private final OzoneConfiguration configuration;
 
+  private SCMMetadataStoreMetrics metrics;
+  private Map<String, Table<?, ?>> tableMap = new ConcurrentHashMap<>();
+
   /**
    * Constructs the metadata store and starts the DB Services.
    *
@@ -139,57 +144,62 @@ public class SCMMetadataStoreImpl implements 
SCMMetadataStore {
       deletedBlocksTable =
           DELETED_BLOCKS.getTable(this.store);
 
-      checkTableStatus(deletedBlocksTable,
-          DELETED_BLOCKS.getName());
+      checkAndPopulateTable(deletedBlocksTable, DELETED_BLOCKS.getName());
 
       validCertsTable = VALID_CERTS.getTable(store);
 
-      checkTableStatus(validCertsTable, VALID_CERTS.getName());
+      checkAndPopulateTable(validCertsTable, VALID_CERTS.getName());
 
       validSCMCertsTable = VALID_SCM_CERTS.getTable(store);
 
-      checkTableStatus(validSCMCertsTable, VALID_SCM_CERTS.getName());
+      checkAndPopulateTable(validSCMCertsTable, VALID_SCM_CERTS.getName());
 
       revokedCertsTable = REVOKED_CERTS.getTable(store);
 
-      checkTableStatus(revokedCertsTable, REVOKED_CERTS.getName());
+      checkAndPopulateTable(revokedCertsTable, REVOKED_CERTS.getName());
 
       revokedCertsV2Table = REVOKED_CERTS_V2.getTable(store);
 
-      checkTableStatus(revokedCertsV2Table, REVOKED_CERTS_V2.getName());
+      checkAndPopulateTable(revokedCertsV2Table, REVOKED_CERTS_V2.getName());
 
       pipelineTable = PIPELINES.getTable(store);
 
-      checkTableStatus(pipelineTable, PIPELINES.getName());
+      checkAndPopulateTable(pipelineTable, PIPELINES.getName());
 
       containerTable = CONTAINERS.getTable(store);
 
-      checkTableStatus(containerTable, CONTAINERS.getName());
+      checkAndPopulateTable(containerTable, CONTAINERS.getName());
 
       transactionInfoTable = TRANSACTIONINFO.getTable(store);
 
-      checkTableStatus(transactionInfoTable, TRANSACTIONINFO.getName());
+      checkAndPopulateTable(transactionInfoTable, TRANSACTIONINFO.getName());
 
       crlInfoTable = CRLS.getTable(store);
 
+      checkAndPopulateTable(crlInfoTable, CRLS.getName());
+
       crlSequenceIdTable = CRL_SEQUENCE_ID.getTable(store);
 
+      checkAndPopulateTable(crlInfoTable, CRL_SEQUENCE_ID.getName());
+
       sequenceIdTable = SEQUENCE_ID.getTable(store);
 
-      checkTableStatus(sequenceIdTable, SEQUENCE_ID.getName());
+      checkAndPopulateTable(sequenceIdTable, SEQUENCE_ID.getName());
 
       moveTable = MOVE.getTable(store);
 
-      checkTableStatus(moveTable, MOVE.getName());
+      checkAndPopulateTable(moveTable, MOVE.getName());
 
       metaTable = META.getTable(store);
 
-      checkTableStatus(moveTable, META.getName());
+      checkAndPopulateTable(moveTable, META.getName());
 
       statefulServiceConfigTable = STATEFUL_SERVICE_CONFIG.getTable(store);
 
-      checkTableStatus(statefulServiceConfigTable,
+      checkAndPopulateTable(statefulServiceConfigTable,
           STATEFUL_SERVICE_CONFIG.getName());
+
+      metrics = SCMMetadataStoreMetrics.create(this);
     }
   }
 
@@ -199,6 +209,10 @@ public class SCMMetadataStoreImpl implements 
SCMMetadataStore {
       store.close();
       store = null;
     }
+    if (metrics != null) {
+      metrics.unRegister();
+      metrics = null;
+    }
   }
 
   @Override
@@ -304,7 +318,8 @@ public class SCMMetadataStoreImpl implements 
SCMMetadataStore {
     return statefulServiceConfigTable;
   }
 
-  private void checkTableStatus(Table table, String name) throws IOException {
+  private void checkAndPopulateTable(Table table, String name)
+      throws IOException {
     String logMessage = "Unable to get a reference to %s table. Cannot " +
         "continue.";
     String errMsg = "Inconsistent DB state, Table - %s. Please check the" +
@@ -313,6 +328,14 @@ public class SCMMetadataStoreImpl implements 
SCMMetadataStore {
       LOG.error(String.format(logMessage, name));
       throw new IOException(String.format(errMsg, name));
     }
+    tableMap.put(name, table);
+  }
+
+  Map<String, Table<?, ?>> getTableMap() {
+    return tableMap;
   }
 
+  SCMMetadataStoreMetrics getMetrics() {
+    return metrics;
+  }
 }
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreMetrics.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreMetrics.java
new file mode 100644
index 0000000000..64be4dab73
--- /dev/null
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/metadata/SCMMetadataStoreMetrics.java
@@ -0,0 +1,116 @@
+/*
+ * 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.hdds.scm.metadata;
+
+import com.google.gson.Gson;
+import org.apache.commons.text.WordUtils;
+import org.apache.hadoop.metrics2.MetricsCollector;
+import org.apache.hadoop.metrics2.MetricsInfo;
+import org.apache.hadoop.metrics2.MetricsRecordBuilder;
+import org.apache.hadoop.metrics2.MetricsSource;
+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.ozone.OzoneConsts;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static org.apache.hadoop.metrics2.lib.Interns.info;
+
+/**
+ * Class contains metrics related to SCM Metadata Store.
+ */
+@Metrics(about = "SCM Metadata Store Metrics", context = OzoneConsts.OZONE)
+public final class SCMMetadataStoreMetrics implements MetricsSource {
+
+  private static final Logger LOG =
+      LoggerFactory.getLogger(SCMMetadataStoreMetrics.class);
+
+  public static final String METRICS_SOURCE_NAME =
+      SCMMetadataStoreMetrics.class.getSimpleName();
+
+  private static final MetricsInfo ESTIMATED_KEY_COUNT = info(
+      "EstimatedKeyCount",
+      "Tracked estimated key count of all column families");
+
+  private MetricsRegistry registry;
+  private static SCMMetadataStoreMetrics instance;
+
+  private SCMMetadataStoreImpl scmMetadataStore;
+
+  private Map<String, MetricsInfo> columnFamilyMetrics;
+
+  public SCMMetadataStoreMetrics(SCMMetadataStoreImpl scmMetadataStoreImpl) {
+    this.registry = new MetricsRegistry(METRICS_SOURCE_NAME);
+    this.scmMetadataStore = scmMetadataStoreImpl;
+
+    columnFamilyMetrics = scmMetadataStoreImpl.getTableMap().entrySet()
+        .stream().collect(
+        Collectors.toMap(Map.Entry::getKey, e -> getMetricsInfo(e.getKey())));
+  }
+
+  public static synchronized SCMMetadataStoreMetrics 
create(SCMMetadataStoreImpl
+      scmMetadataStore) {
+    if (instance != null) {
+      return instance;
+    }
+    instance = DefaultMetricsSystem.instance().register(METRICS_SOURCE_NAME,
+        "SCM Metadata store related metrics",
+        new SCMMetadataStoreMetrics(scmMetadataStore));
+    return instance;
+  }
+
+  @Override
+  public void getMetrics(MetricsCollector collector, boolean all) {
+    MetricsRecordBuilder builder = collector.addRecord(METRICS_SOURCE_NAME);
+
+    Map<String, Long> keyCountMap = new HashMap<>();
+    for (Map.Entry<String, MetricsInfo> entry: columnFamilyMetrics.entrySet()) 
{
+      long count = 0L;
+      try {
+        count = scmMetadataStore.getTableMap().get(entry.getKey())
+            .getEstimatedKeyCount();
+      } catch (IOException e) {
+        LOG.error("Can not get estimated key count for table {}",
+            entry.getKey(), e);
+      }
+      builder.addGauge(entry.getValue(), count);
+      keyCountMap.put(entry.getKey(), count);
+    }
+
+    Gson gson = new Gson();
+    builder.tag(ESTIMATED_KEY_COUNT, gson.toJson(keyCountMap));
+  }
+
+  public static synchronized void unRegister() {
+    instance = null;
+    DefaultMetricsSystem.instance().unregisterSource(METRICS_SOURCE_NAME);
+  }
+
+  private MetricsInfo getMetricsInfo(String tableName) {
+    String name = WordUtils.capitalize(tableName);
+    String metric = name + "EstimatedKeyCount";
+    String description = "Estimated key count in table of " + name;
+    return info(metric, description);
+  }
+}
diff --git 
a/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/metadata/TestSCMMetadataStoreImpl.java
 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/metadata/TestSCMMetadataStoreImpl.java
new file mode 100644
index 0000000000..0c96747d74
--- /dev/null
+++ 
b/hadoop-hdds/server-scm/src/test/java/org/apache/hadoop/hdds/scm/metadata/TestSCMMetadataStoreImpl.java
@@ -0,0 +1,77 @@
+/**
+ * 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.hdds.scm.metadata;
+
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.ozone.container.common.SCMTestUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+import static org.apache.hadoop.test.MetricsAsserts.getLongGauge;
+import static org.apache.hadoop.test.MetricsAsserts.getMetrics;
+import static org.apache.hadoop.test.MetricsAsserts.getStringMetric;
+
+
+/**
+ * Testing of SCMMetadataStoreImpl.
+ */
+public class TestSCMMetadataStoreImpl {
+  private OzoneConfiguration conf;
+  private SCMMetadataStore scmMetadataStore;
+
+  @BeforeEach
+  public void setUp(@TempDir Path tempDir) throws Exception {
+    conf = SCMTestUtils.getConf();
+
+    scmMetadataStore = new SCMMetadataStoreImpl(conf);
+    scmMetadataStore.start(conf);
+  }
+
+  @Test
+  public void testEstimatedKeyCount() {
+    Assertions.assertTrue(getString("EstimatedKeyCount")
+        .contains("\"sequenceId\":0"));
+    Assertions.assertEquals(0, getGauge("SequenceIdEstimatedKeyCount"));
+
+    try {
+      scmMetadataStore.getSequenceIdTable().put("TestKey", 1L);
+    } catch (IOException e) {
+      // Ignore
+    }
+
+    Assertions.assertTrue(getString("EstimatedKeyCount")
+        .contains("\"sequenceId\":1"));
+    Assertions.assertEquals(1, getGauge("SequenceIdEstimatedKeyCount"));
+  }
+
+  private long getGauge(String metricName) {
+    return getLongGauge(metricName,
+        getMetrics(SCMMetadataStoreMetrics.METRICS_SOURCE_NAME));
+  }
+
+  private String getString(String metricName) {
+    return getStringMetric(metricName,
+        getMetrics(SCMMetadataStoreMetrics.METRICS_SOURCE_NAME));
+  }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to