Repaired Metrics name collision between Privacy and RocksDB (#187)

It was identified that when both KV_ROCKSDB metrics and Privacy were enabled,
that Besu failed to start due to a naming collision in Metrics Collators - this was ultimately due to Besu having 2 keyvalue stores - one for public state, and another for private state - and _both_ using the same metrics.

To overcome this issue, the metrics used in the private kv store are prefixed with the word "private".

Signed-off-by: Trent Mohay <trent.mohay@consensys.net>
pull/182/head
Trent Mohay 5 years ago committed by GitHub
parent 3c1768eef7
commit 3d867532de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java
  2. 4
      besu/src/test/java/org/hyperledger/besu/PrivacyTest.java
  3. 4
      besu/src/test/java/org/hyperledger/besu/RunnerTest.java
  4. 4
      ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java
  5. 4
      ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java
  6. 12
      metrics/core/src/main/java/org/hyperledger/besu/metrics/BesuMetricCategory.java
  7. 10
      metrics/rocksdb/src/main/java/org/hyperledger/besu/metrics/rocksdb/RocksDBStats.java
  8. 5
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValuePrivacyStorageFactory.java
  9. 18
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactory.java
  10. 96
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBMetrics.java
  11. 135
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBMetricsFactory.java
  12. 8
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBPlugin.java
  13. 6
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBColumnarKeyValueStorage.java
  14. 7
      plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBKeyValueStorage.java
  15. 33
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBKeyValueStorageFactoryTest.java
  16. 2
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/RocksDBMetricsTest.java
  17. 8
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBKeyValueStorageTest.java
  18. 4
      plugins/rocksdb/src/test/java/org/hyperledger/besu/plugin/services/storage/rocksdb/unsegmented/RocksDBColumnarKeyValueStorageTest.java

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValuePrivacyStorageFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValuePrivacyStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration;
import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
@ -220,7 +221,8 @@ public class PrivacyNode implements AutoCloseable {
MAX_BACKGROUND_COMPACTIONS, MAX_BACKGROUND_COMPACTIONS,
BACKGROUND_THREAD_COUNT, BACKGROUND_THREAD_COUNT,
CACHE_CAPACITY), CACHE_CAPACITY),
Arrays.asList(KeyValueSegmentIdentifier.values()))) Arrays.asList(KeyValueSegmentIdentifier.values()),
RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS))
.withCommonConfiguration(new BesuConfigurationImpl(dataLocation, dbLocation)) .withCommonConfiguration(new BesuConfigurationImpl(dataLocation, dbLocation))
.withMetricsSystem(new NoOpMetricsSystem()) .withMetricsSystem(new NoOpMetricsSystem())
.build(); .build();

@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValuePrivacyStorageFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValuePrivacyStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration;
import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.testutil.TestClock; import org.hyperledger.besu.testutil.TestClock;
@ -105,7 +106,8 @@ public class PrivacyTest {
MAX_BACKGROUND_COMPACTIONS, MAX_BACKGROUND_COMPACTIONS,
BACKGROUND_THREAD_COUNT, BACKGROUND_THREAD_COUNT,
CACHE_CAPACITY), CACHE_CAPACITY),
Arrays.asList(KeyValueSegmentIdentifier.values()))) Arrays.asList(KeyValueSegmentIdentifier.values()),
RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS))
.withCommonConfiguration(new BesuConfigurationImpl(dataDir, dbDir)) .withCommonConfiguration(new BesuConfigurationImpl(dataDir, dbDir))
.withMetricsSystem(new NoOpMetricsSystem()) .withMetricsSystem(new NoOpMetricsSystem())
.build(); .build();

@ -52,6 +52,7 @@ import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration;
import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.testutil.TestClock; import org.hyperledger.besu.testutil.TestClock;
@ -369,7 +370,8 @@ public final class RunnerTest {
MAX_BACKGROUND_COMPACTIONS, MAX_BACKGROUND_COMPACTIONS,
BACKGROUND_THREAD_COUNT, BACKGROUND_THREAD_COUNT,
CACHE_CAPACITY), CACHE_CAPACITY),
Arrays.asList(KeyValueSegmentIdentifier.values()))) Arrays.asList(KeyValueSegmentIdentifier.values()),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS))
.withCommonConfiguration(new BesuConfigurationImpl(dataDir, dbDir)) .withCommonConfiguration(new BesuConfigurationImpl(dataDir, dbDir))
.withMetricsSystem(new NoOpMetricsSystem()) .withMetricsSystem(new NoOpMetricsSystem())
.build(); .build();

