Skip to content

Commit

Permalink
[PIE-1846] Add an experimental flag for disabling timers (#1837)
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
  • Loading branch information
mbaxter authored Aug 9, 2019
1 parent 2fd934e commit 41ece1d
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class MetricsConfiguration {

private static final String DEFAULT_METRICS_PUSH_HOST = "127.0.0.1";
public static final int DEFAULT_METRICS_PUSH_PORT = 9001;
public static final Boolean DEFAULT_TIMERS_ENABLED = true;

private final boolean enabled;
private final int port;
Expand All @@ -42,6 +43,7 @@ public class MetricsConfiguration {
private final int pushInterval;
private final String prometheusJob;
private final List<String> hostsWhitelist;
private final boolean timersEnabled;

public static Builder builder() {
return new Builder();
Expand All @@ -57,7 +59,8 @@ private MetricsConfiguration(
final String pushHost,
final int pushInterval,
final String prometheusJob,
final List<String> hostsWhitelist) {
final List<String> hostsWhitelist,
final boolean timersEnabled) {
this.enabled = enabled;
this.port = port;
this.host = host;
Expand All @@ -68,6 +71,7 @@ private MetricsConfiguration(
this.pushInterval = pushInterval;
this.prometheusJob = prometheusJob;
this.hostsWhitelist = hostsWhitelist;
this.timersEnabled = timersEnabled;
}

public boolean isEnabled() {
Expand Down Expand Up @@ -110,6 +114,10 @@ Collection<String> getHostsWhitelist() {
return Collections.unmodifiableCollection(this.hostsWhitelist);
}

public boolean isTimersEnabled() {
return timersEnabled;
}

@Override
public String toString() {
return MoreObjects.toStringHelper(this)
Expand Down Expand Up @@ -173,6 +181,7 @@ public static class Builder {
private int pushInterval = 15;
private String prometheusJob = "pantheon-client";
private List<String> hostsWhitelist = Arrays.asList("localhost", "127.0.0.1");
private boolean timersEnabled = DEFAULT_TIMERS_ENABLED;

private Builder() {}

Expand Down Expand Up @@ -226,6 +235,11 @@ public Builder hostsWhitelist(final List<String> hostsWhitelist) {
return this;
}

public Builder timersEnabled(final boolean timersEnabled) {
this.timersEnabled = timersEnabled;
return this;
}

public MetricsConfiguration build() {
return new MetricsConfiguration(
enabled,
Expand All @@ -237,7 +251,8 @@ public MetricsConfiguration build() {
pushHost,
pushInterval,
prometheusJob,
hostsWhitelist);
hostsWhitelist,
timersEnabled);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,21 @@ public class PrometheusMetricsSystem implements MetricsSystem {
cachedTimers = new ConcurrentHashMap<>();

private final Set<MetricCategory> enabledCategories;
private final boolean timersEnabled;

PrometheusMetricsSystem(final Set<MetricCategory> enabledCategories) {
PrometheusMetricsSystem(
final Set<MetricCategory> enabledCategories, final boolean timersEnabled) {
this.enabledCategories = ImmutableSet.copyOf(enabledCategories);
this.timersEnabled = timersEnabled;
}

public static MetricsSystem init(final MetricsConfiguration metricsConfiguration) {
if (!metricsConfiguration.isEnabled() && !metricsConfiguration.isPushEnabled()) {
return new NoOpMetricsSystem();
}
final PrometheusMetricsSystem metricsSystem =
new PrometheusMetricsSystem(metricsConfiguration.getMetricCategories());
new PrometheusMetricsSystem(
metricsConfiguration.getMetricCategories(), metricsConfiguration.isTimersEnabled());
if (metricsSystem.isCategoryEnabled(StandardMetricCategory.PROCESS)) {
metricsSystem.collectors.put(
StandardMetricCategory.PROCESS,
Expand Down Expand Up @@ -117,7 +121,7 @@ public LabelledMetric<OperationTimer> createLabelledTimer(
return cachedTimers.computeIfAbsent(
metricName,
(k) -> {
if (isCategoryEnabled(category)) {
if (timersEnabled && isCategoryEnabled(category)) {
final Summary summary =
Summary.build(metricName, help)
.quantile(0.2, 0.02)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class PrometheusMetricsSystemTest {
.thenComparing((o1, o2) -> o1.getLabels().equals(o2.getLabels()) ? 0 : 1);

private final MetricsSystem metricsSystem =
new PrometheusMetricsSystem(DEFAULT_METRIC_CATEGORIES);
new PrometheusMetricsSystem(DEFAULT_METRIC_CATEGORIES, true);

@Test
public void shouldCreateObservationFromCounter() {
Expand Down Expand Up @@ -155,6 +155,19 @@ public void shouldCreateObservationsFromTimerWithLabels() {
new Observation(RPC, "request", null, asList("method", "count")));
}

@Test
public void shouldNotCreateObservationsFromTimerWhenTimersDisabled() {
final MetricsSystem metricsSystem =
new PrometheusMetricsSystem(DEFAULT_METRIC_CATEGORIES, false);
final LabelledMetric<OperationTimer> timer =
metricsSystem.createLabelledTimer(RPC, "request", "Some help", "methodName");

//noinspection EmptyTryBlock
try (final TimingContext ignored = timer.labels("method").startTimer()) {}

assertThat(metricsSystem.streamObservations()).isEmpty();
}

@Test
public void shouldCreateObservationFromGauge() {
metricsSystem.createGauge(JVM, "myValue", "Help", () -> 7d);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import tech.pegasys.pantheon.cli.custom.RpcAuthFileValidator;
import tech.pegasys.pantheon.cli.error.PantheonExceptionHandler;
import tech.pegasys.pantheon.cli.options.EthProtocolOptions;
import tech.pegasys.pantheon.cli.options.MetricsCLIOptions;
import tech.pegasys.pantheon.cli.options.NetworkingOptions;
import tech.pegasys.pantheon.cli.options.RocksDBOptions;
import tech.pegasys.pantheon.cli.options.SynchronizerOptions;
Expand Down Expand Up @@ -160,6 +161,7 @@ public class PantheonCommand implements DefaultCommandValues, Runnable {
final NetworkingOptions networkingOptions = NetworkingOptions.create();
final SynchronizerOptions synchronizerOptions = SynchronizerOptions.create();
final EthProtocolOptions ethProtocolOptions = EthProtocolOptions.create();
final MetricsCLIOptions metricsCLIOptions = MetricsCLIOptions.create();
final RocksDBOptions rocksDBOptions = RocksDBOptions.create();
final TransactionPoolOptions transactionPoolOptions = TransactionPoolOptions.create();
private final RunnerBuilder runnerBuilder;
Expand Down Expand Up @@ -715,19 +717,18 @@ private PantheonCommand registerConverters() {

private PantheonCommand handleUnstableOptions() {
// Add unstable options
UnstableOptionsSubCommand.createUnstableOptions(
commandLine,
ImmutableMap.of(
"P2P Network",
networkingOptions,
"Synchronizer",
synchronizerOptions,
"RocksDB",
rocksDBOptions,
"Ethereum Wire Protocol",
ethProtocolOptions,
"TransactionPool",
transactionPoolOptions));
final ImmutableMap.Builder<String, Object> unstableOptionsBuild = ImmutableMap.builder();
final ImmutableMap<String, Object> unstableOptions =
unstableOptionsBuild
.put("Ethereum Wire Protocol", ethProtocolOptions)
.put("Metrics", metricsCLIOptions)
.put("P2P Network", networkingOptions)
.put("RocksDB", rocksDBOptions)
.put("Synchronizer", synchronizerOptions)
.put("TransactionPool", transactionPoolOptions)
.build();

UnstableOptionsSubCommand.createUnstableOptions(commandLine, unstableOptions);
return this;
}

Expand Down Expand Up @@ -1006,7 +1007,8 @@ public MetricsConfiguration metricsConfiguration() {
"--metrics-push-interval",
"--metrics-push-prometheus-job"));

return MetricsConfiguration.builder()
return metricsCLIOptions
.toDomainObject()
.enabled(isMetricsEnabled)
.host(metricsHost)
.port(metricsPort)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2019 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.
*/
package tech.pegasys.pantheon.cli.options;

import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

import java.util.Arrays;
import java.util.List;

import picocli.CommandLine;

public class MetricsCLIOptions implements CLIOptions<MetricsConfiguration.Builder> {
private static final String TIMERS_ENABLED_FLAG = "--Xmetrics-timers-enabled";

@CommandLine.Option(
names = TIMERS_ENABLED_FLAG,
hidden = true,
defaultValue = "true",
description = "Whether to enable timer metrics (default: ${DEFAULT-VALUE}).")
private Boolean timersEnabled = MetricsConfiguration.DEFAULT_TIMERS_ENABLED;

private MetricsCLIOptions() {}

public static MetricsCLIOptions create() {
return new MetricsCLIOptions();
}

public static MetricsCLIOptions fromConfiguration(final MetricsConfiguration config) {
final MetricsCLIOptions metricsOptions = create();
metricsOptions.timersEnabled = config.isTimersEnabled();
return metricsOptions;
}

@Override
public MetricsConfiguration.Builder toDomainObject() {
return MetricsConfiguration.builder().timersEnabled(timersEnabled);
}

@Override
public List<String> getCLIOptions() {
return Arrays.asList(TIMERS_ENABLED_FLAG + "=" + timersEnabled.toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import tech.pegasys.pantheon.RunnerBuilder;
import tech.pegasys.pantheon.cli.config.EthNetworkConfig;
import tech.pegasys.pantheon.cli.options.EthProtocolOptions;
import tech.pegasys.pantheon.cli.options.MetricsCLIOptions;
import tech.pegasys.pantheon.cli.options.NetworkingOptions;
import tech.pegasys.pantheon.cli.options.RocksDBOptions;
import tech.pegasys.pantheon.cli.options.SynchronizerOptions;
Expand Down Expand Up @@ -288,5 +289,9 @@ public EthProtocolOptions getEthProtocolOptions() {
public TransactionPoolOptions getTransactionPoolOptions() {
return transactionPoolOptions;
}

public MetricsCLIOptions getMetricsCLIOptions() {
return metricsCLIOptions;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2019 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.
*/
package tech.pegasys.pantheon.cli.options;

import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;

public class MetricsCLIOptionsTest
extends AbstractCLIOptionsTest<MetricsConfiguration.Builder, MetricsCLIOptions> {

@Override
MetricsConfiguration.Builder createDefaultDomainObject() {
return MetricsConfiguration.builder();
}

@Override
MetricsConfiguration.Builder createCustomizedDomainObject() {
return MetricsConfiguration.builder()
.timersEnabled(!MetricsConfiguration.DEFAULT_TIMERS_ENABLED);
}

@Override
MetricsCLIOptions optionsFromDomainObject(final MetricsConfiguration.Builder domainObject) {
return MetricsCLIOptions.fromConfiguration(domainObject.build());
}

@Override
MetricsCLIOptions getOptionsFromPantheonCommand(final TestPantheonCommand pantheonCommand) {
return pantheonCommand.getMetricsCLIOptions();
}
}

0 comments on commit 41ece1d

Please sign in to comment.