@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.MessageFrameTestFixture;
import org.hyperledger.besu.ethereum.vm.MessageFrame; import org.hyperledger.besu.ethereum.vm.MessageFrame;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder;
import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage;
import org.hyperledger.besu.util.uint.UInt256; import org.hyperledger.besu.util.uint.UInt256;
@ -56,7 +57,8 @@ public class OperationBenchmarkHelper {
final KeyValueStorage keyValueStorage = final KeyValueStorage keyValueStorage =
new RocksDBKeyValueStorage( new RocksDBKeyValueStorage(
new RocksDBConfigurationBuilder().databaseDir(storageDirectory).build(), new RocksDBConfigurationBuilder().databaseDir(storageDirectory).build(),
new NoOpMetricsSystem()); new NoOpMetricsSystem(),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
final ExecutionContextTestFixture executionContext = final ExecutionContextTestFixture executionContext =
ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build(); ExecutionContextTestFixture.builder().keyValueStorage(keyValueStorage).build();

@ -40,6 +40,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration;
import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.tasks.CachingTaskCollection; import org.hyperledger.besu.services.tasks.CachingTaskCollection;
@ -168,7 +169,8 @@ public class WorldStateDownloaderBenchmark {
DEFAULT_MAX_BACKGROUND_COMPACTIONS, DEFAULT_MAX_BACKGROUND_COMPACTIONS,
DEFAULT_BACKGROUND_THREAD_COUNT, DEFAULT_BACKGROUND_THREAD_COUNT,
DEFAULT_CACHE_CAPACITY), DEFAULT_CACHE_CAPACITY),
Arrays.asList(KeyValueSegmentIdentifier.values()))) Arrays.asList(KeyValueSegmentIdentifier.values()),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS))
.withCommonConfiguration(new BesuConfigurationImpl(dataDir, dbDir)) .withCommonConfiguration(new BesuConfigurationImpl(dataDir, dbDir))
.withMetricsSystem(new NoOpMetricsSystem()) .withMetricsSystem(new NoOpMetricsSystem())
.build(); .build();

@ -30,7 +30,9 @@ public enum BesuMetricCategory implements MetricCategory {
PEERS("peers"), PEERS("peers"),
PERMISSIONING("permissioning"), PERMISSIONING("permissioning"),
KVSTORE_ROCKSDB("rocksdb"), KVSTORE_ROCKSDB("rocksdb"),
KVSTORE_PRIVATE_ROCKSDB("private_rocksdb"),
KVSTORE_ROCKSDB_STATS("rocksdb", false), KVSTORE_ROCKSDB_STATS("rocksdb", false),
KVSTORE_PRIVATE_ROCKSDB_STATS("private_rocksdb", false),
PRUNER("pruner"), PRUNER("pruner"),
RPC("rpc"), RPC("rpc"),
SYNCHRONIZER("synchronizer"), SYNCHRONIZER("synchronizer"),
@ -40,9 +42,15 @@ public enum BesuMetricCategory implements MetricCategory {
public static final Set<MetricCategory> DEFAULT_METRIC_CATEGORIES; public static final Set<MetricCategory> DEFAULT_METRIC_CATEGORIES;
static { static {
// Why not ROCKSDB and KVSTORE_ROCKSDB_STATS? They hurt performance under load. // Why not KVSTORE_ROCKSDB and KVSTORE_ROCKSDB_STATS, KVSTORE_PRIVATE_ROCKSDB_STATS,
// KVSTORE_PRIVATE_ROCKSDB_STATS? They hurt performance under load.
final EnumSet<BesuMetricCategory> besuCategories = final EnumSet<BesuMetricCategory> besuCategories =
EnumSet.complementOf(EnumSet.of(KVSTORE_ROCKSDB, KVSTORE_ROCKSDB_STATS)); EnumSet.complementOf(
EnumSet.of(
KVSTORE_ROCKSDB,
KVSTORE_ROCKSDB_STATS,
KVSTORE_PRIVATE_ROCKSDB,
KVSTORE_PRIVATE_ROCKSDB_STATS));
DEFAULT_METRIC_CATEGORIES = DEFAULT_METRIC_CATEGORIES =
ImmutableSet.<MetricCategory>builder() ImmutableSet.<MetricCategory>builder()

@ -17,6 +17,7 @@ package org.hyperledger.besu.metrics.rocksdb;
import static org.hyperledger.besu.metrics.BesuMetricCategory.KVSTORE_ROCKSDB_STATS; import static org.hyperledger.besu.metrics.BesuMetricCategory.KVSTORE_ROCKSDB_STATS;
import org.hyperledger.besu.metrics.prometheus.PrometheusMetricsSystem; import org.hyperledger.besu.metrics.prometheus.PrometheusMetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -169,19 +170,20 @@ public class RocksDBStats {
}; };
public static void registerRocksDBMetrics( public static void registerRocksDBMetrics(
final Statistics stats, final PrometheusMetricsSystem metricsSystem) { final Statistics stats,
final PrometheusMetricsSystem metricsSystem,
final MetricCategory category) {
for (final TickerType ticker : TICKERS) { for (final TickerType ticker : TICKERS) {
final String promCounterName = ticker.name().toLowerCase(); final String promCounterName = ticker.name().toLowerCase();
metricsSystem.createLongGauge( metricsSystem.createLongGauge(
KVSTORE_ROCKSDB_STATS, category,
promCounterName, promCounterName,
"RocksDB reported statistics for " + ticker.name(), "RocksDB reported statistics for " + ticker.name(),
() -> stats.getTickerCount(ticker)); () -> stats.getTickerCount(ticker));
} }
for (final HistogramType histogram : HISTOGRAMS) { for (final HistogramType histogram : HISTOGRAMS) {
metricsSystem.addCollector(KVSTORE_ROCKSDB_STATS, histogramToCollector(stats, histogram)); metricsSystem.addCollector(category, histogramToCollector(stats, histogram));
} }
} }

@ -30,8 +30,9 @@ public class RocksDBKeyValuePrivacyStorageFactory extends RocksDBKeyValueStorage
public RocksDBKeyValuePrivacyStorageFactory( public RocksDBKeyValuePrivacyStorageFactory(
final Supplier<RocksDBFactoryConfiguration> configuration, final Supplier<RocksDBFactoryConfiguration> configuration,
final List<SegmentIdentifier> segments) { final List<SegmentIdentifier> segments,
super(configuration, segments); final RocksDBMetricsFactory rocksDBMetricsFactory) {
super(configuration, segments, rocksDBMetricsFactory);
} }
@Override @Override

@ -47,6 +47,7 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
private final int DEFAULT_VERSION; private final int DEFAULT_VERSION;
private static final Set<Integer> SUPPORTED_VERSIONS = Set.of(0, 1); private static final Set<Integer> SUPPORTED_VERSIONS = Set.of(0, 1);
private static final String NAME = "rocksdb"; private static final String NAME = "rocksdb";
private final RocksDBMetricsFactory rocksDBMetricsFactory;
private Integer databaseVersion; private Integer databaseVersion;
private Boolean isSegmentIsolationSupported; private Boolean isSegmentIsolationSupported;
@ -60,20 +61,24 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
RocksDBKeyValueStorageFactory( RocksDBKeyValueStorageFactory(
final Supplier<RocksDBFactoryConfiguration> configuration, final Supplier<RocksDBFactoryConfiguration> configuration,
final List<SegmentIdentifier> segments, final List<SegmentIdentifier> segments,
final int DEFAULT_VERSION) { final int DEFAULT_VERSION,
final RocksDBMetricsFactory rocksDBMetricsFactory) {
this.configuration = configuration; this.configuration = configuration;
this.segments = segments; this.segments = segments;
this.DEFAULT_VERSION = DEFAULT_VERSION; this.DEFAULT_VERSION = DEFAULT_VERSION;
this.rocksDBMetricsFactory = rocksDBMetricsFactory;
} }
public RocksDBKeyValueStorageFactory( public RocksDBKeyValueStorageFactory(
final Supplier<RocksDBFactoryConfiguration> configuration, final Supplier<RocksDBFactoryConfiguration> configuration,
final List<SegmentIdentifier> segments) { final List<SegmentIdentifier> segments,
final RocksDBMetricsFactory rocksDBMetricsFactory) {
this( this(
configuration, configuration,
segments, segments,
/** Source of truth for the default database version. */ /** Source of truth for the default database version. */
1); 1,
rocksDBMetricsFactory);
} }
@Override @Override
@ -100,7 +105,9 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
{ {
segmentedStorage = null; segmentedStorage = null;
if (unsegmentedStorage == null) { if (unsegmentedStorage == null) {
unsegmentedStorage = new RocksDBKeyValueStorage(rocksDBConfiguration, metricsSystem); unsegmentedStorage =
new RocksDBKeyValueStorage(
rocksDBConfiguration, metricsSystem, rocksDBMetricsFactory);
} }
return unsegmentedStorage; return unsegmentedStorage;
} }
@ -109,7 +116,8 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
unsegmentedStorage = null; unsegmentedStorage = null;
if (segmentedStorage == null) { if (segmentedStorage == null) {
segmentedStorage = segmentedStorage =
new RocksDBColumnarKeyValueStorage(rocksDBConfiguration, segments, metricsSystem); new RocksDBColumnarKeyValueStorage(
rocksDBConfiguration, segments, metricsSystem, rocksDBMetricsFactory);
} }
return new SegmentedKeyValueStorageAdapter<>(segment, segmentedStorage); return new SegmentedKeyValueStorageAdapter<>(segment, segmentedStorage);
} }

@ -14,31 +14,18 @@
*/ */
package org.hyperledger.besu.plugin.services.storage.rocksdb; package org.hyperledger.besu.plugin.services.storage.rocksdb;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.prometheus.PrometheusMetricsSystem;
import org.hyperledger.besu.metrics.rocksdb.RocksDBStats;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter; import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.OperationTimer; import org.hyperledger.besu.plugin.services.metrics.OperationTimer;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.rocksdb.RocksDBException;
import org.rocksdb.Statistics;
import org.rocksdb.TransactionDB;
public class RocksDBMetrics { public class RocksDBMetrics {
private static final Logger LOG = LogManager.getLogger();
private final OperationTimer readLatency; private final OperationTimer readLatency;
private final OperationTimer removeLatency; private final OperationTimer removeLatency;
private final OperationTimer writeLatency; private final OperationTimer writeLatency;
private final OperationTimer commitLatency; private final OperationTimer commitLatency;
private final Counter rollbackCount; private final Counter rollbackCount;
private RocksDBMetrics( public RocksDBMetrics(
final OperationTimer readLatency, final OperationTimer readLatency,
final OperationTimer removeLatency, final OperationTimer removeLatency,
final OperationTimer writeLatency, final OperationTimer writeLatency,
@ -51,87 +38,6 @@ public class RocksDBMetrics {
this.rollbackCount = rollbackCount; this.rollbackCount = rollbackCount;
} }
public static RocksDBMetrics of(
final MetricsSystem metricsSystem,
final RocksDBConfiguration rocksDbConfiguration,
final TransactionDB db,
final Statistics stats) {
final OperationTimer readLatency =
metricsSystem
.createLabelledTimer(
BesuMetricCategory.KVSTORE_ROCKSDB,
"read_latency_seconds",
"Latency for read from RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
final OperationTimer removeLatency =
metricsSystem
.createLabelledTimer(
BesuMetricCategory.KVSTORE_ROCKSDB,
"remove_latency_seconds",
"Latency of remove requests from RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
final OperationTimer writeLatency =
metricsSystem
.createLabelledTimer(
BesuMetricCategory.KVSTORE_ROCKSDB,
"write_latency_seconds",
"Latency for write to RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
final OperationTimer commitLatency =
metricsSystem
.createLabelledTimer(
BesuMetricCategory.KVSTORE_ROCKSDB,
"commit_latency_seconds",
"Latency for commits to RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
if (metricsSystem instanceof PrometheusMetricsSystem) {
RocksDBStats.registerRocksDBMetrics(stats, (PrometheusMetricsSystem) metricsSystem);
}
metricsSystem.createLongGauge(
BesuMetricCategory.KVSTORE_ROCKSDB,
"rocks_db_table_readers_memory_bytes",
"Estimated memory used for RocksDB index and filter blocks in bytes",
() -> {
try {
return db.getLongProperty("rocksdb.estimate-table-readers-mem");
} catch (final RocksDBException e) {
LOG.debug("Failed to get RocksDB metric", e);
return 0L;
}
});
metricsSystem.createLongGauge(
BesuMetricCategory.KVSTORE_ROCKSDB,
"rocks_db_files_size_bytes",
"Estimated database size in bytes",
() -> {
try {
return db.getLongProperty("rocksdb.live-sst-files-size");
} catch (final RocksDBException e) {
LOG.debug("Failed to get RocksDB metric", e);
return 0L;
}
});
final Counter rollbackCount =
metricsSystem
.createLabelledCounter(
BesuMetricCategory.KVSTORE_ROCKSDB,
"rollback_count",
"Number of RocksDB transactions rolled back.",
"database")
.labels(rocksDbConfiguration.getLabel());
return new RocksDBMetrics(
readLatency, removeLatency, writeLatency, commitLatency, rollbackCount);
}
public OperationTimer getReadLatency() { public OperationTimer getReadLatency() {
return readLatency; return readLatency;
} }

@ -0,0 +1,135 @@
/*
* Copyright ConsenSys AG.
*
* Licensed 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.plugin.services.storage.rocksdb;
import org.hyperledger.besu.metrics.BesuMetricCategory;
import org.hyperledger.besu.metrics.prometheus.PrometheusMetricsSystem;
import org.hyperledger.besu.metrics.rocksdb.RocksDBStats;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
import org.hyperledger.besu.plugin.services.metrics.OperationTimer;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.rocksdb.RocksDBException;
import org.rocksdb.Statistics;
import org.rocksdb.TransactionDB;
public class RocksDBMetricsFactory {
public static final RocksDBMetricsFactory PUBLIC_ROCKS_DB_METRICS =
new RocksDBMetricsFactory(
BesuMetricCategory.KVSTORE_ROCKSDB, BesuMetricCategory.KVSTORE_ROCKSDB_STATS);
public static final RocksDBMetricsFactory PRIVATE_ROCKS_DB_METRICS =
new RocksDBMetricsFactory(
BesuMetricCategory.KVSTORE_PRIVATE_ROCKSDB,
BesuMetricCategory.KVSTORE_PRIVATE_ROCKSDB_STATS);
private static final Logger LOG = LogManager.getLogger();
private final MetricCategory rocksDbMetricCategory;
private final MetricCategory statsDbMetricCategory;
public RocksDBMetricsFactory(
final MetricCategory rocksDbMetricCategory, final MetricCategory statsDbMetricCategory) {
this.rocksDbMetricCategory = rocksDbMetricCategory;
this.statsDbMetricCategory = statsDbMetricCategory;
}
public RocksDBMetrics create(
final MetricsSystem metricsSystem,
final RocksDBConfiguration rocksDbConfiguration,
final TransactionDB db,
final Statistics stats) {
final OperationTimer readLatency =
metricsSystem
.createLabelledTimer(
rocksDbMetricCategory,
"read_latency_seconds",
"Latency for read from RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
final OperationTimer removeLatency =
metricsSystem
.createLabelledTimer(
rocksDbMetricCategory,
"remove_latency_seconds",
"Latency of remove requests from RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
final OperationTimer writeLatency =
metricsSystem
.createLabelledTimer(
rocksDbMetricCategory,
"write_latency_seconds",
"Latency for write to RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
final OperationTimer commitLatency =
metricsSystem
.createLabelledTimer(
rocksDbMetricCategory,
"commit_latency_seconds",
"Latency for commits to RocksDB.",
"database")
.labels(rocksDbConfiguration.getLabel());
if (metricsSystem instanceof PrometheusMetricsSystem) {
RocksDBStats.registerRocksDBMetrics(
stats, (PrometheusMetricsSystem) metricsSystem, statsDbMetricCategory);
}
metricsSystem.createLongGauge(
rocksDbMetricCategory,
"rocks_db_table_readers_memory_bytes",
"Estimated memory used for RocksDB index and filter blocks in bytes",
() -> {
try {
return db.getLongProperty("rocksdb.estimate-table-readers-mem");
} catch (final RocksDBException e) {
LOG.debug("Failed to get RocksDB metric", e);
return 0L;
}
});
metricsSystem.createLongGauge(
rocksDbMetricCategory,
"rocks_db_files_size_bytes",
"Estimated database size in bytes",
() -> {
try {
return db.getLongProperty("rocksdb.live-sst-files-size");
} catch (final RocksDBException e) {
LOG.debug("Failed to get RocksDB metric", e);
return 0L;
}
});
final Counter rollbackCount =
metricsSystem
.createLabelledCounter(
rocksDbMetricCategory,
"rollback_count",
"Number of RocksDB transactions rolled back.",
"database")
.labels(rocksDbConfiguration.getLabel());
return new RocksDBMetrics(
readLatency, removeLatency, writeLatency, commitLatency, rollbackCount);
}
}

@ -100,8 +100,12 @@ public class RocksDBPlugin implements BesuPlugin {
final Supplier<RocksDBFactoryConfiguration> configuration = final Supplier<RocksDBFactoryConfiguration> configuration =
Suppliers.memoize(options::toDomainObject); Suppliers.memoize(options::toDomainObject);
factory = new RocksDBKeyValueStorageFactory(configuration, segments); factory =
privacyFactory = new RocksDBKeyValuePrivacyStorageFactory(configuration, segments); new RocksDBKeyValueStorageFactory(
configuration, segments, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
privacyFactory =
new RocksDBKeyValuePrivacyStorageFactory(
configuration, segments, RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS);
service.registerKeyValueStorage(factory); service.registerKeyValueStorage(factory);
service.registerKeyValueStorage(privacyFactory); service.registerKeyValueStorage(privacyFactory);

@ -21,6 +21,7 @@ import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.metrics.OperationTimer; import org.hyperledger.besu.plugin.services.metrics.OperationTimer;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetrics; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetrics;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbUtil; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbUtil;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration;
import org.hyperledger.besu.services.kvstore.SegmentedKeyValueStorage; import org.hyperledger.besu.services.kvstore.SegmentedKeyValueStorage;
@ -76,7 +77,8 @@ public class RocksDBColumnarKeyValueStorage
public RocksDBColumnarKeyValueStorage( public RocksDBColumnarKeyValueStorage(
final RocksDBConfiguration configuration, final RocksDBConfiguration configuration,
final List<SegmentIdentifier> segments, final List<SegmentIdentifier> segments,
final MetricsSystem metricsSystem) final MetricsSystem metricsSystem,
final RocksDBMetricsFactory rocksDBMetricsFactory)
throws StorageException { throws StorageException {
try { try {
@ -110,7 +112,7 @@ public class RocksDBColumnarKeyValueStorage
configuration.getDatabaseDir().toString(), configuration.getDatabaseDir().toString(),
columnDescriptors, columnDescriptors,
columnHandles); columnHandles);
metrics = RocksDBMetrics.of(metricsSystem, configuration, db, stats); metrics = rocksDBMetricsFactory.create(metricsSystem, configuration, db, stats);
final Map<BytesValue, String> segmentsById = final Map<BytesValue, String> segmentsById =
segments.stream() segments.stream()
.collect( .collect(

@ -20,6 +20,7 @@ import org.hyperledger.besu.plugin.services.metrics.OperationTimer;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction; import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetrics; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetrics;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbUtil; import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDbUtil;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration;
import org.hyperledger.besu.services.kvstore.KeyValueStorageTransactionTransitionValidatorDecorator; import org.hyperledger.besu.services.kvstore.KeyValueStorageTransactionTransitionValidatorDecorator;
@ -57,7 +58,9 @@ public class RocksDBKeyValueStorage implements KeyValueStorage {
private final RocksDBMetrics rocksDBMetrics; private final RocksDBMetrics rocksDBMetrics;
public RocksDBKeyValueStorage( public RocksDBKeyValueStorage(
final RocksDBConfiguration configuration, final MetricsSystem metricsSystem) { final RocksDBConfiguration configuration,
final MetricsSystem metricsSystem,
final RocksDBMetricsFactory rocksDBMetricsFactory) {
try { try {
final Statistics stats = new Statistics(); final Statistics stats = new Statistics();
@ -72,7 +75,7 @@ public class RocksDBKeyValueStorage implements KeyValueStorage {
txOptions = new TransactionDBOptions(); txOptions = new TransactionDBOptions();
db = TransactionDB.open(options, txOptions, configuration.getDatabaseDir().toString()); db = TransactionDB.open(options, txOptions, configuration.getDatabaseDir().toString());
rocksDBMetrics = RocksDBMetrics.of(metricsSystem, configuration, db, stats); rocksDBMetrics = rocksDBMetricsFactory.create(metricsSystem, configuration, db, stats);
} catch (final RocksDBException e) { } catch (final RocksDBException e) {
throw new StorageException(e); throw new StorageException(e);
} }

@ -60,7 +60,8 @@ public class RocksDBKeyValueStorageFactoryTest {
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir); when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
final RocksDBKeyValueStorageFactory storageFactory = final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments); new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration, segments, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
// Side effect is creation of the Metadata version file // Side effect is creation of the Metadata version file
storageFactory.create(segment, commonConfiguration, metricsSystem); storageFactory.create(segment, commonConfiguration, metricsSystem);
@ -83,7 +84,8 @@ public class RocksDBKeyValueStorageFactoryTest {
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir); when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
final RocksDBKeyValueStorageFactory storageFactory = final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments); new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration, segments, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
storageFactory.create(segment, commonConfiguration, metricsSystem); storageFactory.create(segment, commonConfiguration, metricsSystem);
@ -100,7 +102,8 @@ public class RocksDBKeyValueStorageFactoryTest {
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir); when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
final RocksDBKeyValueStorageFactory storageFactory = final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments); new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration, segments, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
storageFactory.create(segment, commonConfiguration, metricsSystem); storageFactory.create(segment, commonConfiguration, metricsSystem);
@ -119,13 +122,15 @@ public class RocksDBKeyValueStorageFactoryTest {
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir); when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
final RocksDBKeyValueStorageFactory storageFactory = final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments, 1); new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration, segments, 1, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
storageFactory.create(segment, commonConfiguration, metricsSystem); storageFactory.create(segment, commonConfiguration, metricsSystem);
storageFactory.close(); storageFactory.close();
final RocksDBKeyValueStorageFactory rolledbackStorageFactory = final RocksDBKeyValueStorageFactory rolledbackStorageFactory =
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments, 0); new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration, segments, 0, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
rolledbackStorageFactory.create(segment, commonConfiguration, metricsSystem); rolledbackStorageFactory.create(segment, commonConfiguration, metricsSystem);
} }
@ -141,7 +146,10 @@ public class RocksDBKeyValueStorageFactoryTest {
new DatabaseMetadata(-1).writeToDirectory(tempDatabaseDir); new DatabaseMetadata(-1).writeToDirectory(tempDatabaseDir);
assertThatThrownBy( assertThatThrownBy(
() -> () ->
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments) new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration,
segments,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS)
.create(segment, commonConfiguration, metricsSystem)) .create(segment, commonConfiguration, metricsSystem))
.isInstanceOf(StorageException.class); .isInstanceOf(StorageException.class);
} }
@ -156,7 +164,8 @@ public class RocksDBKeyValueStorageFactoryTest {
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir); when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
final RocksDBKeyValueStorageFactory storageFactory = final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments); new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration, segments, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
storageFactory.create(segment, commonConfiguration, metricsSystem); storageFactory.create(segment, commonConfiguration, metricsSystem);
assertThatCode(storageFactory::isSegmentIsolationSupported).doesNotThrowAnyException(); assertThatCode(storageFactory::isSegmentIsolationSupported).doesNotThrowAnyException();
} }
@ -177,7 +186,10 @@ public class RocksDBKeyValueStorageFactoryTest {
assertThatThrownBy( assertThatThrownBy(
() -> () ->
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments) new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration,
segments,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS)
.create(segment, commonConfiguration, metricsSystem)) .create(segment, commonConfiguration, metricsSystem))
.isInstanceOf(IllegalStateException.class); .isInstanceOf(IllegalStateException.class);
@ -187,7 +199,10 @@ public class RocksDBKeyValueStorageFactoryTest {
assertThatThrownBy( assertThatThrownBy(
() -> () ->
new RocksDBKeyValueStorageFactory(() -> rocksDbConfiguration, segments) new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration,
segments,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS)
.create(segment, commonConfiguration, metricsSystem)) .create(segment, commonConfiguration, metricsSystem))
.isInstanceOf(IllegalStateException.class); .isInstanceOf(IllegalStateException.class);
} }

@ -74,7 +74,7 @@ public class RocksDBMetricsTest {
final ArgumentCaptor<String> longGaugesMetricsNameArgs = ArgumentCaptor.forClass(String.class); final ArgumentCaptor<String> longGaugesMetricsNameArgs = ArgumentCaptor.forClass(String.class);
final ArgumentCaptor<String> longGaugesHelpArgs = ArgumentCaptor.forClass(String.class); final ArgumentCaptor<String> longGaugesHelpArgs = ArgumentCaptor.forClass(String.class);
RocksDBMetrics.of(metricsSystemMock, config(), db, stats); RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS.create(metricsSystemMock, config(), db, stats);
verify(metricsSystemMock, times(4)) verify(metricsSystemMock, times(4))
.createLabelledTimer( .createLabelledTimer(

@ -30,6 +30,7 @@ import org.hyperledger.besu.plugin.services.metrics.Counter;
import org.hyperledger.besu.plugin.services.metrics.LabelledMetric; import org.hyperledger.besu.plugin.services.metrics.LabelledMetric;
import org.hyperledger.besu.plugin.services.metrics.OperationTimer; import org.hyperledger.besu.plugin.services.metrics.OperationTimer;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfiguration;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder;
import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.rocksdb.unsegmented.RocksDBKeyValueStorage;
@ -55,7 +56,8 @@ public class RocksDBKeyValueStorageTest extends AbstractKeyValueStorageTest {
@Override @Override
protected KeyValueStorage createStore() throws Exception { protected KeyValueStorage createStore() throws Exception {
return new RocksDBKeyValueStorage(config(), new NoOpMetricsSystem()); return new RocksDBKeyValueStorage(
config(), new NoOpMetricsSystem(), RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
} }
@Test @Test
@ -79,7 +81,9 @@ public class RocksDBKeyValueStorageTest extends AbstractKeyValueStorageTest {
final ArgumentCaptor<String> longGaugesHelpArgs = ArgumentCaptor.forClass(String.class); final ArgumentCaptor<String> longGaugesHelpArgs = ArgumentCaptor.forClass(String.class);
// Actual call // Actual call
final KeyValueStorage keyValueStorage = new RocksDBKeyValueStorage(config(), metricsSystemMock); final KeyValueStorage keyValueStorage =
new RocksDBKeyValueStorage(
config(), metricsSystemMock, RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
// Assertions // Assertions
assertThat(keyValueStorage).isNotNull(); assertThat(keyValueStorage).isNotNull();

@ -20,6 +20,7 @@ import org.hyperledger.besu.kvstore.AbstractKeyValueStorageTest;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier; import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder; import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBConfigurationBuilder;
import org.hyperledger.besu.plugin.services.storage.rocksdb.segmented.RocksDBColumnarKeyValueStorage; import org.hyperledger.besu.plugin.services.storage.rocksdb.segmented.RocksDBColumnarKeyValueStorage;
import org.hyperledger.besu.services.kvstore.SegmentedKeyValueStorage; import org.hyperledger.besu.services.kvstore.SegmentedKeyValueStorage;
@ -147,7 +148,8 @@ public class RocksDBColumnarKeyValueStorageTest extends AbstractKeyValueStorageT
return new RocksDBColumnarKeyValueStorage( return new RocksDBColumnarKeyValueStorage(
new RocksDBConfigurationBuilder().databaseDir(folder.newFolder().toPath()).build(), new RocksDBConfigurationBuilder().databaseDir(folder.newFolder().toPath()).build(),
Arrays.asList(TestSegment.FOO, TestSegment.BAR), Arrays.asList(TestSegment.FOO, TestSegment.BAR),
new NoOpMetricsSystem()); new NoOpMetricsSystem(),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS);
} }
@Override @Override

Loading…
Cancel
Save