diff --git a/.gitignore b/.gitignore index 5e58b5b..2ce613a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ dependency-reduced-pom.xml *.releaseBackup release.properties +*.srl diff --git a/README.md b/README.md index d3f336f..c14e86f 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,17 @@ The available command line options may be seen by passing `-h`/`--help`: [--jmx-service-url=URL] [--jmx-user=NAME] [--keyspace-metrics=FILTER] [--node-metrics=FILTER] [--table-metrics=FILTER] - [--exclude-keyspaces=]... [-g=LABEL + [--exclude-keyspaces=]... + [--ssl=MODE] + [--ssl-client-authentication=CLIENT-AUTHENTICATION] + [--ssl-implementation=IMPLEMENTATION] + [--ssl-reload-interval=SECONDS] + [--ssl-server-certificate=SERVER-CERTIFICATE] + [--ssl-server-key=SERVER-KEY] + [--ssl-server-key-password=SERVER-KEY-PASSWORD] + [--ssl-trusted-certificate=TRUSTED-CERTIFICATE] + [--ssl-ciphers=CIPHER[,CIPHER...]]... + [--ssl-protocols=PROTOCOL[,PROTOCOL...]]... [-g=LABEL [,LABEL...]]... [-l=[ADDRESS][:PORT]]... [-t=LABEL[, LABEL...]]... [-e=EXCLUSION...]... -g, --global-labels=LABEL[,LABEL...] @@ -180,6 +190,49 @@ The available command line options may be seen by passing `-h`/`--help`: or PORT will be interpreted as a decimal IPv4 address. This option may be specified more than once to listen on multiple addresses. Defaults to '0.0.0.0:9500' + --ssl=MODE Enable or disable secured communication with SSL. Valid + modes: DISABLE, ENABLE, OPTIONAL. Optional support + requires Netty version 4.0.45 or later. Defaults to + DISABLE. + --ssl-implementation=IMPLEMENTATION + SSL implementation to use for secure communication. + OpenSSL requires platform specific libraries. Valid + implementations: OPENSSL, JDK, DISCOVER. Defaults to + DISCOVER which will use OpenSSL if required libraries + are discoverable. + --ssl-ciphers=CIPHER[,CIPHER...] + A comma-separated list of SSL cipher suites to enable, + in the order of preference. Defaults to system + settings. + --ssl-protocols=PROTOCOL[,PROTOCOL...] + A comma-separated list of TLS protocol versions to + enable. Defaults to system settings. + --ssl-reload-interval=SECONDS + Interval in seconds by which keys and certificates will + be reloaded. Defaults to 0 which will disable run-time + reload of certificates. + --ssl-server-key=SERVER-KEY + Path to the private key file for the SSL server. Must be + provided together with a server-certificate. The file + should contain a PKCS#8 private key in PEM format. + --ssl-server-key-password=SERVER-KEY-PASSWORD + Path to the private key password file for the SSL + server. This is only required if the server-key is + password protected. The file should contain a clear + text password for the server-key. + --ssl-server-certificate=SERVER-CERTIFICATE + Path to the certificate chain file for the SSL server. + Must be provided together with a server-key. The file + should contain an X.509 certificate chain in PEM + format. + --ssl-client-authentication=CLIENT-AUTHENTICATION + Set SSL client authentication mode. Valid options: NONE, + OPTIONAL, REQUIRE, VALIDATE. Defaults to NONE. + --ssl-trusted-certificate=TRUSTED-CERTIFICATE + Path to trusted certificates for verifying the remote + endpoint's certificate. The file should contain an X. + 509 certificate collection in PEM format. Defaults to + the system setting. --family-help=VALUE Include or exclude metric family help in the exposition format. AUTOMATIC excludes help strings when the user agent is Prometheus and includes them for all other diff --git a/agent/src/main/java/com/zegelin/cassandra/exporter/Agent.java b/agent/src/main/java/com/zegelin/cassandra/exporter/Agent.java index d94e2e6..7970465 100644 --- a/agent/src/main/java/com/zegelin/cassandra/exporter/Agent.java +++ b/agent/src/main/java/com/zegelin/cassandra/exporter/Agent.java @@ -28,7 +28,7 @@ public Void call() throws Exception { final MBeanServerInterceptorHarvester harvester = new MBeanServerInterceptorHarvester(harvesterOptions); - final Server server = Server.start(httpServerOptions.listenAddresses, harvester, httpServerOptions.helpExposition); + final Server server = Server.start(harvester, httpServerOptions); Runtime.getRuntime().addShutdownHook(new Thread(() -> { try { diff --git a/bin/generate_cert_for_test.sh b/bin/generate_cert_for_test.sh new file mode 100755 index 0000000..e51862d --- /dev/null +++ b/bin/generate_cert_for_test.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +RESOURCE_PATH="common/src/test/resources" + +# Generate a private key and store it both unecrypted and encrypted (password protected) +# Create a self-signed certificate for the key +mkdir -p ${RESOURCE_PATH}/cert +rm -f ${RESOURCE_PATH}/cert/* +openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -outform PEM -out ${RESOURCE_PATH}/cert/key.pem +echo -n "password" > ${RESOURCE_PATH}/cert/protected-key.pass +openssl pkcs8 -topk8 -v1 PBE-SHA1-RC4-128 -in ${RESOURCE_PATH}/cert/key.pem -out ${RESOURCE_PATH}/cert/protected-key.pem -passout file:${RESOURCE_PATH}/cert/protected-key.pass +openssl req -x509 -new -key ${RESOURCE_PATH}/cert/key.pem -sha256 -days 10000 -out ${RESOURCE_PATH}/cert/cert.pem -subj '/CN=localhost/O=Example Company/C=SE' -nodes diff --git a/common/pom.xml b/common/pom.xml index 942efd0..466a424 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -14,16 +14,25 @@ Cassandra Exporter Common - 3.6.1 + 3.9.5 + + + io.netty + netty-all + 4.0.53.Final + provided + + org.apache.cassandra cassandra-all provided + info.picocli picocli @@ -46,5 +55,20 @@ test + + org.assertj + assertj-core + 3.12.0 + test + + + + io.netty + netty-tcnative-boringssl-static + 2.0.28.Final + test + + + diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/CollectorFunctions.java b/common/src/main/java/com/zegelin/cassandra/exporter/CollectorFunctions.java index 6455bee..61f1ed5 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/CollectorFunctions.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/CollectorFunctions.java @@ -1,15 +1,24 @@ package com.zegelin.cassandra.exporter; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.zegelin.function.FloatFloatFunction; import com.zegelin.cassandra.exporter.collector.dynamic.FunctionalMetricFamilyCollector.CollectorFunction; import com.zegelin.cassandra.exporter.collector.dynamic.FunctionalMetricFamilyCollector.LabeledObjectGroup; import com.zegelin.prometheus.domain.*; +import com.zegelin.prometheus.domain.Interval.Quantile; + import org.apache.cassandra.metrics.CassandraMetricsRegistry.JmxCounterMBean; import org.apache.cassandra.metrics.CassandraMetricsRegistry.JmxGaugeMBean; import org.apache.cassandra.metrics.CassandraMetricsRegistry.JmxMeterMBean; import org.apache.cassandra.utils.EstimatedHistogram; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; public final class CollectorFunctions { @@ -124,7 +133,8 @@ public static CollectorFunction numericGaugeAsCounter() { /** * Collect a {@link JmxGaugeMBean} with a Cassandra {@link EstimatedHistogram} value as a Prometheus summary */ - public static CollectorFunction histogramGaugeAsSummary(final FloatFloatFunction bucketScaleFunction) { + public static CollectorFunction histogramGaugeAsSummary(final FloatFloatFunction bucketScaleFunction,Set excludeQuantiles) { + Set includedQuantiles =excludeQuantiles==null?Interval.Quantile.STANDARD_PERCENTILES:Sets.difference(Interval.Quantile.STANDARD_PERCENTILES,excludeQuantiles); return group -> { final Stream summaryStream = group.labeledObjects().entrySet().stream() .map(e -> new Object() { @@ -135,12 +145,11 @@ public static CollectorFunction histogramGaugeAsSummary(final Flo final long[] bucketData = (long[]) e.gauge.getValue(); if (bucketData.length == 0) { - return new SummaryMetricFamily.Summary(e.labels, Float.NaN, Float.NaN, Interval.asIntervals(Interval.Quantile.STANDARD_PERCENTILES, q -> Float.NaN)); + return new SummaryMetricFamily.Summary(e.labels, Float.NaN, Float.NaN, Interval.asIntervals(includedQuantiles, q -> Float.NaN)); } final EstimatedHistogram histogram = new EstimatedHistogram(bucketData); - - final Iterable quantiles = Interval.asIntervals(Interval.Quantile.STANDARD_PERCENTILES, q -> bucketScaleFunction.apply((float) histogram.percentile(q.value))); + final Iterable quantiles = Interval.asIntervals(includedQuantiles, q -> bucketScaleFunction.apply((float) histogram.percentile(q.value))); return new SummaryMetricFamily.Summary(e.labels, Float.NaN, histogram.count(), quantiles); }); @@ -149,14 +158,14 @@ public static CollectorFunction histogramGaugeAsSummary(final Flo }; } - public static CollectorFunction histogramGaugeAsSummary() { - return histogramGaugeAsSummary(l -> l); + public static CollectorFunction histogramGaugeAsSummary(Set excludeQuantiles) { + return histogramGaugeAsSummary((l -> l),excludeQuantiles); } /** * Collect a {@link SamplingCounting} as a Prometheus summary */ - protected static CollectorFunction samplingAndCountingAsSummary(final FloatFloatFunction quantileScaleFunction) { + protected static CollectorFunction samplingAndCountingAsSummary(final FloatFloatFunction quantileScaleFunction,Set excludeQuantiles) { return group -> { final Stream summaryStream = group.labeledObjects().entrySet().stream() .map(e -> new Object() { @@ -164,8 +173,18 @@ protected static CollectorFunction samplingAndCountingAsSummar final SamplingCounting samplingCounting = e.getValue(); }) .map(e -> { - final Iterable quantiles = Iterables.transform(e.samplingCounting.getIntervals(), i -> i.transform(quantileScaleFunction)); - + + Iterator itr = e.samplingCounting.getIntervals().iterator(); + ArrayList filtered = Lists.newArrayList(); + while(itr.hasNext()) { + Interval interval = itr.next(); + if(excludeQuantiles.contains(interval.quantile)) { + continue; + } + filtered.add(interval); + } + + final Iterable quantiles = Iterables.transform(filtered, i -> i.transform(quantileScaleFunction)); return new SummaryMetricFamily.Summary(e.labels, Float.NaN, e.samplingCounting.getCount(), quantiles); }); @@ -173,7 +192,7 @@ protected static CollectorFunction samplingAndCountingAsSummar }; } - public static CollectorFunction samplingAndCountingAsSummary() { - return samplingAndCountingAsSummary(FloatFloatFunction.identity()); + public static CollectorFunction samplingAndCountingAsSummary(Set excludeQuantiles) { + return samplingAndCountingAsSummary(FloatFloatFunction.identity(),excludeQuantiles); } } diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/FactoriesSupplier.java b/common/src/main/java/com/zegelin/cassandra/exporter/FactoriesSupplier.java index 5539d2b..e143907 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/FactoriesSupplier.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/FactoriesSupplier.java @@ -11,6 +11,7 @@ import com.zegelin.cassandra.exporter.collector.dynamic.FunctionalMetricFamilyCollector; import com.zegelin.cassandra.exporter.collector.jvm.*; import com.zegelin.prometheus.domain.Labels; +import com.zegelin.prometheus.domain.Interval.Quantile; import javax.management.*; import java.util.*; @@ -36,6 +37,7 @@ private static class FactoryBuilder { private final CollectorConstructor collectorConstructor; private final QueryExp objectNameQuery; private final String metricFamilyName; + private Set excludeQuantiles; private String help; @@ -56,10 +58,11 @@ interface LabelMaker extends Function, Map> private final List modifiers = new LinkedList<>(); - FactoryBuilder(final CollectorConstructor collectorConstructor, final QueryExp objectNameQuery, final String metricFamilyName) { + FactoryBuilder(final CollectorConstructor collectorConstructor, final QueryExp objectNameQuery, final String metricFamilyName,Set excludeQuantiles) { this.collectorConstructor = collectorConstructor; this.objectNameQuery = objectNameQuery; this.metricFamilyName = metricFamilyName; + this.excludeQuantiles=excludeQuantiles; } FactoryBuilder withModifier(final Modifier modifier) { @@ -101,13 +104,13 @@ Factory build() { } } - return collectorConstructor.groupCollectorForMBean(name, help, new Labels(rawLabels), mBean); + return collectorConstructor.groupCollectorForMBean(name, help, new Labels(rawLabels), mBean,excludeQuantiles); }; } @FunctionalInterface public interface CollectorConstructor { - MBeanGroupMetricFamilyCollector groupCollectorForMBean(final String name, final String help, final Labels labels, final NamedObject mBean); + MBeanGroupMetricFamilyCollector groupCollectorForMBean(final String name, final String help, final Labels labels, final NamedObject mBean,Set excludeQuantiles); } } @@ -116,6 +119,7 @@ public interface CollectorConstructor { private final Set tableLabels; private final Set excludedKeyspaces; private final Map tableMetricScopeFilters; + private final Set excludeQuantiles; public FactoriesSupplier(final MetadataFactory metadataFactory, final HarvesterOptions options) { @@ -123,6 +127,7 @@ public FactoriesSupplier(final MetadataFactory metadataFactory, final HarvesterO this.perThreadTimingEnabled = options.perThreadTimingEnabled; this.tableLabels = options.tableLabels; this.excludedKeyspaces = options.excludedKeyspaces; + excludeQuantiles=options.excludedHistoQuantiles; this.tableMetricScopeFilters = ImmutableMap.builder() .put(TableMetricScope.NODE, options.nodeMetricsFilter) @@ -136,7 +141,7 @@ private Factory bufferPoolMetricFactory(final FactoryBuilder.CollectorConstructo final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=BufferPool,name=%s", jmxName); final String metricFamilyName = String.format("buffer_pool_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .build(); } @@ -150,7 +155,7 @@ private Factory cqlMetricFactory(final FactoryBuilder.CollectorConstructor colle final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=CQL,name=%s", jmxName); final String metricFamilyName = String.format("cql_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withLabelMaker(keyPropertyList -> labels) .build(); @@ -161,7 +166,7 @@ private Factory cacheMetricFactory(final FactoryBuilder.CollectorConstructor col final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Cache,scope=*,name=%s", jmxName); final String metricFamilyName = String.format("cache_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withLabelMaker(keyPropertyList -> ImmutableMap.of( "cache", keyPropertyList.get("scope").replaceAll("Cache", "").toLowerCase() @@ -174,7 +179,7 @@ private Factory clientMetricFactory(final FactoryBuilder.CollectorConstructor co final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Client,name=%s", jmxName); final String metricFamilyName = String.format("client_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .build(); } @@ -183,7 +188,7 @@ private Factory clientRequestMetricFactory(final FactoryBuilder.CollectorConstru final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=ClientRequest,name=%s,scope=*", jmxName); final String metricFamilyName = String.format("client_request_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withModifier((keyPropertyList, labels) -> { final String scope = keyPropertyList.get("scope"); @@ -216,7 +221,7 @@ private Factory commitLogMetricFactory(final FactoryBuilder.CollectorConstructor final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=CommitLog,name=%s", jmxName); final String metricFamilyName = String.format("commit_log_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .build(); } @@ -225,7 +230,7 @@ private Factory messagingMetricFactory(final FactoryBuilder.CollectorConstructor final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Messaging,name=%s", jmxName); final String metricFamilyName = String.format("messaging_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withLabelMaker(keyPropertyList -> { final String name = keyPropertyList.get("name"); @@ -245,7 +250,7 @@ private Factory memtablePoolMetricsFactory(final FactoryBuilder.CollectorConstru final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=MemtablePool,name=%s", jmxName); final String metricFamilyName = String.format("memtable_pool_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .build(); } @@ -254,7 +259,7 @@ private Factory storageMetric(final FactoryBuilder.CollectorConstructor collecto final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Storage,name=%s", jmxName); final String metricFamilyName = String.format("storage_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .build(); } @@ -359,7 +364,7 @@ private Iterator tableMetricFactory(final Set tableMe final QueryExp query = scope.query(jmxName); final String metricFamilyName = String.format(scope.metricFamilyNameFormat, familyNameSuffix); - return new FactoryBuilder(collectorConstructor, query, metricFamilyName) + return new FactoryBuilder(collectorConstructor, query, metricFamilyName, excludeQuantiles) .withHelp(help) .withModifier((keyPropertyList, labels) -> { labels.putAll(extraLabels); @@ -425,7 +430,7 @@ private Factory threadPoolMetric(final FactoryBuilder.CollectorConstructor colle final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=ThreadPools,path=*,scope=*,name=%s", jmxName); final String metricFamilyName = String.format("thread_pool_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withLabelMaker(keyPropertyList -> ImmutableMap.of( "group", keyPropertyList.get("path"), @@ -438,14 +443,14 @@ private Factory rowIndexMetric(final FactoryBuilder.CollectorConstructor collect final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Index,scope=RowIndexEntry,name=%s", jmxName); final String metricFamilyName = String.format("row_index_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName).build(); + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles).build(); } private Factory droppedMessagesMetric(final FactoryBuilder.CollectorConstructor collectorConstructor, final String jmxName, final String familyNameSuffix, final String help) { final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=DroppedMessage,scope=*,name=%s", jmxName); final String metricFamilyName = String.format("dropped_messages_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withLabelMaker(keyPropertyList -> ImmutableMap.of("message_type", keyPropertyList.get("scope"))) .build(); @@ -455,7 +460,7 @@ private Factory compactionMetric(final FactoryBuilder.CollectorConstructor colle final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Compaction,name=%s", jmxName); final String metricFamilyName = String.format("compaction_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .build(); } @@ -464,7 +469,7 @@ private Factory connectionMetric(final FactoryBuilder.CollectorConstructor colle final ObjectName objectNamePattern = format("org.apache.cassandra.metrics:type=Connection,scope=*,name=%s", jmxName); final String metricFamilyName = String.format("endpoint_connection_%s", familyNameSuffix); - return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName) + return new FactoryBuilder(collectorConstructor, objectNamePattern, metricFamilyName, excludeQuantiles) .withHelp(help) .withLabelMaker(keyPropertyList -> { final HashMap labels = new HashMap<>(); @@ -492,26 +497,26 @@ private Factory connectionMetric(final FactoryBuilder.CollectorConstructor colle } - private static FactoryBuilder.CollectorConstructor timerAsSummaryCollectorConstructor() { - return (name, help, labels, mBean) -> { + private FactoryBuilder.CollectorConstructor timerAsSummaryCollectorConstructor() { + return (name, help, labels, mBean, excludeQuantiles) -> { final NamedObject samplingCountingNamedObject = CassandraMetricsUtilities.jmxTimerMBeanAsSamplingCounting(mBean); return new FunctionalMetricFamilyCollector<>(name, help, ImmutableMap.of(labels, samplingCountingNamedObject), - samplingAndCountingAsSummary(MetricValueConversionFunctions::nanosecondsToSeconds)); + samplingAndCountingAsSummary(MetricValueConversionFunctions::nanosecondsToSeconds,excludeQuantiles)); }; } - private static FactoryBuilder.CollectorConstructor histogramAsSummaryCollectorConstructor() { - return (name, help, labels, mBean) -> { + private FactoryBuilder.CollectorConstructor histogramAsSummaryCollectorConstructor() { + return (name, help, labels, mBean,excludeQuantiles) -> { final NamedObject samplingCountingNamedObject = CassandraMetricsUtilities.jmxHistogramAsSamplingCounting(mBean); - return new FunctionalMetricFamilyCollector<>(name, help, ImmutableMap.of(labels, samplingCountingNamedObject), samplingAndCountingAsSummary()); + return new FunctionalMetricFamilyCollector<>(name, help, ImmutableMap.of(labels, samplingCountingNamedObject), samplingAndCountingAsSummary(excludeQuantiles)); }; } private static FactoryBuilder.CollectorConstructor functionalCollectorConstructor(final FunctionalMetricFamilyCollector.CollectorFunction function) { - return (final String name, final String help, final Labels labels, final NamedObject mBean) -> + return (final String name, final String help, final Labels labels, final NamedObject mBean,Set excludeQuantiles) -> new FunctionalMetricFamilyCollector<>(name, help, ImmutableMap.of(labels, mBean.cast()), function); } @@ -700,10 +705,10 @@ public List get() { builder.addAll(tableMetricFactory(functionalCollectorConstructor(numericGaugeAsGauge(MetricValueConversionFunctions::neg1ToNaN)), "CompressionRatio", "compression_ratio", null)); - builder.addAll(tableMetricFactory(functionalCollectorConstructor(histogramGaugeAsSummary()), "EstimatedPartitionSizeHistogram", "estimated_partition_size_bytes", null)); + builder.addAll(tableMetricFactory(functionalCollectorConstructor(histogramGaugeAsSummary(excludeQuantiles)), "EstimatedPartitionSizeHistogram", "estimated_partition_size_bytes", null)); builder.addAll(tableMetricFactory(functionalCollectorConstructor(numericGaugeAsGauge(MetricValueConversionFunctions::neg1ToNaN)), "EstimatedPartitionCount", "estimated_partitions", null)); - builder.addAll(tableMetricFactory(functionalCollectorConstructor(histogramGaugeAsSummary()), "EstimatedColumnCountHistogram", "estimated_columns", null)); + builder.addAll(tableMetricFactory(functionalCollectorConstructor(histogramGaugeAsSummary(excludeQuantiles)), "EstimatedColumnCountHistogram", "estimated_columns", null)); builder.addAll(tableMetricFactory(histogramAsSummaryCollectorConstructor(), "SSTablesPerReadHistogram", "sstables_per_read", null)); // @@ -793,10 +798,12 @@ public List get() { // org.apache.cassandra.metrics.ThreadPoolMetrics { builder.add(threadPoolMetric(functionalCollectorConstructor(numericGaugeAsGauge()), "ActiveTasks", "active_tasks", null)); + builder.add(threadPoolMetric(functionalCollectorConstructor(numericGaugeAsGauge()), "PendingTasks", "pending_tasks", null)); builder.add(threadPoolMetric(functionalCollectorConstructor(numericGaugeAsCounter()), "CompletedTasks", "completed_tasks_total", null)); builder.add(threadPoolMetric(functionalCollectorConstructor(counterAsCounter()), "TotalBlockedTasks", "blocked_tasks_total", null)); builder.add(threadPoolMetric(functionalCollectorConstructor(counterAsGauge()), "CurrentlyBlockedTasks", "blocked_tasks", null)); builder.add(threadPoolMetric(functionalCollectorConstructor(numericGaugeAsGauge()), "MaxPoolSize", "maximum_tasks", null)); + builder.add(threadPoolMetric(functionalCollectorConstructor(numericGaugeAsGauge()), "MaxTasksQueued", "maximum_tasks_queued", null)); } diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/Harvester.java b/common/src/main/java/com/zegelin/cassandra/exporter/Harvester.java index ae433c9..bb99d28 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/Harvester.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/Harvester.java @@ -7,6 +7,7 @@ import com.zegelin.jmx.NamedObject; import com.zegelin.cassandra.exporter.cli.HarvesterOptions; import com.zegelin.prometheus.domain.CounterMetricFamily; +import com.zegelin.prometheus.domain.Interval.Quantile; import com.zegelin.prometheus.domain.Labels; import com.zegelin.prometheus.domain.MetricFamily; import com.zegelin.prometheus.domain.NumericMetric; @@ -132,6 +133,7 @@ public boolean equals(final Object o) { private final boolean collectorTimingEnabled; private final Map collectionTimes = new ConcurrentHashMap<>(); + private final Set excludedHistoQuantiles; private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder() .setNameFormat("cassandra-exporter-harvester-defer-%d") @@ -145,6 +147,11 @@ protected Harvester(final MetadataFactory metadataFactory, final HarvesterOption this.exclusions = options.exclusions; this.enabledGlobalLabels = options.globalLabels; this.collectorTimingEnabled = options.collectorTimingEnabled; + this.excludedHistoQuantiles=options.excludedHistoQuantiles; + } + + public Set getExcludedHistoQuantiles() { + return excludedHistoQuantiles; } protected void addCollectorFactory(final MBeanGroupMetricFamilyCollector.Factory factory) { diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/cli/HarvesterOptions.java b/common/src/main/java/com/zegelin/cassandra/exporter/cli/HarvesterOptions.java index dea9e82..a7d97b1 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/cli/HarvesterOptions.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/cli/HarvesterOptions.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableSet; import com.zegelin.netty.Floats; +import com.zegelin.prometheus.domain.Interval.Quantile; import com.zegelin.cassandra.exporter.FactoriesSupplier; import com.zegelin.cassandra.exporter.Harvester; import picocli.CommandLine; @@ -152,4 +153,27 @@ public void setExcludeSystemTables(final boolean excludeSystemTables) { excludedKeyspaces.addAll(CASSANDRA_SYSTEM_KEYSPACES); } + + public Set excludedHistoQuantiles = new HashSet<>(); + @Option(names = {"--exclude-from-histogram"}, paramLabel = "EXCLUSION", arity = "1..*", + description = "Select which quantiles to exclude from histogram metrics. The specified quantiles are excluded from all histogram/summary metrics" + + "Valid options are: P_50, P_75, P_95, P_98, P_99, P_99_9" + + "'P_50' (Quantile .5), " + + "'P_75' (Quantile .75), " + + "'P_95' (Quantile .95), " + + "'P_98' (Quantile .98). " + + "'P_99' (Quantile .99). " + + "'P_99_9' (Quantile .999). " + + "The default is to include all quantiles. " + ) + void setExcludeFromHistogram(final Set values) { + values.forEach(e->{ + Quantile q=Quantile.ALL_PERCENTILES.get(e); + if(q==null) { + throw new IllegalArgumentException(String.format("The specified exlusion quantile '%s' is invalid, value values are '%s'", e,Quantile.ALL_PERCENTILES.keySet())); + } + excludedHistoQuantiles.add(q); + }); + } + } diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/cli/HttpServerOptions.java b/common/src/main/java/com/zegelin/cassandra/exporter/cli/HttpServerOptions.java index 08cc20d..ff70ebb 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/cli/HttpServerOptions.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/cli/HttpServerOptions.java @@ -1,11 +1,16 @@ package com.zegelin.cassandra.exporter.cli; -import com.zegelin.picocli.InetSocketAddressTypeConverter; import com.zegelin.cassandra.exporter.netty.HttpHandler; +import com.zegelin.cassandra.exporter.netty.ssl.ClientAuthentication; +import com.zegelin.cassandra.exporter.netty.ssl.SslImplementation; +import com.zegelin.cassandra.exporter.netty.ssl.SslMode; +import com.zegelin.picocli.InetSocketAddressTypeConverter; import picocli.CommandLine.Option; +import java.io.File; import java.net.InetSocketAddress; import java.util.List; +import java.util.Set; public class HttpServerOptions { @@ -33,6 +38,91 @@ protected int defaultPort() { "Defaults to '${DEFAULT-VALUE}'") public List listenAddresses; + @Option(names = "--ssl", + paramLabel = "MODE", + defaultValue = "DISABLE", + description = "Enable or disable secured communication with SSL. " + + "Valid modes: ${COMPLETION-CANDIDATES}. " + + "Optional support requires Netty version 4.0.45 or later. " + + "Defaults to ${DEFAULT-VALUE}." + ) + public SslMode sslMode = SslMode.DISABLE; + + @Option(names = "--ssl-implementation", + paramLabel = "IMPLEMENTATION", + defaultValue = "DISCOVER", + description = "SSL implementation to use for secure communication. " + + "OpenSSL requires platform specific libraries. " + + "Valid implementations: ${COMPLETION-CANDIDATES}. " + + "Defaults to ${DEFAULT-VALUE} which will use OpenSSL if required libraries are discoverable." + ) + public SslImplementation sslImplementation = SslImplementation.DISCOVER; + + @Option(names = "--ssl-ciphers", + paramLabel = "CIPHER", + split = ",", + description = "A comma-separated list of SSL cipher suites to enable, in the order of preference. " + + "Defaults to system settings." + ) + public List sslCiphers; + + @Option(names = "--ssl-protocols", + paramLabel = "PROTOCOL", + split = ",", + description = "A comma-separated list of TLS protocol versions to enable. " + + "Defaults to system settings." + ) + public Set sslProtocols; + + @Option(names = "--ssl-reload-interval", + paramLabel = "SECONDS", + defaultValue = "0", + description = "Interval in seconds by which keys and certificates will be reloaded. " + + "Defaults to ${DEFAULT-VALUE} which will disable run-time reload of certificates." + ) + public long sslReloadIntervalInSeconds = 0L; + + @Option(names = "--ssl-server-key", + paramLabel = "SERVER-KEY", + description = "Path to the private key file for the SSL server. " + + "Must be provided together with a server-certificate. " + + "The file should contain a PKCS#8 private key in PEM format." + ) + public File sslServerKeyFile; + + @Option(names = "--ssl-server-key-password", + paramLabel = "SERVER-KEY-PASSWORD", + description = "Path to the private key password file for the SSL server. " + + "This is only required if the server-key is password protected. " + + "The file should contain a clear text password for the server-key." + ) + public File sslServerKeyPasswordFile; + + @Option(names = "--ssl-server-certificate", + paramLabel = "SERVER-CERTIFICATE", + description = "Path to the certificate chain file for the SSL server. " + + "Must be provided together with a server-key. " + + "The file should contain an X.509 certificate chain in PEM format." + ) + public File sslServerCertificateFile; + + @Option(names = "--ssl-client-authentication", + paramLabel = "CLIENT-AUTHENTICATION", + defaultValue = "NONE", + description = "Set SSL client authentication mode. " + + "Valid options: ${COMPLETION-CANDIDATES}. " + + "Defaults to ${DEFAULT-VALUE}." + ) + public ClientAuthentication sslClientAuthentication = ClientAuthentication.NONE; + + @Option(names = "--ssl-trusted-certificate", + paramLabel = "TRUSTED-CERTIFICATE", + description = "Path to trusted certificates for verifying the remote endpoint's certificate. " + + "The file should contain an X.509 certificate collection in PEM format. " + + "Defaults to the system setting." + ) + public File sslTrustedCertificateFile; + @Option(names = {"--family-help"}, paramLabel = "VALUE", defaultValue = "AUTOMATIC", diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/collector/LatencyMetricGroupSummaryCollector.java b/common/src/main/java/com/zegelin/cassandra/exporter/collector/LatencyMetricGroupSummaryCollector.java index c7aacb3..d6520fe 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/collector/LatencyMetricGroupSummaryCollector.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/collector/LatencyMetricGroupSummaryCollector.java @@ -2,11 +2,13 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.zegelin.jmx.NamedObject; import com.zegelin.cassandra.exporter.MBeanGroupMetricFamilyCollector; import com.zegelin.cassandra.exporter.MetricValueConversionFunctions; import com.zegelin.cassandra.exporter.SamplingCounting; import com.zegelin.prometheus.domain.Interval; +import com.zegelin.prometheus.domain.Interval.Quantile; import com.zegelin.prometheus.domain.Labels; import com.zegelin.prometheus.domain.MetricFamily; import com.zegelin.prometheus.domain.SummaryMetricFamily; @@ -14,8 +16,12 @@ import org.apache.cassandra.metrics.CassandraMetricsRegistry.JmxTimerMBean; import javax.management.ObjectName; + +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.stream.Stream; import static com.zegelin.cassandra.exporter.CassandraMetricsUtilities.jmxTimerMBeanAsSamplingCounting; @@ -73,21 +79,23 @@ LatencyMetricGroup removeMBean(final ObjectName objectName) { private final String name; private final String help; private final Map latencyMetricGroups; + private final Set excludeQuantiles; - private LatencyMetricGroupSummaryCollector(final String name, final String help, final Map latencyMetricGroups) { + private LatencyMetricGroupSummaryCollector(final String name, final String help, final Map latencyMetricGroups, Set excludeQuantiles) { this.name = name; this.help = help; this.latencyMetricGroups = ImmutableMap.copyOf(latencyMetricGroups); + this.excludeQuantiles=excludeQuantiles; } - public static LatencyMetricGroupSummaryCollector collectorForMBean(final String name, final String help, final Labels labels, final NamedObject mBean) { + public static LatencyMetricGroupSummaryCollector collectorForMBean(final String name, final String help, final Labels labels, final NamedObject mBean,Set excludeQuantiles) { final NamedObject timer = (mBean.object instanceof JmxTimerMBean) ? jmxTimerMBeanAsSamplingCounting(mBean) : null; final NamedObject counter = mBean.map((n, o) -> (o instanceof JmxCounterMBean) ? (JmxCounterMBean) o : null); final LatencyMetricGroup latencyMetricGroup = new LatencyMetricGroup(timer, counter); - return new LatencyMetricGroupSummaryCollector(name, help, ImmutableMap.of(labels, latencyMetricGroup)); + return new LatencyMetricGroupSummaryCollector(name, help, ImmutableMap.of(labels, latencyMetricGroup),excludeQuantiles); } @Override @@ -108,7 +116,7 @@ public MBeanGroupMetricFamilyCollector merge(final MBeanGroupMetricFamilyCollect newLatencyMetricGroups.merge(group.getKey(), group.getValue(), LatencyMetricGroup::merge); } - return new LatencyMetricGroupSummaryCollector(name, help, newLatencyMetricGroups); + return new LatencyMetricGroupSummaryCollector(name, help, newLatencyMetricGroups,excludeQuantiles); } @Override @@ -129,7 +137,7 @@ public MBeanGroupMetricFamilyCollector removeMBean(final ObjectName mBeanName) { return null; } - return new LatencyMetricGroupSummaryCollector(name, help, newLatencyMetricGroups); + return new LatencyMetricGroupSummaryCollector(name, help, newLatencyMetricGroups,excludeQuantiles); } @Override @@ -144,10 +152,20 @@ public Stream collect() { final float count = e.latencyMetricGroup.latencyTimer.object.getCount(); final float sum = microsecondsToSeconds(e.latencyMetricGroup.totalLatencyCounter.object.getCount()); - final Iterable quantiles = Iterables.transform(e.latencyMetricGroup.latencyTimer.object.getIntervals(), + Iterator itr=e.latencyMetricGroup.latencyTimer.object.getIntervals().iterator(); + ArrayList filtered = Lists.newArrayList(); + while(itr.hasNext()) { + Interval interval = itr.next(); + if(excludeQuantiles.contains(interval.quantile)) { + continue; + } + filtered.add(interval); + } + + final Iterable quantiles = Iterables.transform(filtered, i -> i.transform(MetricValueConversionFunctions::nanosecondsToSeconds) ); - + return new SummaryMetricFamily.Summary(e.labels, sum, count, quantiles); }); diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/HttpHandler.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/HttpHandler.java index 2748da5..e065f1d 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/netty/HttpHandler.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/HttpHandler.java @@ -10,8 +10,9 @@ import com.zegelin.cassandra.exporter.Harvester; import com.zegelin.prometheus.domain.Labels; import com.zegelin.prometheus.domain.MetricFamily; -import com.zegelin.prometheus.exposition.json.JsonFormatChunkedInput; -import com.zegelin.prometheus.exposition.text.TextFormatChunkedInput; +import com.zegelin.prometheus.exposition.json.JsonFormatExposition; +import com.zegelin.prometheus.exposition.text.TextFormatExposition; +import com.zegelin.prometheus.exposition.FormattedByteChannel; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelFuture; @@ -19,9 +20,11 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.*; +import io.netty.handler.stream.ChunkedNioStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.channels.ReadableByteChannel; import java.time.Instant; import java.util.List; import java.util.Map; @@ -296,7 +299,8 @@ private ChannelFuture sendMetrics(final ChannelHandlerContext ctx, final FullHtt lastWriteFuture = ctx.writeAndFlush(response); if (request.getMethod() == HttpMethod.GET) { - lastWriteFuture = ctx.writeAndFlush(new HttpChunkedInput(new TextFormatChunkedInput(metricFamilyStream, timestamp, globalLabels, includeHelp))); + ReadableByteChannel byteChannel = new FormattedByteChannel(new TextFormatExposition(metricFamilyStream, timestamp, globalLabels, includeHelp)); + lastWriteFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedNioStream(byteChannel, FormattedByteChannel.MAX_CHUNK_SIZE))); } return lastWriteFuture; @@ -308,7 +312,8 @@ private ChannelFuture sendMetrics(final ChannelHandlerContext ctx, final FullHtt lastWriteFuture = ctx.writeAndFlush(response); if (request.getMethod() == HttpMethod.GET) { - lastWriteFuture = ctx.writeAndFlush(new HttpChunkedInput(new JsonFormatChunkedInput(metricFamilyStream, timestamp, globalLabels, includeHelp))); + ReadableByteChannel byteChannel = new FormattedByteChannel(new JsonFormatExposition(metricFamilyStream, timestamp, globalLabels, includeHelp)); + lastWriteFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedNioStream(byteChannel, FormattedByteChannel.MAX_CHUNK_SIZE))); } return lastWriteFuture; diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/Server.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/Server.java index 21e2597..1091522 100644 --- a/common/src/main/java/com/zegelin/cassandra/exporter/netty/Server.java +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/Server.java @@ -4,6 +4,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.zegelin.cassandra.exporter.Harvester; +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import com.zegelin.cassandra.exporter.netty.ssl.SslSupport; import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.PooledByteBufAllocator; import io.netty.channel.Channel; @@ -41,10 +43,12 @@ public Server(final List channels, final EventLoopGroup eventLoopGroup) public static class ChildInitializer extends ChannelInitializer { private final Harvester harvester; private final HttpHandler.HelpExposition helpExposition; + private final SslSupport sslSupport; - ChildInitializer(final Harvester harvester, final HttpHandler.HelpExposition helpExposition) { + ChildInitializer(final Harvester harvester, final HttpServerOptions httpServerOptions) { this.harvester = harvester; - this.helpExposition = helpExposition; + this.helpExposition = httpServerOptions.helpExposition; + this.sslSupport = new SslSupport(httpServerOptions); } @Override @@ -54,13 +58,14 @@ public void initChannel(final SocketChannel ch) { .addLast(new HttpObjectAggregator(1048576)) .addLast(new HttpContentCompressor()) .addLast(new ChunkedWriteHandler()) - .addLast(new HttpHandler(harvester, helpExposition)); + .addLast(new HttpHandler(harvester, helpExposition)) + .addLast(new SuppressingExceptionHandler()); + + sslSupport.maybeAddHandler(ch); } } - public static Server start(final List listenAddresses, - final Harvester harvester, - final HttpHandler.HelpExposition helpExposition) throws InterruptedException { + public static Server start(final Harvester harvester, final HttpServerOptions httpServerOptions) throws InterruptedException { final ThreadFactory threadFactory = new ThreadFactoryBuilder() .setDaemon(true) @@ -74,13 +79,13 @@ public static Server start(final List listenAddresses, bootstrap.group(eventLoopGroup) .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) .channel(NioServerSocketChannel.class) - .childHandler(new ChildInitializer(harvester, helpExposition)); + .childHandler(new ChildInitializer(harvester, httpServerOptions)); final List serverChannels; { final ImmutableList.Builder builder = ImmutableList.builder(); - for (final InetSocketAddress listenAddress : listenAddresses) { + for (final InetSocketAddress listenAddress : httpServerOptions.listenAddresses) { builder.add(bootstrap.bind(listenAddress).sync().channel()); } diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/SuppressingExceptionHandler.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/SuppressingExceptionHandler.java new file mode 100644 index 0000000..1322f20 --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/SuppressingExceptionHandler.java @@ -0,0 +1,26 @@ +package com.zegelin.cassandra.exporter.netty; + +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class SuppressingExceptionHandler extends ChannelHandlerAdapter { + private static final Logger logger = LoggerFactory.getLogger(SuppressingExceptionHandler.class); + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + if (brokenPipeException(cause)) { + logger.debug("Exception while processing scrape request: {}", cause.getMessage()); + } else { + ctx.fireExceptionCaught(cause); + } + } + + private boolean brokenPipeException(Throwable cause) { + return cause instanceof IOException + && "Broken pipe".equals(cause.getMessage()); + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/ClientAuthentication.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/ClientAuthentication.java new file mode 100644 index 0000000..019286e --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/ClientAuthentication.java @@ -0,0 +1,26 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import io.netty.handler.ssl.ClientAuth; + +public enum ClientAuthentication { + NONE(ClientAuth.NONE, false), + OPTIONAL(ClientAuth.OPTIONAL, false), + REQUIRE(ClientAuth.REQUIRE, false), + VALIDATE(ClientAuth.REQUIRE, true); + + private final ClientAuth clientAuth; + private final boolean hostnameValidation; + + ClientAuthentication(final ClientAuth clientAuth, final boolean hostnameValidation) { + this.clientAuth = clientAuth; + this.hostnameValidation = hostnameValidation; + } + + ClientAuth getClientAuth() { + return clientAuth; + } + + boolean getHostnameValidation() { + return hostnameValidation; + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/ReloadWatcher.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/ReloadWatcher.java new file mode 100644 index 0000000..958d43f --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/ReloadWatcher.java @@ -0,0 +1,93 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.Collection; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +// TODO: Switch to using java.time.* classes (Instant, Duration, etc) and java.nio.Path +public class ReloadWatcher { + private static final Logger logger = LoggerFactory.getLogger(ReloadWatcher.class); + + private static final long RELOAD_MARGIN_MILLIS = 1000; + private final long intervalInMs; + private final Collection files; + + private long nextReloadAt; + private long reloadedAt; + + public ReloadWatcher(final HttpServerOptions httpServerOptions) { + intervalInMs = TimeUnit.SECONDS.toMillis(httpServerOptions.sslReloadIntervalInSeconds); + files = Stream.of(httpServerOptions.sslServerKeyFile, + httpServerOptions.sslServerKeyPasswordFile, + httpServerOptions.sslServerCertificateFile, + httpServerOptions.sslTrustedCertificateFile) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + logger.info("Watching {} for changes every {} seconds.", this.files, httpServerOptions.sslReloadIntervalInSeconds); + reset(System.currentTimeMillis()); + } + + private void reset(final long now) { + // Create a 1 second margin to compensate for poor resolution of File.lastModified() + reloadedAt = now - RELOAD_MARGIN_MILLIS; + + nextReloadAt = now + intervalInMs; + logger.debug("Next reload at {}.", nextReloadAt); + } + + public synchronized void forceReload() { + if (!enabled()) { + return; + } + + logger.info("Forced reload of exporter certificates on next scrape."); + + reloadedAt = 0L; + nextReloadAt = 0L; + } + + boolean needReload() { + if (!enabled()) { + return false; + } + + final long now = System.currentTimeMillis(); + + if (timeToPoll(now)) { + return reallyNeedReload(now); + } + + return false; + } + + private boolean enabled() { + return intervalInMs > 0; + } + + private boolean timeToPoll(final long now) { + return now > nextReloadAt; + } + + private synchronized boolean reallyNeedReload(final long now) { + if (timeToPoll(now)) { + try { + return anyFileModified(); + } finally { + reset(now); + } + } + return false; + } + + private boolean anyFileModified() { + return files.stream().anyMatch(f -> f.lastModified() > reloadedAt); + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslContextFactory.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslContextFactory.java new file mode 100644 index 0000000..b1530cc --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslContextFactory.java @@ -0,0 +1,98 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import com.google.common.collect.Iterables; +import com.google.common.io.Files; +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLException; +import java.io.IOException; +import java.security.cert.CertificateException; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.nio.charset.StandardCharsets.UTF_8; + +public class SslContextFactory { + private static final Logger logger = LoggerFactory.getLogger(SslContextFactory.class); + + private final HttpServerOptions httpServerOptions; + + public SslContextFactory(HttpServerOptions httpServerOptions) { + this.httpServerOptions = httpServerOptions; + } + + SslContext createSslContext() { + final SslContextBuilder builder = getContextBuilder(); + + builder.sslProvider(httpServerOptions.sslImplementation.getProvider()); + + if (httpServerOptions.sslProtocols != null) { + builder.protocols(Iterables.toArray(httpServerOptions.sslProtocols, String.class)); + } + + builder.clientAuth(httpServerOptions.sslClientAuthentication.getClientAuth()); + + builder.trustManager(httpServerOptions.sslTrustedCertificateFile); + + builder.ciphers(httpServerOptions.sslCiphers); + + try { + return builder.build(); + + } catch (final SSLException e) { + throw new IllegalArgumentException("Failed to initialize an SSL context for the exporter.", e); + } + } + + private SslContextBuilder getContextBuilder() { + if (hasServerKeyAndCert()) { + return SslContextBuilder.forServer(httpServerOptions.sslServerCertificateFile, + httpServerOptions.sslServerKeyFile, + getKeyPassword()); + } else { + return getSelfSignedContextBuilder(); + } + } + + private boolean hasServerKeyAndCert() { + if (httpServerOptions.sslServerKeyFile != null) { + checkArgument(httpServerOptions.sslServerCertificateFile != null, + "A server certificate must be specified together with the server key for the exporter."); + return true; + } + + checkArgument(httpServerOptions.sslServerCertificateFile == null, + "A server key must be specified together with the server certificate for the exporter."); + + return false; + } + + private String getKeyPassword() { + if (httpServerOptions.sslServerKeyPasswordFile == null) { + return null; + } + + try { + return Files.toString(httpServerOptions.sslServerKeyPasswordFile, UTF_8); + + } catch (final IOException e) { + throw new IllegalArgumentException("Unable to read SSL server key password file for the exporter.", e); + } + } + + private SslContextBuilder getSelfSignedContextBuilder() { + logger.warn("Running exporter in SSL mode with insecure self-signed certificate"); + + try { + final SelfSignedCertificate ssc = new SelfSignedCertificate(); + return SslContextBuilder.forServer(ssc.key(), ssc.cert()); + + } catch (final CertificateException e) { + throw new IllegalArgumentException("Failed to create self-signed certificate for the exporter.", e); + } + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslImplementation.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslImplementation.java new file mode 100644 index 0000000..48e1ea0 --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslImplementation.java @@ -0,0 +1,41 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import io.netty.handler.ssl.OpenSsl; +import io.netty.handler.ssl.SslProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public enum SslImplementation { + OPENSSL(SslProvider.OPENSSL), + JDK(SslProvider.JDK), + DISCOVER(); + + private final SslProvider provider; + + SslImplementation() { + provider = null; + } + + SslImplementation(final SslProvider provider) { + this.provider = provider; + } + + SslProvider getProvider() { + if (provider != null) { + return provider; + } else { + if (OpenSsl.isAvailable()) { + logger().info("Native OpenSSL library discovered for exporter: {}", OpenSsl.versionString()); + return SslProvider.OPENSSL; + } else { + logger().info("No native OpenSSL library discovered for exporter - falling back to JDK implementation"); + return SslProvider.JDK; + } + } + } + + // Instead of normal static initialization which cause JVM to bail out. + private Logger logger() { + return LoggerFactory.getLogger(SslImplementation.class); + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslMode.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslMode.java new file mode 100644 index 0000000..4ae5884 --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslMode.java @@ -0,0 +1,7 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +public enum SslMode { + DISABLE, + ENABLE, + OPTIONAL +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslSupport.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslSupport.java new file mode 100644 index 0000000..6c750be --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SslSupport.java @@ -0,0 +1,108 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import com.google.common.annotations.VisibleForTesting; +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.ssl.OptionalSslHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import java.net.InetSocketAddress; +import java.util.concurrent.atomic.AtomicReference; + +public class SslSupport { + private static final Logger logger = LoggerFactory.getLogger(SslSupport.class); + + private final HttpServerOptions httpServerOptions; + private final SslContextFactory sslContextFactory; + private final ReloadWatcher reloadWatcher; + private final AtomicReference sslContextRef = new AtomicReference<>(); + + public SslSupport(final HttpServerOptions httpServerOptions) { + this.httpServerOptions = httpServerOptions; + + if (isEnabled()) { + sslContextFactory = new SslContextFactory(httpServerOptions); + reloadWatcher = new ReloadWatcher(httpServerOptions); + sslContextRef.set(sslContextFactory.createSslContext()); + } else { + sslContextFactory = null; + reloadWatcher = null; + } + } + + public void maybeAddHandler(final SocketChannel ch) { + if (isEnabled()) { + ch.pipeline() + .addFirst(createSslHandler(ch)) + .addLast(new UnexpectedSslExceptionHandler(reloadWatcher)) + .addLast(new SuppressingSslExceptionHandler()); + } + } + + private boolean isEnabled() { + return httpServerOptions.sslMode != SslMode.DISABLE; + } + + private ChannelHandler createSslHandler(final SocketChannel socketChannel) { + maybeReloadContext(); + + if (httpServerOptions.sslMode == SslMode.OPTIONAL) { + if (httpServerOptions.sslClientAuthentication.getHostnameValidation()) { + return new OptionalSslHandler(sslContextRef.get()) { + @Override + protected SslHandler newSslHandler(final ChannelHandlerContext handlerContext, final SslContext context) { + return createValidatingSslHandler(context, handlerContext.alloc(), socketChannel.remoteAddress()); + } + }; + } else { + return new OptionalSslHandler(sslContextRef.get()); + } + } else { + if (httpServerOptions.sslClientAuthentication.getHostnameValidation()) { + return createValidatingSslHandler(sslContextRef.get(), socketChannel.alloc(), socketChannel.remoteAddress()); + } else { + return sslContextRef.get().newHandler(socketChannel.alloc()); + } + } + } + + private SslHandler createValidatingSslHandler(final SslContext context, final ByteBufAllocator allocator, final InetSocketAddress peer) { + final SslHandler handler = context.newHandler(allocator, peer.getHostString(), peer.getPort()); + + final SSLEngine engine = handler.engine(); + + final SSLParameters sslParameters = engine.getSSLParameters(); + sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); + + engine.setSSLParameters(sslParameters); + + return handler; + } + + private void maybeReloadContext() { + if (reloadWatcher.needReload()) { + try { + sslContextRef.set(sslContextFactory.createSslContext()); + logger.info("Reloaded exporter SSL certificate"); + + } catch (final IllegalArgumentException e) { + logger.error("Failed to reload exporter SSL certificate - Next poll in {} seconds.", httpServerOptions.sslReloadIntervalInSeconds); + } + } else { + logger.debug("No need to reload exporter SSL certificate."); + } + } + + @VisibleForTesting + SslContext getSslContext() { + return sslContextRef.get(); + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SuppressingSslExceptionHandler.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SuppressingSslExceptionHandler.java new file mode 100644 index 0000000..c0c9d0b --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/SuppressingSslExceptionHandler.java @@ -0,0 +1,59 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.DecoderException; +import io.netty.handler.ssl.NotSslRecordException; +import io.netty.util.ReferenceCountUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLHandshakeException; +import java.net.SocketAddress; + +/** + * This handler will catch and suppress exceptions which are triggered when a client send a + * non-SSL request when SSL is required. We mute these exceptions as they are typically + * caused by misbehaving clients and so it doesn't make sense to fill server logs with + * stack traces for these scenarios. + */ +public class SuppressingSslExceptionHandler extends ChannelHandlerAdapter { + private static final Logger logger = LoggerFactory.getLogger(SuppressingSslExceptionHandler.class); + + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + if (handshakeException(cause) + || sslRecordException(cause) + || decoderSslRecordException(cause)) { + try { + logger.info("Exception while processing SSL scrape request from {}: {}", remotePeer(ctx), cause.getMessage()); + logger.debug("Exception while processing SSL scrape request.", cause); + } finally { + ReferenceCountUtil.release(cause); + } + } else { + ctx.fireExceptionCaught(cause); + } + } + + private SocketAddress remotePeer(final ChannelHandlerContext ctx) { + if (ctx.channel() == null) { + return null; + } + return ctx.channel().remoteAddress(); + } + + private boolean handshakeException(final Throwable cause) { + return cause instanceof DecoderException + && cause.getCause() instanceof SSLHandshakeException; + } + + private boolean sslRecordException(final Throwable cause) { + return cause instanceof NotSslRecordException; + } + + private boolean decoderSslRecordException(final Throwable cause) { + return cause instanceof DecoderException + && cause.getCause() instanceof NotSslRecordException; + } +} diff --git a/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/UnexpectedSslExceptionHandler.java b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/UnexpectedSslExceptionHandler.java new file mode 100644 index 0000000..1f68d79 --- /dev/null +++ b/common/src/main/java/com/zegelin/cassandra/exporter/netty/ssl/UnexpectedSslExceptionHandler.java @@ -0,0 +1,38 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import io.netty.channel.ChannelHandlerAdapter; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.DecoderException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLException; + +public class UnexpectedSslExceptionHandler extends ChannelHandlerAdapter { + private static final Logger logger = LoggerFactory.getLogger(UnexpectedSslExceptionHandler.class); + + private final ReloadWatcher reloadWatcher; + + UnexpectedSslExceptionHandler(final ReloadWatcher reloadWatcher) { + this.reloadWatcher = reloadWatcher; + } + + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + try { + if (unexpectedMessage(cause)) { + logger.warn(cause.getMessage()); + // This may indicate that we're currently using invalid combo of key & cert + reloadWatcher.forceReload(); + } + } finally { + ctx.fireExceptionCaught(cause); + } + } + + private boolean unexpectedMessage(final Throwable cause) { + return cause instanceof DecoderException + && cause.getCause() instanceof SSLException + && cause.getCause().getMessage().contains("unexpected_message"); + } +} diff --git a/common/src/main/java/com/zegelin/netty/Floats.java b/common/src/main/java/com/zegelin/netty/Floats.java index 11ca501..2a4cb80 100644 --- a/common/src/main/java/com/zegelin/netty/Floats.java +++ b/common/src/main/java/com/zegelin/netty/Floats.java @@ -4,16 +4,27 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; +import java.nio.ByteBuffer; + +import static java.nio.charset.StandardCharsets.US_ASCII; + public final class Floats { public static boolean useFastFloat = true; private Floats() {} - public static void writeFloatString(final ByteBuf buffer, final float f) { + public static int writeFloatString(final ByteBuf buffer, final float f) { + return ByteBufUtil.writeAscii(buffer, Float.toString(f)); + } + + public static int writeFloatString(final ByteBuffer buffer, final float f) { if (useFastFloat) { - RyuFloat.floatToString(buffer, f); + return RyuFloat.floatToString(buffer, f); } else { - ByteBufUtil.writeAscii(buffer, Float.toString(f)); + byte[] byteBuffer = Float.toString(f).getBytes(US_ASCII); + int size = byteBuffer.length; + buffer.put(byteBuffer); + return size; } } } diff --git a/common/src/main/java/com/zegelin/prometheus/domain/Interval.java b/common/src/main/java/com/zegelin/prometheus/domain/Interval.java index 1394ded..ec9b191 100644 --- a/common/src/main/java/com/zegelin/prometheus/domain/Interval.java +++ b/common/src/main/java/com/zegelin/prometheus/domain/Interval.java @@ -1,13 +1,13 @@ package com.zegelin.prometheus.domain; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.zegelin.function.FloatFloatFunction; +import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; /* A Summary quanitle or Histogram bucket and associated value. @@ -23,6 +23,14 @@ public static class Quantile { public static final Set STANDARD_PERCENTILES = ImmutableSet.of(P_50, P_75, P_95, P_98, P_99, P_99_9); public static final Quantile POSITIVE_INFINITY = q(Float.POSITIVE_INFINITY); + public static final Map ALL_PERCENTILES = new ImmutableMap.Builder() + .put("P_50",P_50) + .put("P_75",P_75) + .put("P_95",P_95) + .put("P_98",P_98) + .put("P_99",P_99) + .put("P_99_9",P_99_9) + .build(); public final float value; diff --git a/common/src/main/java/com/zegelin/prometheus/domain/Labels.java b/common/src/main/java/com/zegelin/prometheus/domain/Labels.java index dffa8ba..6231f16 100644 --- a/common/src/main/java/com/zegelin/prometheus/domain/Labels.java +++ b/common/src/main/java/com/zegelin/prometheus/domain/Labels.java @@ -2,7 +2,7 @@ import com.google.common.collect.ForwardingMap; import com.google.common.collect.ImmutableMap; -import com.zegelin.prometheus.exposition.json.JsonFormatChunkedInput; +import com.zegelin.prometheus.exposition.json.JsonFormatExposition; import com.zegelin.prometheus.exposition.text.TextFormatLabels; import io.netty.buffer.ByteBuf; @@ -47,7 +47,7 @@ public ByteBuf asPlainTextFormatUTF8EncodedByteBuf() { public ByteBuf asJSONFormatUTF8EncodedByteBuf() { if (jsonFormatUTF8EncodedByteBuf == null) { - this.jsonFormatUTF8EncodedByteBuf = JsonFormatChunkedInput.formatLabels(labels); + this.jsonFormatUTF8EncodedByteBuf = JsonFormatExposition.formatLabels(labels); } return jsonFormatUTF8EncodedByteBuf; @@ -55,9 +55,22 @@ public ByteBuf asJSONFormatUTF8EncodedByteBuf() { @Override protected void finalize() throws Throwable { - this.plainTextFormatUTF8EncodedByteBuf.release(); - this.jsonFormatUTF8EncodedByteBuf.release(); + try { + maybeRelease(); + } finally { + super.finalize(); + } + } - super.finalize(); + private void maybeRelease() { + if (this.plainTextFormatUTF8EncodedByteBuf != null) { + this.plainTextFormatUTF8EncodedByteBuf.release(); + this.plainTextFormatUTF8EncodedByteBuf = null; + } + + if (this.jsonFormatUTF8EncodedByteBuf != null) { + this.jsonFormatUTF8EncodedByteBuf.release(); + this.jsonFormatUTF8EncodedByteBuf = null; + } } } diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/ExpositionSink.java b/common/src/main/java/com/zegelin/prometheus/exposition/ExpositionSink.java new file mode 100644 index 0000000..f7f7476 --- /dev/null +++ b/common/src/main/java/com/zegelin/prometheus/exposition/ExpositionSink.java @@ -0,0 +1,19 @@ +package com.zegelin.prometheus.exposition; + +import java.nio.ByteBuffer; + +public interface ExpositionSink { + void writeByte(int asciiChar); + + void writeBytes(ByteBuffer nioBuffer); + + void writeAscii(String asciiString); + + void writeUtf8(String utf8String); + + void writeFloat(float value); + + T getBuffer(); + + int getIngestedByteCount(); +} diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/FormattedByteChannel.java b/common/src/main/java/com/zegelin/prometheus/exposition/FormattedByteChannel.java new file mode 100644 index 0000000..0d68e27 --- /dev/null +++ b/common/src/main/java/com/zegelin/prometheus/exposition/FormattedByteChannel.java @@ -0,0 +1,38 @@ +package com.zegelin.prometheus.exposition; + +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; + +public class FormattedByteChannel implements ReadableByteChannel { + public static final int MIN_CHUNK_SIZE = 1024 * 1024; + public static final int MAX_CHUNK_SIZE = MIN_CHUNK_SIZE * 5; + + private final FormattedExposition formattedExposition; + + public FormattedByteChannel(FormattedExposition formattedExposition) { + this.formattedExposition = formattedExposition; + } + + @Override + public int read(ByteBuffer dst) { + if (!isOpen()) { + return -1; + } + + final NioExpositionSink sink = new NioExpositionSink(dst); + while (sink.getIngestedByteCount() < MIN_CHUNK_SIZE && isOpen()) { + formattedExposition.nextSlice(sink); + } + + return sink.getIngestedByteCount(); + } + + @Override + public boolean isOpen() { + return !formattedExposition.isEndOfInput(); + } + + @Override + public void close() { + } +} diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/FormattedExposition.java b/common/src/main/java/com/zegelin/prometheus/exposition/FormattedExposition.java new file mode 100644 index 0000000..384f064 --- /dev/null +++ b/common/src/main/java/com/zegelin/prometheus/exposition/FormattedExposition.java @@ -0,0 +1,7 @@ +package com.zegelin.prometheus.exposition; + +public interface FormattedExposition { + void nextSlice(final ExpositionSink sink); + + boolean isEndOfInput(); +} diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/NettyExpositionSink.java b/common/src/main/java/com/zegelin/prometheus/exposition/NettyExpositionSink.java new file mode 100644 index 0000000..a4cbeef --- /dev/null +++ b/common/src/main/java/com/zegelin/prometheus/exposition/NettyExpositionSink.java @@ -0,0 +1,53 @@ +package com.zegelin.prometheus.exposition; + +import com.zegelin.netty.Floats; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; + +import java.nio.ByteBuffer; + +public class NettyExpositionSink implements ExpositionSink { + private int ingestedByteCount = 0; + private final ByteBuf buffer; + + public NettyExpositionSink(ByteBuf buffer) { + this.buffer = buffer; + } + + @Override + public void writeByte(int asciiChar) { + ingestedByteCount++; + buffer.writeByte(asciiChar); + } + + @Override + public void writeBytes(ByteBuffer nioBuffer) { + ingestedByteCount += nioBuffer.remaining(); + buffer.writeBytes(nioBuffer); + } + + @Override + public void writeAscii(String asciiString) { + ingestedByteCount += ByteBufUtil.writeAscii(buffer, asciiString); + } + + @Override + public void writeUtf8(String utf8String) { + ingestedByteCount += ByteBufUtil.writeUtf8(buffer, utf8String); + } + + @Override + public void writeFloat(float value) { + ingestedByteCount += Floats.writeFloatString(buffer, value); + } + + @Override + public ByteBuf getBuffer() { + return buffer; + } + + @Override + public int getIngestedByteCount() { + return ingestedByteCount; + } +} diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/NioExpositionSink.java b/common/src/main/java/com/zegelin/prometheus/exposition/NioExpositionSink.java new file mode 100644 index 0000000..c596d93 --- /dev/null +++ b/common/src/main/java/com/zegelin/prometheus/exposition/NioExpositionSink.java @@ -0,0 +1,58 @@ +package com.zegelin.prometheus.exposition; + +import com.zegelin.netty.Floats; + +import java.nio.ByteBuffer; + +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.nio.charset.StandardCharsets.UTF_8; + +class NioExpositionSink implements ExpositionSink { + private int ingestedByteCount = 0; + private final ByteBuffer buffer; + + NioExpositionSink(ByteBuffer buffer) { + this.buffer = buffer; + } + + @Override + public void writeByte(int asciiChar) { + ingestedByteCount++; + buffer.put((byte) asciiChar); + } + + @Override + public void writeBytes(ByteBuffer nioBuffer) { + ingestedByteCount += nioBuffer.remaining(); + buffer.put(nioBuffer); + } + + @Override + public void writeAscii(String asciiString) { + byte[] byteBuffer = asciiString.getBytes(US_ASCII); + ingestedByteCount += byteBuffer.length; + buffer.put(byteBuffer); + } + + @Override + public void writeUtf8(String utf8String) { + byte[] byteBuffer = utf8String.getBytes(UTF_8); + ingestedByteCount += byteBuffer.length; + buffer.put(byteBuffer); + } + + @Override + public void writeFloat(float value) { + ingestedByteCount += Floats.writeFloatString(buffer, value); + } + + @Override + public ByteBuffer getBuffer() { + return buffer; + } + + @Override + public int getIngestedByteCount() { + return ingestedByteCount; + } +} diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFormatChunkedInput.java b/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFormatExposition.java similarity index 77% rename from common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFormatChunkedInput.java rename to common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFormatExposition.java index 0f5cef9..ba731f6 100644 --- a/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFormatChunkedInput.java +++ b/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFormatExposition.java @@ -4,10 +4,11 @@ import com.google.common.escape.CharEscaperBuilder; import com.google.common.escape.Escaper; import com.zegelin.prometheus.domain.*; +import com.zegelin.prometheus.exposition.ExpositionSink; +import com.zegelin.prometheus.exposition.FormattedExposition; +import com.zegelin.prometheus.exposition.NettyExpositionSink; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.stream.ChunkedInput; import java.time.Instant; import java.util.Iterator; @@ -20,7 +21,7 @@ import static com.zegelin.prometheus.exposition.json.JsonFragment.*; -public class JsonFormatChunkedInput implements ChunkedInput { +public class JsonFormatExposition implements FormattedExposition { private enum State { HEADER, METRIC_FAMILY, @@ -36,7 +37,7 @@ private enum MetricFamilyType { SUMMARY, UNTYPED; - void write(final ByteBuf buffer) { + void write(final ExpositionSink buffer) { JsonFragment.writeAsciiString(buffer, name()); } } @@ -68,7 +69,7 @@ void write(final ByteBuf buffer) { private final Stopwatch stopwatch = Stopwatch.createUnstarted(); - public JsonFormatChunkedInput(final Stream metricFamilies, final Instant timestamp, final Labels globalLabels, final boolean includeHelp) { + public JsonFormatExposition(final Stream metricFamilies, final Instant timestamp, final Labels globalLabels, final boolean includeHelp) { this.metricFamilyIterator = metricFamilies.iterator(); this.timestamp = timestamp; this.globalLabels = globalLabels; @@ -76,17 +77,12 @@ public JsonFormatChunkedInput(final Stream metricFamilies, final I } @Override - public boolean isEndOfInput() throws Exception { + public boolean isEndOfInput() { return state == State.EOF; } - @Override - public void close() throws Exception { - } - - public static ByteBuf formatLabels(final Map labels) { - final ByteBuf buffer = Unpooled.buffer(); + final NettyExpositionSink buffer = new NettyExpositionSink(Unpooled.buffer()); JsonToken.OBJECT_START.write(buffer); @@ -105,16 +101,16 @@ public static ByteBuf formatLabels(final Map labels) { JsonToken.OBJECT_END.write(buffer); - return buffer; + return buffer.getBuffer(); } class MetricFamilyWriter { - private final Consumer headerWriter; - private final Function metricWriter; + private final Consumer> headerWriter; + private final Function, Boolean> metricWriter; - class HeaderVisitor implements MetricFamilyVisitor> { - private void writeFamilyHeader(final MetricFamily metricFamily, final ByteBuf buffer, final MetricFamilyType type) { + class HeaderVisitor implements MetricFamilyVisitor>> { + private void writeFamilyHeader(final MetricFamily metricFamily, final ExpositionSink buffer, final MetricFamilyType type) { writeObjectKey(buffer, metricFamily.name); JsonToken.OBJECT_START.write(buffer); @@ -135,38 +131,38 @@ private void writeFamilyHeader(final MetricFamily metricFamily, final ByteBuf JsonToken.ARRAY_START.write(buffer); } - private Consumer forType(final MetricFamily metricFamily, final MetricFamilyType type) { + private Consumer> forType(final MetricFamily metricFamily, final MetricFamilyType type) { return (buffer) -> writeFamilyHeader(metricFamily, buffer, type); } @Override - public Consumer visit(final CounterMetricFamily metricFamily) { + public Consumer> visit(final CounterMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.COUNTER); } @Override - public Consumer visit(final GaugeMetricFamily metricFamily) { + public Consumer> visit(final GaugeMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.GAUGE); } @Override - public Consumer visit(final SummaryMetricFamily metricFamily) { + public Consumer> visit(final SummaryMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.SUMMARY); } @Override - public Consumer visit(final HistogramMetricFamily metricFamily) { + public Consumer> visit(final HistogramMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.HISTOGRAM); } @Override - public Consumer visit(final UntypedMetricFamily metricFamily) { + public Consumer> visit(final UntypedMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.UNTYPED); } } - class MetricVisitor implements MetricFamilyVisitor> { - private Function metricWriter(final MetricFamily metricFamily, final BiConsumer valueWriter) { + class MetricVisitor implements MetricFamilyVisitor, Boolean>> { + private Function, Boolean> metricWriter(final MetricFamily metricFamily, final BiConsumer> valueWriter) { final Iterator metricIterator = metricFamily.metrics().iterator(); return (buffer) -> { @@ -176,7 +172,7 @@ private Function metricWriter(final MetricF JsonToken.OBJECT_START.write(buffer); writeObjectKey(buffer, "labels"); if (metric.labels != null) { - buffer.writeBytes(metric.labels.asJSONFormatUTF8EncodedByteBuf().slice()); + buffer.writeBytes(metric.labels.asJSONFormatUTF8EncodedByteBuf().nioBuffer()); } else { writeNull(buffer); } @@ -200,20 +196,20 @@ private Function metricWriter(final MetricF } @Override - public Function visit(final CounterMetricFamily metricFamily) { + public Function, Boolean> visit(final CounterMetricFamily metricFamily) { return metricWriter(metricFamily, (counter, buffer) -> { writeFloat(buffer, counter.value); }); } @Override - public Function visit(final GaugeMetricFamily metricFamily) { + public Function, Boolean> visit(final GaugeMetricFamily metricFamily) { return metricWriter(metricFamily, (gauge, buffer) -> { writeFloat(buffer, gauge.value); }); } - private void writeSumAndCount(final ByteBuf buffer, final float sum, final float count) { + private void writeSumAndCount(final ExpositionSink buffer, final float sum, final float count) { writeObjectKey(buffer, "sum"); writeFloat(buffer, sum); @@ -223,7 +219,7 @@ private void writeSumAndCount(final ByteBuf buffer, final float sum, final float writeFloat(buffer, count); } - private void writeIntervals(final ByteBuf buffer, final Iterable intervals) { + private void writeIntervals(final ExpositionSink buffer, final Iterable intervals) { JsonToken.OBJECT_START.write(buffer); final Iterator iterator = intervals.iterator(); @@ -243,7 +239,7 @@ private void writeIntervals(final ByteBuf buffer, final Iterable inter } @Override - public Function visit(final SummaryMetricFamily metricFamily) { + public Function, Boolean> visit(final SummaryMetricFamily metricFamily) { return metricWriter(metricFamily, (summary, buffer) -> { JsonToken.OBJECT_START.write(buffer); @@ -259,7 +255,7 @@ public Function visit(final SummaryMetricFamily metricFamily) } @Override - public Function visit(final HistogramMetricFamily metricFamily) { + public Function, Boolean> visit(final HistogramMetricFamily metricFamily) { return metricWriter(metricFamily, (histogram, buffer) -> { JsonToken.OBJECT_START.write(buffer); @@ -275,9 +271,9 @@ public Function visit(final HistogramMetricFamily metricFamily } @Override - public Function visit(final UntypedMetricFamily metricFamily) { + public Function, Boolean> visit(final UntypedMetricFamily metricFamily) { return metricWriter(metricFamily, (untyped, buffer) -> { - writeFloat(buffer, untyped.value); + buffer.writeFloat(untyped.value); }); } } @@ -287,21 +283,21 @@ public Function visit(final UntypedMetricFamily metricFamily) this.metricWriter = metricFamily.accept(new MetricVisitor()); } - void writeFamilyHeader(final ByteBuf buffer) { + void writeFamilyHeader(final ExpositionSink buffer) { this.headerWriter.accept(buffer); } - void writeFamilyFooter(final ByteBuf buffer) { + void writeFamilyFooter(final ExpositionSink buffer) { JsonToken.ARRAY_END.write(buffer); JsonToken.OBJECT_END.write(buffer); } - boolean writeMetric(final ByteBuf buffer) { + boolean writeMetric(final ExpositionSink buffer) { return this.metricWriter.apply(buffer); } } - private void writeStatistics(final ByteBuf chunkBuffer) { + private void writeStatistics(final ExpositionSink chunkBuffer) { JsonToken.OBJECT_START.write(chunkBuffer); writeObjectKey(chunkBuffer, "expositionTime"); @@ -320,7 +316,8 @@ private void writeStatistics(final ByteBuf chunkBuffer) { JsonToken.OBJECT_END.write(chunkBuffer); } - private void nextSlice(final ByteBuf chunkBuffer) { + @Override + public void nextSlice(final ExpositionSink chunkBuffer) { switch (state) { case HEADER: stopwatch.start(); @@ -333,7 +330,7 @@ private void nextSlice(final ByteBuf chunkBuffer) { JsonToken.COMMA.write(chunkBuffer); writeObjectKey(chunkBuffer, "globalLabels"); - chunkBuffer.writeBytes(globalLabels.asJSONFormatUTF8EncodedByteBuf().slice()); + chunkBuffer.writeBytes(globalLabels.asJSONFormatUTF8EncodedByteBuf().nioBuffer()); JsonToken.COMMA.write(chunkBuffer); @@ -398,22 +395,4 @@ private void nextSlice(final ByteBuf chunkBuffer) { throw new IllegalStateException(); } } - - @Override - public ByteBuf readChunk(final ChannelHandlerContext ctx) throws Exception { - final ByteBuf chunkBuffer = ctx.alloc().buffer(1024 * 1024 * 5); - - // add slices till we hit the chunk size (or slightly over it), or hit EOF - while (chunkBuffer.readableBytes() < 1024 * 1024 && state != State.EOF) { - try { - nextSlice(chunkBuffer); - - } catch (final Exception e) { - chunkBuffer.release(); - throw e; - } - } - - return chunkBuffer; - } } diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFragment.java b/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFragment.java index 0ec3558..30f6bd2 100644 --- a/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFragment.java +++ b/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonFragment.java @@ -2,9 +2,7 @@ import com.google.common.escape.CharEscaperBuilder; import com.google.common.escape.Escaper; -import com.zegelin.netty.Floats; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; +import com.zegelin.prometheus.exposition.ExpositionSink; final class JsonFragment { private JsonFragment() {} @@ -19,42 +17,42 @@ private JsonFragment() {} .addEscape('\\', "\\\\") .toEscaper(); - static void writeNull(final ByteBuf buffer) { - ByteBufUtil.writeAscii(buffer, "null"); + static void writeNull(final ExpositionSink buffer) { + buffer.writeAscii("null"); } - static void writeAsciiString(final ByteBuf buffer, final String string) { + static void writeAsciiString(final ExpositionSink buffer, final String string) { JsonToken.DOUBLE_QUOTE.write(buffer); - ByteBufUtil.writeAscii(buffer, STRING_ESCAPER.escape(string)); + buffer.writeAscii(STRING_ESCAPER.escape(string)); JsonToken.DOUBLE_QUOTE.write(buffer); } - static void writeUtf8String(final ByteBuf buffer, final String string) { + static void writeUtf8String(final ExpositionSink buffer, final String string) { JsonToken.DOUBLE_QUOTE.write(buffer); - ByteBufUtil.writeUtf8(buffer, STRING_ESCAPER.escape(string)); + buffer.writeUtf8(STRING_ESCAPER.escape(string)); JsonToken.DOUBLE_QUOTE.write(buffer); } - static void writeObjectKey(final ByteBuf buffer, final String key) { - writeAsciiString(buffer, key); + static void writeObjectKey(final ExpositionSink buffer, final String key) { + buffer.writeAscii(key); JsonToken.COLON.write(buffer); } - static void writeFloat(final ByteBuf buffer, final float f) { + static void writeFloat(final ExpositionSink buffer, final float f) { if (Float.isNaN(f)) { - ByteBufUtil.writeAscii(buffer, "\"NaN\""); + buffer.writeAscii("\"NaN\""); return; } if (Float.isInfinite(f)) { - ByteBufUtil.writeAscii(buffer, (f < 0 ? "\"-Inf\"" : "\"+Inf\"")); + buffer.writeAscii((f < 0 ? "\"-Inf\"" : "\"+Inf\"")); return; } - Floats.writeFloatString(buffer, f); + buffer.writeFloat(f); } - static void writeLong(final ByteBuf buffer, final long l) { - ByteBufUtil.writeAscii(buffer, Long.toString(l)); + static void writeLong(final ExpositionSink buffer, final long l) { + buffer.writeAscii(Long.toString(l)); } } diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonToken.java b/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonToken.java index e3ebcb6..df01210 100644 --- a/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonToken.java +++ b/common/src/main/java/com/zegelin/prometheus/exposition/json/JsonToken.java @@ -1,6 +1,6 @@ package com.zegelin.prometheus.exposition.json; -import io.netty.buffer.ByteBuf; +import com.zegelin.prometheus.exposition.ExpositionSink; enum JsonToken { OBJECT_START('{'), @@ -17,7 +17,7 @@ enum JsonToken { this.encoded = (byte) c; } - void write(final ByteBuf buffer) { + void write(final ExpositionSink buffer) { buffer.writeByte(encoded); } } diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatChunkedInput.java b/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatExposition.java similarity index 62% rename from common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatChunkedInput.java rename to common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatExposition.java index eb624be..4c53c6f 100644 --- a/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatChunkedInput.java +++ b/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatExposition.java @@ -1,23 +1,17 @@ package com.zegelin.prometheus.exposition.text; import com.google.common.base.Stopwatch; -import com.google.common.escape.CharEscaperBuilder; -import com.google.common.escape.Escaper; import com.zegelin.netty.Resources; import com.zegelin.prometheus.domain.*; +import com.zegelin.prometheus.exposition.ExpositionSink; +import com.zegelin.prometheus.exposition.FormattedExposition; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.stream.ChunkedInput; import java.time.Instant; import java.util.Iterator; -import java.util.Map; import java.util.stream.Stream; -public class TextFormatChunkedInput implements ChunkedInput { +public class TextFormatExposition implements FormattedExposition { private enum State { BANNER, METRIC_FAMILY, @@ -26,7 +20,7 @@ private enum State { EOF } - private static final ByteBuf BANNER = Resources.asByteBuf(TextFormatChunkedInput.class, "banner.txt"); + private static final ByteBuf BANNER = Resources.asByteBuf(TextFormatExposition.class, "banner.txt"); private final Iterator metricFamiliesIterator; @@ -43,7 +37,7 @@ private enum State { private final Stopwatch stopwatch = Stopwatch.createUnstarted(); - public TextFormatChunkedInput(final Stream metricFamilies, final Instant timestamp, final Labels globalLabels, final boolean includeHelp) { + public TextFormatExposition(final Stream metricFamilies, final Instant timestamp, final Labels globalLabels, final boolean includeHelp) { this.metricFamiliesIterator = metricFamilies.iterator(); this.timestamp = timestamp; this.globalLabels = globalLabels; @@ -56,15 +50,12 @@ public boolean isEndOfInput() { } @Override - public void close() {} - - - private void nextSlice(final ByteBuf chunkBuffer) { + public void nextSlice(final ExpositionSink chunkBuffer) { switch (state) { case BANNER: stopwatch.start(); - chunkBuffer.writeBytes(BANNER.slice()); + chunkBuffer.writeBytes(BANNER.nioBuffer()); state = State.METRIC_FAMILY; return; @@ -101,8 +92,8 @@ private void nextSlice(final ByteBuf chunkBuffer) { case FOOTER: stopwatch.stop(); - ByteBufUtil.writeAscii(chunkBuffer, "\n\n# Thanks and come again!\n\n"); - ByteBufUtil.writeAscii(chunkBuffer, String.format("# Wrote %s metrics for %s metric families in %s\n", metricCount, metricFamilyCount, stopwatch.toString())); + chunkBuffer.writeAscii("\n\n# Thanks and come again!\n\n"); + chunkBuffer.writeAscii(String.format("# Wrote %s metrics for %s metric families in %s\n", metricCount, metricFamilyCount, stopwatch.toString())); state = State.EOF; return; @@ -114,23 +105,4 @@ private void nextSlice(final ByteBuf chunkBuffer) { throw new IllegalStateException(); } } - - @Override - public ByteBuf readChunk(final ChannelHandlerContext ctx) { - final ByteBuf chunkBuffer = ctx.alloc().buffer(1024 * 1024 * 5); - - // add slices till we hit the chunk size (or slightly over it), or hit EOF - while (chunkBuffer.readableBytes() < 1024 * 1024 && state != State.EOF) { - try { - nextSlice(chunkBuffer); - - } catch (final Exception e) { - chunkBuffer.release(); - - throw e; - } - } - - return chunkBuffer; - } } diff --git a/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatMetricFamilyWriter.java b/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatMetricFamilyWriter.java index d2976f3..e0209f7 100644 --- a/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatMetricFamilyWriter.java +++ b/common/src/main/java/com/zegelin/prometheus/exposition/text/TextFormatMetricFamilyWriter.java @@ -2,10 +2,8 @@ import com.google.common.escape.CharEscaperBuilder; import com.google.common.escape.Escaper; -import com.zegelin.netty.Floats; import com.zegelin.prometheus.domain.*; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; +import com.zegelin.prometheus.exposition.ExpositionSink; import java.time.Instant; import java.util.Iterator; @@ -27,8 +25,8 @@ private enum MetricFamilyType { encoded = this.name().toLowerCase(); } - void write(final ByteBuf buffer) { - ByteBufUtil.writeAscii(buffer, encoded); + void write(final ExpositionSink buffer) { + buffer.writeAscii(encoded); } } @@ -41,8 +39,8 @@ void write(final ByteBuf buffer) { private final Labels globalLabels; private final boolean includeHelp; - private final Consumer headerWriter; - private final Function metricWriter; + private final Consumer> headerWriter; + private final Function, Boolean> metricWriter; TextFormatMetricFamilyWriter(final Instant timestamp, final Labels globalLabels, final boolean includeHelp, final MetricFamily metricFamily) { this.timestamp = " " + timestamp.toEpochMilli(); @@ -53,20 +51,20 @@ void write(final ByteBuf buffer) { this.metricWriter = metricFamily.accept(new MetricVisitor()); } - class HeaderVisitor implements MetricFamilyVisitor> { - private void writeFamilyHeader(final MetricFamily metricFamily, final ByteBuf buffer, final MetricFamilyType type) { + class HeaderVisitor implements MetricFamilyVisitor>> { + private void writeFamilyHeader(final MetricFamily metricFamily, final ExpositionSink buffer, final MetricFamilyType type) { // # HELP \n if (includeHelp && metricFamily.help != null) { - ByteBufUtil.writeAscii(buffer, "# HELP "); - ByteBufUtil.writeAscii(buffer, metricFamily.name); + buffer.writeAscii("# HELP "); + buffer.writeAscii(metricFamily.name); buffer.writeByte(' '); - ByteBufUtil.writeUtf8(buffer, HELP_STRING_ESCAPER.escape(metricFamily.help)); + buffer.writeUtf8(HELP_STRING_ESCAPER.escape(metricFamily.help)); buffer.writeByte('\n'); } // # TYPE \n - ByteBufUtil.writeAscii(buffer, "# TYPE "); - ByteBufUtil.writeAscii(buffer, metricFamily.name); + buffer.writeAscii("# TYPE "); + buffer.writeAscii(metricFamily.name); buffer.writeByte(' '); type.write(buffer); buffer.writeByte('\n'); @@ -74,46 +72,46 @@ private void writeFamilyHeader(final MetricFamily metricFamily, final ByteBuf bu - private Consumer forType(final MetricFamily metricFamily, final MetricFamilyType type) { + private Consumer> forType(final MetricFamily metricFamily, final MetricFamilyType type) { return (buffer) -> writeFamilyHeader(metricFamily, buffer, type); } @Override - public Consumer visit(final CounterMetricFamily metricFamily) { + public Consumer> visit(final CounterMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.COUNTER); } @Override - public Consumer visit(final GaugeMetricFamily metricFamily) { + public Consumer> visit(final GaugeMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.GAUGE); } @Override - public Consumer visit(final SummaryMetricFamily metricFamily) { + public Consumer> visit(final SummaryMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.SUMMARY); } @Override - public Consumer visit(final HistogramMetricFamily metricFamily) { + public Consumer> visit(final HistogramMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.HISTOGRAM); } @Override - public Consumer visit(final UntypedMetricFamily metricFamily) { + public Consumer> visit(final UntypedMetricFamily metricFamily) { return forType(metricFamily, MetricFamilyType.UNTYPED); } } - class MetricVisitor implements MetricFamilyVisitor> { - private void writeLabels(final ByteBuf buffer, final Labels labels, final boolean commaPrefix) { + class MetricVisitor implements MetricFamilyVisitor, Boolean>> { + private void writeLabels(final ExpositionSink buffer, final Labels labels, final boolean commaPrefix) { if (commaPrefix) { buffer.writeByte(','); } - buffer.writeBytes(labels.asPlainTextFormatUTF8EncodedByteBuf().slice()); + buffer.writeBytes(labels.asPlainTextFormatUTF8EncodedByteBuf().nioBuffer()); } - private void writeLabelSets(final ByteBuf buffer, final Labels... labelSets) { + private void writeLabelSets(final ExpositionSink buffer, final Labels... labelSets) { buffer.writeByte('{'); boolean needsComma = false; @@ -134,22 +132,22 @@ private void writeLabelSets(final ByteBuf buffer, final Labels... labelSets) { buffer.writeByte('}'); } - private void writeMetric(final ByteBuf buffer, final MetricFamily metricFamily, final String suffix, final float value, final Labels... labelSets) { - ByteBufUtil.writeAscii(buffer, metricFamily.name); + private void writeMetric(final ExpositionSink buffer, final MetricFamily metricFamily, final String suffix, final float value, final Labels... labelSets) { + buffer.writeAscii(metricFamily.name); if (suffix != null) { - ByteBufUtil.writeAscii(buffer, suffix); + buffer.writeAscii(suffix); } writeLabelSets(buffer, labelSets); buffer.writeByte(' '); - Floats.writeFloatString(buffer, value); - ByteBufUtil.writeAscii(buffer, timestamp); // timestamp already has a leading space + buffer.writeFloat(value); + buffer.writeAscii(timestamp); // timestamp already has a leading space buffer.writeByte('\n'); } - private Function metricWriter(final MetricFamily metricFamily, final BiConsumer writer) { + private Function, Boolean> metricWriter(final MetricFamily metricFamily, final BiConsumer> writer) { final Iterator metricIterator = metricFamily.metrics().iterator(); return (buffer) -> { @@ -164,21 +162,21 @@ private Function metricWriter(final MetricF } @Override - public Function visit(final CounterMetricFamily metricFamily) { + public Function, Boolean> visit(final CounterMetricFamily metricFamily) { return metricWriter(metricFamily, (counter, buffer) -> { writeMetric(buffer, metricFamily, null, counter.value, counter.labels); }); } @Override - public Function visit(final GaugeMetricFamily metricFamily) { + public Function, Boolean> visit(final GaugeMetricFamily metricFamily) { return metricWriter(metricFamily, (gauge, buffer) -> { writeMetric(buffer, metricFamily, null, gauge.value, gauge.labels); }); } @Override - public Function visit(final SummaryMetricFamily metricFamily) { + public Function, Boolean> visit(final SummaryMetricFamily metricFamily) { return metricWriter(metricFamily, (summary, buffer) -> { writeMetric(buffer, metricFamily, "_sum", summary.sum, summary.labels); writeMetric(buffer, metricFamily, "_count", summary.count, summary.labels); @@ -190,7 +188,7 @@ public Function visit(final SummaryMetricFamily metricFamily) } @Override - public Function visit(final HistogramMetricFamily metricFamily) { + public Function, Boolean> visit(final HistogramMetricFamily metricFamily) { return metricWriter(metricFamily, (histogram, buffer) -> { writeMetric(buffer, metricFamily, "_sum", histogram.sum, histogram.labels); writeMetric(buffer, metricFamily, "_count", histogram.count, histogram.labels); @@ -204,7 +202,7 @@ public Function visit(final HistogramMetricFamily metricFamily } @Override - public Function visit(final UntypedMetricFamily metricFamily) { + public Function, Boolean> visit(final UntypedMetricFamily metricFamily) { return metricWriter(metricFamily, (untyped, buffer) -> { writeMetric(buffer, metricFamily, null, untyped.value, untyped.labels); }); @@ -216,7 +214,7 @@ public Function visit(final UntypedMetricFamily metricFamily) /*** * Write the header fields (TYPE, HELP) for the MetricFamily to the provided ByteBuf. */ - void writeFamilyHeader(final ByteBuf buffer) { + void writeFamilyHeader(final ExpositionSink buffer) { this.headerWriter.accept(buffer); } @@ -225,7 +223,7 @@ void writeFamilyHeader(final ByteBuf buffer) { * * @return true if there are more Metrics to write, false if not. */ - boolean writeMetric(final ByteBuf buffer) { + boolean writeMetric(final ExpositionSink buffer) { return this.metricWriter.apply(buffer); } } diff --git a/common/src/main/java/info/adams/ryu/RyuFloat.java b/common/src/main/java/info/adams/ryu/RyuFloat.java index 167b7a8..a67f5a4 100644 --- a/common/src/main/java/info/adams/ryu/RyuFloat.java +++ b/common/src/main/java/info/adams/ryu/RyuFloat.java @@ -15,11 +15,12 @@ // limitations under the License. -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.ByteBufUtil; +import org.apache.commons.codec.binary.Hex; import java.math.BigInteger; +import java.nio.ByteBuffer; + +import static java.nio.charset.StandardCharsets.US_ASCII; /** * An implementation of Ryu for float. @@ -90,43 +91,38 @@ public final class RyuFloat { public static void main(String[] args) { DEBUG = true; float f = 0.33007812f; - final ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer(); + final ByteBuffer buffer = ByteBuffer.allocate(10); floatToString(buffer, f, RoundingMode.ROUND_EVEN); - System.out.println(ByteBufUtil.hexDump(buffer) + " " + f); + System.out.println(Hex.encodeHexString(buffer.array()) + " " + f); } - public static void floatToString(final ByteBuf buffer, float value) { - floatToString(buffer, value, RoundingMode.ROUND_EVEN); + public static int floatToString(final ByteBuffer buffer, float value) { + return floatToString(buffer, value, RoundingMode.ROUND_EVEN); } - public static void floatToString(final ByteBuf buffer, float value, RoundingMode roundingMode) { + public static int floatToString(final ByteBuffer buffer, float value, RoundingMode roundingMode) { // Step 1: Decode the floating point number, and unify normalized and subnormal cases. // First, handle all the trivial cases. if (Float.isNaN(value)) { - ByteBufUtil.writeAscii(buffer, "NaN"); - return; + return writeAscii(buffer, "NaN"); } if (value == Float.POSITIVE_INFINITY) { - ByteBufUtil.writeAscii(buffer, "Infinity"); - return; + return writeAscii(buffer, "Infinity"); } if (value == Float.NEGATIVE_INFINITY) { - ByteBufUtil.writeAscii(buffer, "-Infinity"); - return; + return writeAscii(buffer, "-Infinity"); } int bits = Float.floatToIntBits(value); if (bits == 0) { - ByteBufUtil.writeAscii(buffer, "0.0"); - return; + return writeAscii(buffer, "0.0"); } if (bits == 0x80000000) { - ByteBufUtil.writeAscii(buffer, "-0.0"); - return; + return writeAscii(buffer, "-0.0"); } // Otherwise extract the mantissa and exponent bits and run the full algorithm. @@ -386,7 +382,14 @@ public static void floatToString(final ByteBuf buffer, float value, RoundingMode } } - buffer.writeBytes(result, 0, index); + buffer.put(result, 0, index); + return index; + } + + private static int writeAscii(final ByteBuffer buffer, String asciiString) { + byte[] byteBuffer = asciiString.getBytes(US_ASCII); + buffer.put(byteBuffer); + return byteBuffer.length; } private static int pow5bits(int e) { diff --git a/common/src/test/java/com/zegelin/cassandra/exporter/netty/TestSuppressingExceptionHandler.java b/common/src/test/java/com/zegelin/cassandra/exporter/netty/TestSuppressingExceptionHandler.java new file mode 100644 index 0000000..d15561d --- /dev/null +++ b/common/src/test/java/com/zegelin/cassandra/exporter/netty/TestSuppressingExceptionHandler.java @@ -0,0 +1,44 @@ +package com.zegelin.cassandra.exporter.netty; + +import io.netty.channel.ChannelHandlerContext; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.IOException; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class TestSuppressingExceptionHandler { + @Mock + private ChannelHandlerContext context; + + private SuppressingExceptionHandler handler; + + @BeforeMethod + public void before() { + MockitoAnnotations.initMocks(this); + handler = new SuppressingExceptionHandler(); + } + + @Test + public void testBrokenPipeIoExceptionIsMuted() throws Exception { + handler.exceptionCaught(context, new IOException("Broken pipe")); + verify(context, times(0)).fireExceptionCaught(any()); + } + + @Test + public void testOtherIoExceptionIsPropagated() throws Exception { + handler.exceptionCaught(context, new IOException("Other")); + verify(context, times(1)).fireExceptionCaught(any()); + } + + @Test + public void testOtherExceptionIsPropagated() throws Exception { + handler.exceptionCaught(context, new NullPointerException()); + verify(context, times(1)).fireExceptionCaught(any()); + } +} diff --git a/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestReloadWatcher.java b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestReloadWatcher.java new file mode 100644 index 0000000..fcba7de --- /dev/null +++ b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestReloadWatcher.java @@ -0,0 +1,107 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TestReloadWatcher { + public static final long INITIAL_FILE_AGE_MILLIS = 5000; + public static final long SLEEP_MILLIS = 1001; + + private HttpServerOptions options; + private ReloadWatcher watcher; + + @BeforeMethod + public void before() throws IOException { + options = new HttpServerOptions(); + options.sslReloadIntervalInSeconds = 1; + + options.sslServerKeyFile = givenTemporaryFile("server-key"); + options.sslServerCertificateFile = givenTemporaryFile("server-cert"); + options.sslTrustedCertificateFile = givenTemporaryFile("trusted-cert"); + + options.sslServerKeyFile.setLastModified(System.currentTimeMillis() - INITIAL_FILE_AGE_MILLIS); + options.sslServerCertificateFile.setLastModified(System.currentTimeMillis() - INITIAL_FILE_AGE_MILLIS); + options.sslTrustedCertificateFile.setLastModified(System.currentTimeMillis() - INITIAL_FILE_AGE_MILLIS); + + watcher = new ReloadWatcher(options); + } + + @Test + public void testNoImmediateReload() { + options.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + + assertThat(watcher.needReload()).isFalse(); + } + + @Test + public void testNoReloadWhenFilesAreUntouched() throws InterruptedException { + Thread.sleep(SLEEP_MILLIS); + + assertThat(watcher.needReload()).isFalse(); + } + + @Test + public void testReloadOnceWhenFilesAreTouched() throws InterruptedException { + Thread.sleep(SLEEP_MILLIS); + + options.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + options.sslServerCertificateFile.setLastModified(System.currentTimeMillis()); + + Thread.sleep(SLEEP_MILLIS); + + assertThat(watcher.needReload()).isTrue(); + + Thread.sleep(SLEEP_MILLIS); + + assertThat(watcher.needReload()).isFalse(); + } + + // Verify that we reload certificates on next pass again in case files are modified + // just as we check for reload. + @Test + public void testReloadAgainWhenFilesAreTouchedJustAfterReload() throws InterruptedException { + Thread.sleep(SLEEP_MILLIS); + + options.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + assertThat(watcher.needReload()).isTrue(); + options.sslServerCertificateFile.setLastModified(System.currentTimeMillis()); + + Thread.sleep(SLEEP_MILLIS); + + assertThat(watcher.needReload()).isTrue(); + } + + @Test + public void testReloadWhenForced() throws InterruptedException { + Thread.sleep(SLEEP_MILLIS); + + watcher.forceReload(); + + assertThat(watcher.needReload()).isTrue(); + } + + @Test + public void testNoReloadWhenDisabled() throws InterruptedException { + options.sslReloadIntervalInSeconds = 0; + watcher = new ReloadWatcher(options); + + Thread.sleep(SLEEP_MILLIS); + options.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + + assertThat(watcher.needReload()).isFalse(); + } + + private File givenTemporaryFile(String filename) throws IOException { + File file = File.createTempFile(filename, "tmp"); + Files.write(file.toPath(), "dummy".getBytes()); + + return file; + } +} diff --git a/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSslContextFactory.java b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSslContextFactory.java new file mode 100644 index 0000000..95a08ca --- /dev/null +++ b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSslContextFactory.java @@ -0,0 +1,211 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import io.netty.buffer.ByteBufAllocator; +import io.netty.handler.ssl.OpenSslEngine; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import sun.security.ssl.SSLEngineImpl; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.security.cert.CertificateException; +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; + +public class TestSslContextFactory { + private HttpServerOptions serverOptions; + private SelfSignedCertificate selfSignedCertificate; + private SslContextFactory contextFactory; + + @BeforeMethod + public void before() throws CertificateException { + serverOptions = new HttpServerOptions(); + selfSignedCertificate = new SelfSignedCertificate(); + contextFactory = new SslContextFactory(serverOptions); + } + + @Test + public void testCreateDiscoveredSslContext() { + serverOptions.sslImplementation = SslImplementation.DISCOVER; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT)).isInstanceOf(OpenSslEngine.class); + } + + @Test + public void testCreateJdkSslContext() { + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT)).isInstanceOf(SSLEngineImpl.class); + } + + @Test + public void testCreateOpenSslContext() { + serverOptions.sslImplementation = SslImplementation.OPENSSL; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT)).isInstanceOf(OpenSslEngine.class); + } + + @Test + public void testCustomCipherSuite() { + serverOptions.sslCiphers = Collections.singletonList("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"); + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.cipherSuites()).containsExactly("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"); + } + + @Test + public void testSystemCipherSuites() { + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.cipherSuites().size()).isNotEqualTo(1); + } + + @Test + public void testCustomProtocolVersion() { + serverOptions.sslProtocols = Collections.singleton("TLSv1.2"); + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getEnabledProtocols()).containsExactly("TLSv1.2"); + } + + @Test + public void testSystemProtocolVersions() { + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getEnabledProtocols().length).isNotEqualTo(1); + } + + @Test + public void testWithRequiredClientAuth() { + serverOptions.sslImplementation = SslImplementation.JDK; + serverOptions.sslClientAuthentication = ClientAuthentication.REQUIRE; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getNeedClientAuth()).isTrue(); + } + + @Test + public void testWithOptionalClientAuth() { + serverOptions.sslImplementation = SslImplementation.JDK; + serverOptions.sslClientAuthentication = ClientAuthentication.OPTIONAL; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getNeedClientAuth()).isFalse(); + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getWantClientAuth()).isTrue(); + } + + @Test + public void testWithNoClientAuth() { + serverOptions.sslImplementation = SslImplementation.JDK; + serverOptions.sslClientAuthentication = ClientAuthentication.NONE; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getNeedClientAuth()).isFalse(); + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getWantClientAuth()).isFalse(); + assertThat(context.newEngine(ByteBufAllocator.DEFAULT).getUseClientMode()).isFalse(); + } + + @Test + public void testCreateFailWithKeyOnly() { + serverOptions.sslServerKeyFile = selfSignedCertificate.privateKey(); + + assertThatIllegalArgumentException().isThrownBy(() -> contextFactory.createSslContext()) + .withMessageContaining("server certificate must be specified"); + } + + @Test + public void testSslFailWithCertOnly() { + serverOptions.sslServerCertificateFile = selfSignedCertificate.certificate(); + + assertThatIllegalArgumentException().isThrownBy(() -> contextFactory.createSslContext()) + .withMessageContaining("server key must be specified"); + } + + @Test + public void testSslFailWithNonReadablePasswordFile() { + serverOptions.sslServerKeyFile = selfSignedCertificate.privateKey(); + serverOptions.sslServerKeyPasswordFile = new File("/tmp/do-not-exist-ddddddddd.pass"); + serverOptions.sslServerCertificateFile = selfSignedCertificate.certificate(); + + assertThatIllegalArgumentException().isThrownBy(() -> contextFactory.createSslContext()) + .withMessageContaining("Unable to read SSL server key password file"); + } + + @Test + public void testCreateSslContextWithServerKeyAndCert() { + serverOptions.sslServerKeyFile = givenResource("cert/key.pem"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT)).isInstanceOf(SSLEngineImpl.class); + } + + @Test + public void testCreateSslContextWithServerKeyAndCertWithPassword() { + serverOptions.sslServerKeyFile = givenResource("cert/protected-key.pem"); + serverOptions.sslServerKeyPasswordFile = givenResource("cert/protected-key.pass"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + serverOptions.sslImplementation = SslImplementation.JDK; + + SslContext context = contextFactory.createSslContext(); + + assertThat(context.newEngine(ByteBufAllocator.DEFAULT)).isInstanceOf(SSLEngineImpl.class); + } + + @Test + public void testCreateSslContextWithServerKeyAndCertFailWithWrongPassword() throws IOException { + serverOptions.sslServerKeyFile = givenResource("cert/protected-key.pem"); + serverOptions.sslServerKeyPasswordFile = givenTemporaryFile("key.pass", "wrongpass"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + serverOptions.sslImplementation = SslImplementation.JDK; + + assertThatIllegalArgumentException().isThrownBy(() -> contextFactory.createSslContext()); + } + + @Test + public void testCreateSslContextWithServerKeyAndCertFailWithMissingPassword() { + serverOptions.sslServerKeyFile = givenResource("cert/protected-key.pem"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + serverOptions.sslImplementation = SslImplementation.JDK; + + assertThatIllegalArgumentException().isThrownBy(() -> contextFactory.createSslContext()); + } + + private File givenResource(String resource) { + URL url = this.getClass().getResource("/" + resource); + return new File(url.getFile()); + } + + private File givenTemporaryFile(String filename, String content) throws IOException { + File file = File.createTempFile(filename, "tmp"); + Files.write(file.toPath(), content.getBytes()); + + return file; + } +} diff --git a/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSslSupport.java b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSslSupport.java new file mode 100644 index 0000000..00a2a8e --- /dev/null +++ b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSslSupport.java @@ -0,0 +1,168 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import com.zegelin.cassandra.exporter.cli.HttpServerOptions; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.ssl.OptionalSslHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslHandler; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.File; +import java.net.InetSocketAddress; +import java.net.URL; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class TestSslSupport { + @Mock + private SocketChannel socketChannel; + + @Mock + private ChannelPipeline channelPipeline; + + private HttpServerOptions serverOptions; + + @BeforeMethod + public void before() { + MockitoAnnotations.initMocks(this); + when(socketChannel.pipeline()).thenReturn(channelPipeline); + when(socketChannel.alloc()).thenReturn(ByteBufAllocator.DEFAULT); + when(socketChannel.remoteAddress()).thenReturn(InetSocketAddress.createUnresolved("localhost", 12345)); + when(channelPipeline.addFirst(any(ChannelHandler.class))).thenReturn(channelPipeline); + when(channelPipeline.addLast(any(ChannelHandler.class))).thenReturn(channelPipeline); + + serverOptions = new HttpServerOptions(); + } + + @Test + public void testSslDisabled() { + serverOptions.sslMode = SslMode.DISABLE; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + + verifyNoMoreInteractions(channelPipeline); + } + + @Test + public void testSslEnabled() { + serverOptions.sslMode = SslMode.ENABLE; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + + verify(channelPipeline).addFirst(any(SslHandler.class)); + verify(channelPipeline).addLast(any(SuppressingSslExceptionHandler.class)); + } + + @Test + public void testSslOptional() { + serverOptions.sslMode = SslMode.OPTIONAL; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + + verify(channelPipeline).addFirst(any(OptionalSslHandler.class)); + verify(channelPipeline).addLast(any(SuppressingSslExceptionHandler.class)); + } + + @Test + public void testSslWithValidation() { + serverOptions.sslMode = SslMode.ENABLE; + serverOptions.sslClientAuthentication = ClientAuthentication.VALIDATE; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + + ArgumentCaptor handlerCaptor = ArgumentCaptor.forClass(SslHandler.class); + verify(channelPipeline).addFirst(handlerCaptor.capture()); + assertThat(handlerCaptor.getValue().engine().getSSLParameters().getEndpointIdentificationAlgorithm()).isEqualTo("HTTPS"); + verify(channelPipeline).addLast(any(SuppressingSslExceptionHandler.class)); + } + + @Test + public void testSslOptionalWithValidation() { + serverOptions.sslMode = SslMode.OPTIONAL; + serverOptions.sslClientAuthentication = ClientAuthentication.VALIDATE; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + + verify(channelPipeline).addFirst(any(OptionalSslHandler.class)); + verify(channelPipeline).addLast(any(SuppressingSslExceptionHandler.class)); + } + + + @Test + public void testSslReload() throws InterruptedException { + serverOptions.sslMode = SslMode.ENABLE; + serverOptions.sslServerKeyFile = givenResource("cert/key.pem"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + serverOptions.sslReloadIntervalInSeconds = 1; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + SslContext unexpectedContext = sslSupport.getSslContext(); + + Thread.sleep(1001); + serverOptions.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + + sslSupport.maybeAddHandler(socketChannel); + + assertThat(sslSupport.getSslContext()).isNotSameAs(unexpectedContext); + } + + @Test + public void testSslNoReloadOnFailure() throws InterruptedException { + serverOptions.sslMode = SslMode.ENABLE; + serverOptions.sslServerKeyFile = givenResource("cert/key.pem"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + serverOptions.sslReloadIntervalInSeconds = 1; + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + SslContext expectedContext = sslSupport.getSslContext(); + + Thread.sleep(1001); + serverOptions.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + serverOptions.sslServerCertificateFile = null; + + sslSupport.maybeAddHandler(socketChannel); + + assertThat(sslSupport.getSslContext()).isSameAs(expectedContext); + } + + @Test + public void testSslReloadDisabled() throws InterruptedException { + serverOptions.sslMode = SslMode.ENABLE; + serverOptions.sslServerKeyFile = givenResource("cert/key.pem"); + serverOptions.sslServerCertificateFile = givenResource("cert/cert.pem"); + SslSupport sslSupport = new SslSupport(serverOptions); + + sslSupport.maybeAddHandler(socketChannel); + SslContext expectedContext = sslSupport.getSslContext(); + + Thread.sleep(1001); + serverOptions.sslServerKeyFile.setLastModified(System.currentTimeMillis()); + + sslSupport.maybeAddHandler(socketChannel); + + assertThat(sslSupport.getSslContext()).isSameAs(expectedContext); + } + + private File givenResource(String resource) { + URL url = this.getClass().getResource("/" + resource); + return new File(url.getFile()); + } +} diff --git a/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSuppressingSslExceptionHandler.java b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSuppressingSslExceptionHandler.java new file mode 100644 index 0000000..89cdd56 --- /dev/null +++ b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestSuppressingSslExceptionHandler.java @@ -0,0 +1,77 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.DecoderException; +import io.netty.handler.ssl.NotSslRecordException; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import javax.net.ssl.SSLHandshakeException; + +import java.net.InetSocketAddress; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +public class TestSuppressingSslExceptionHandler { + @Mock + private ChannelHandlerContext context; + + @Mock + private Channel channel; + + private SuppressingSslExceptionHandler handler; + + @BeforeMethod + public void before() { + MockitoAnnotations.initMocks(this); + handler = new SuppressingSslExceptionHandler(); + + when(context.channel()).thenReturn(channel); + when(channel.remoteAddress()).thenReturn(InetSocketAddress.createUnresolved("127.0.0.1", 12345)); + } + + @Test + public void testNotSslExceptionFromJdkImplementationIsMuted() { + handler.exceptionCaught(context, new NotSslRecordException("Some HTTP_REQUEST in message")); + verify(context, times(0)).fireExceptionCaught(any()); + } + + @Test + public void testSslHandshakeExceptionFromOpenSslImplementationIsMuted() { + handler.exceptionCaught(context, new DecoderException(new SSLHandshakeException("Some HTTP_REQUEST in message"))); + verify(context, times(0)).fireExceptionCaught(any()); + } + + @Test + public void testNotSslRecordExceptionIsMuted() { + handler.exceptionCaught(context, new DecoderException(new NotSslRecordException("Some HTTP_REQUEST in message"))); + verify(context, times(0)).fireExceptionCaught(any()); + } + + @Test + public void testInfoLogDoNotBailOnNullChannel() { + when(context.channel()).thenReturn(null); + handler.exceptionCaught(context, new NotSslRecordException("Some HTTP_REQUEST in message")); + verify(context, times(0)).fireExceptionCaught(any()); + } + + @Test + public void testInfoLogDoNotBailOnNullRemoteAddress() { + when(channel.remoteAddress()).thenReturn(null); + handler.exceptionCaught(context, new NotSslRecordException("Some HTTP_REQUEST in message")); + verify(context, times(0)).fireExceptionCaught(any()); + } + + @Test + public void testOtherExceptionIsPropagated() { + handler.exceptionCaught(context, new NullPointerException()); + verify(context, times(1)).fireExceptionCaught(any()); + } +} diff --git a/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestUnexpectedSslExceptionHandler.java b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestUnexpectedSslExceptionHandler.java new file mode 100644 index 0000000..d3f3c78 --- /dev/null +++ b/common/src/test/java/com/zegelin/cassandra/exporter/netty/ssl/TestUnexpectedSslExceptionHandler.java @@ -0,0 +1,70 @@ +package com.zegelin.cassandra.exporter.netty.ssl; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.DecoderException; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import javax.net.ssl.SSLException; +import java.net.InetSocketAddress; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + + +public class TestUnexpectedSslExceptionHandler { + @Mock + private ChannelHandlerContext context; + + @Mock + private Channel channel; + + @Mock + private ReloadWatcher watcher; + + private UnexpectedSslExceptionHandler handler; + + @BeforeMethod + public void before() { + MockitoAnnotations.initMocks(this); + + handler = new UnexpectedSslExceptionHandler(watcher); + + when(context.channel()).thenReturn(channel); + when(channel.remoteAddress()).thenReturn(InetSocketAddress.createUnresolved("127.0.0.1", 12345)); + } + + @AfterMethod + public void after() { + verify(context, times(1)).fireExceptionCaught(any()); + verifyNoMoreInteractions(context, watcher); + } + + @Test + public void testUnexpectedSslExceptionCauseForcedReload() { + handler.exceptionCaught(context, new DecoderException(new SSLException("Received fatal alert: unexpected_message"))); + verify(watcher, times(1)).forceReload(); + } + + @Test + public void testOtherSslExceptionIsPropagated() { + handler.exceptionCaught(context, new DecoderException(new SSLException("Other message"))); + } + + @Test + public void testDecoderExceptionIsPropagated() { + handler.exceptionCaught(context, new DecoderException()); + } + + @Test + public void testOtherExceptionIsPropagated() { + handler.exceptionCaught(context, new NullPointerException()); + } +} diff --git a/common/src/test/java/com/zegelin/prometheus/domain/TestLabels.java b/common/src/test/java/com/zegelin/prometheus/domain/TestLabels.java new file mode 100644 index 0000000..2c6abc6 --- /dev/null +++ b/common/src/test/java/com/zegelin/prometheus/domain/TestLabels.java @@ -0,0 +1,87 @@ +package com.zegelin.prometheus.domain; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import io.netty.util.ResourceLeakDetector; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Ignore; +import org.testng.annotations.Test; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +public class TestLabels { + private static ResourceLeakDetector.Level originalDetectionLevel; + + @Mock + private Appender loggingEventAppender; + + @BeforeClass + public static void beforeClass() { + originalDetectionLevel = ResourceLeakDetector.getLevel(); + ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.PARANOID); + } + + @BeforeMethod + public void beforeMethod() { + MockitoAnnotations.initMocks(this); + + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + loggerContext.getLogger(ResourceLeakDetector.class).addAppender(loggingEventAppender); + } + + @AfterMethod + public void afterMethod() { + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + loggerContext.getLogger(ResourceLeakDetector.class).detachAppender(loggingEventAppender); + } + + @AfterClass + public static void afterClass() { + ResourceLeakDetector.setLevel(originalDetectionLevel); + } + + @Ignore ("Fails on a false-positive leak detection in Netty. See #46") + @Test + public void testPlainTextNettyLeakWarning() { + for (int i = 0; i < 10; i++) { + Labels labels = Labels.of("key", "value"); + labels.asPlainTextFormatUTF8EncodedByteBuf(); + Runtime.getRuntime().gc(); + } + + verifyNoMoreInteractions(loggingEventAppender); + } + + @Test + public void testJSONNettyLeakWarning() { + for (int i = 0; i < 10; i++) { + Labels labels = Labels.of("key", "value"); + labels.asJSONFormatUTF8EncodedByteBuf(); + Runtime.getRuntime().gc(); + } + + verifyNoMoreInteractions(loggingEventAppender); + } + + @Test + public void testPlainTextFinalizer() throws Throwable { + Labels labels = Labels.of("key", "value"); + labels.asPlainTextFormatUTF8EncodedByteBuf(); + assertThatCode(() -> labels.finalize()).doesNotThrowAnyException(); + } + + @Test + public void testJSONFinalizer() throws Throwable { + Labels labels = Labels.of("key", "value"); + labels.asJSONFormatUTF8EncodedByteBuf(); + assertThatCode(() -> labels.finalize()).doesNotThrowAnyException(); + } +} diff --git a/common/src/test/java/com/zegelin/prometheus/exposition/TestFormattedByteChannel.java b/common/src/test/java/com/zegelin/prometheus/exposition/TestFormattedByteChannel.java new file mode 100644 index 0000000..adebcd4 --- /dev/null +++ b/common/src/test/java/com/zegelin/prometheus/exposition/TestFormattedByteChannel.java @@ -0,0 +1,56 @@ +package com.zegelin.prometheus.exposition; + +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.when; + +public class TestFormattedByteChannel { + @Mock + private FormattedExposition formattedExposition; + + private ByteBuffer buffer; + private FormattedByteChannel channel; + + @BeforeMethod + public void before() { + MockitoAnnotations.initMocks(this); + buffer = ByteBuffer.allocate(128); + channel = new FormattedByteChannel(formattedExposition); + } + + @Test + public void testClosed() { + when(formattedExposition.isEndOfInput()).thenReturn(true); + + assertThat(channel.read(buffer)).isEqualTo(-1); + assertThat(channel.isOpen()).isEqualTo(false); + } + + @Test + public void testOpen() { + when(formattedExposition.isEndOfInput()).thenReturn(false); + + assertThat(channel.isOpen()).isEqualTo(true); + } + + @Test + public void testOneChunk() { + when(formattedExposition.isEndOfInput()).thenReturn(false).thenReturn(false).thenReturn(true); + doAnswer(invocation -> { + NioExpositionSink sink = invocation.getArgument(0); + sink.writeAscii("abcdefghij"); + return null; + }).when(formattedExposition).nextSlice(any(NioExpositionSink.class)); + + assertThat(channel.read(buffer)).isEqualTo(10); + assertThat(channel.isOpen()).isEqualTo(false); + } +} diff --git a/common/src/test/java/com/zegelin/prometheus/exposition/TestNettyExpositionSink.java b/common/src/test/java/com/zegelin/prometheus/exposition/TestNettyExpositionSink.java new file mode 100644 index 0000000..a763751 --- /dev/null +++ b/common/src/test/java/com/zegelin/prometheus/exposition/TestNettyExpositionSink.java @@ -0,0 +1,63 @@ +package com.zegelin.prometheus.exposition; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; + +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.assertj.core.api.Assertions.assertThat; + +public class TestNettyExpositionSink { + + private NettyExpositionSink sink; + + @BeforeMethod + public void before() { + ByteBuf buffer = Unpooled.buffer(); + sink = new NettyExpositionSink(buffer); + } + + @Test + public void testAsciiCharSize() { + sink.writeByte('a'); + sink.writeByte('b'); + sink.writeByte('c'); + + assertThat(sink.getIngestedByteCount()).isEqualTo(3); + } + + @Test + public void testAsciiStringSize() { + sink.writeAscii("123"); + sink.writeAscii("abc"); + + assertThat(sink.getIngestedByteCount()).isEqualTo(6); + } + + @Test + public void testUtf8StringSize() { + sink.writeUtf8("123"); + sink.writeUtf8("abc"); + sink.writeUtf8("åäö"); + + assertThat(sink.getIngestedByteCount()).isEqualTo(12); + } + + @Test + public void testFloatSize() { + sink.writeFloat(0.123f); + + assertThat(sink.getIngestedByteCount()).isEqualTo(5); + } + + @Test + public void testBufferSize() { + ByteBuffer buffer = ByteBuffer.wrap("abc".getBytes(US_ASCII)); + sink.writeBytes(buffer); + + assertThat(sink.getIngestedByteCount()).isEqualTo(3); + } +} diff --git a/common/src/test/java/com/zegelin/prometheus/exposition/TestNioExpositionSink.java b/common/src/test/java/com/zegelin/prometheus/exposition/TestNioExpositionSink.java new file mode 100644 index 0000000..e6c9689 --- /dev/null +++ b/common/src/test/java/com/zegelin/prometheus/exposition/TestNioExpositionSink.java @@ -0,0 +1,61 @@ +package com.zegelin.prometheus.exposition; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; + +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.assertj.core.api.Assertions.assertThat; + +public class TestNioExpositionSink { + + private NioExpositionSink sink; + + @BeforeMethod + public void before() { + ByteBuffer buffer = ByteBuffer.allocate(128); + sink = new NioExpositionSink(buffer); + } + + @Test + public void testAsciiCharSize() { + sink.writeByte('a'); + sink.writeByte('b'); + sink.writeByte('c'); + + assertThat(sink.getIngestedByteCount()).isEqualTo(3); + } + + @Test + public void testAsciiStringSize() { + sink.writeAscii("123"); + sink.writeAscii("abc"); + + assertThat(sink.getIngestedByteCount()).isEqualTo(6); + } + + @Test + public void testUtf8StringSize() { + sink.writeUtf8("123"); + sink.writeUtf8("abc"); + sink.writeUtf8("åäö"); + + assertThat(sink.getIngestedByteCount()).isEqualTo(12); + } + + @Test + public void testFloatSize() { + sink.writeFloat(0.123f); + + assertThat(sink.getIngestedByteCount()).isEqualTo(5); + } + + @Test + public void testBufferSize() { + ByteBuffer buffer = ByteBuffer.wrap("abc".getBytes(US_ASCII)); + sink.writeBytes(buffer); + + assertThat(sink.getIngestedByteCount()).isEqualTo(3); + } +} diff --git a/common/src/test/java/info/adams/ryu/TestRyuFloat.java b/common/src/test/java/info/adams/ryu/TestRyuFloat.java new file mode 100644 index 0000000..3c3759a --- /dev/null +++ b/common/src/test/java/info/adams/ryu/TestRyuFloat.java @@ -0,0 +1,23 @@ +package info.adams.ryu; + +import org.apache.commons.codec.binary.Hex; +import org.testng.annotations.Test; + +import java.nio.ByteBuffer; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; + +public class TestRyuFloat { + @Test + public void testFloatToBuffer() { + float f = 0.33007812f; + final ByteBuffer buffer = ByteBuffer.allocate(10); + + int size = RyuFloat.floatToString(buffer, f, RoundingMode.ROUND_EVEN); + + assertThat(size).isEqualTo(10); + assertThat(Hex.encodeHexString(buffer.array())).isEqualTo("302e3333303037383132"); + assertThat(new String(buffer.array(), UTF_8)).isEqualTo("0.33007812"); + } +} diff --git a/common/src/test/resources/cert/cert.pem b/common/src/test/resources/cert/cert.pem new file mode 100644 index 0000000..8dfea2a --- /dev/null +++ b/common/src/test/resources/cert/cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIJAKWYKinU7ISSMA0GCSqGSIb3DQEBCwUAMDsxEjAQBgNV +BAMMCWxvY2FsaG9zdDEYMBYGA1UECgwPRXhhbXBsZSBDb21wYW55MQswCQYDVQQG +EwJTRTAeFw0yMDAxMTUxMjI3NTRaFw00NzA2MDIxMjI3NTRaMDsxEjAQBgNVBAMM +CWxvY2FsaG9zdDEYMBYGA1UECgwPRXhhbXBsZSBDb21wYW55MQswCQYDVQQGEwJT +RTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK8ynksuPHrifO5rYUtE +xRjONbYSVpEeWuGTIluX32EItGkporfBiFySbcdEFjC3+P0QJhgDTK2lu5FMjefI +lZYjByVMaaWmnJnW7VjGu2jdvZkFstylSsfFx79XxoHma3b0a6j+OXTR/Hrr2ytL +sp0kTScwo2THbNlmLFIHZgIUvLzwOALHbfOlVDkXrt3/hJnlm+4ssCEYycSRc2lG +lvB0fXLxMbBoJAtsqzeSzl+EptUf2dyB849nwX3XLtYLOI7gY2jKNiMn+ZnEM5IB +lqIPwS0GCqfRPuVUpr+DV4w4n8JK62UD24omnomhRjg1jZuyb5ewDI4nwaB5gjog +JuMCAwEAAaNTMFEwHQYDVR0OBBYEFDLHQ8iMY1GKrOd8sE7TqUsLMmDHMB8GA1Ud +IwQYMBaAFDLHQ8iMY1GKrOd8sE7TqUsLMmDHMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBAJReqMSSYuh+YjIb/Xwd1QteRs0bWlHrMReU26XOHWwf +EfYSQgiEAeJmeLPbx10GVhT2TtUCE4zkuesaAx7TpWduS5UPeKmu1ltbZGQWsLsG +k0NuEqWnuOMowkWjKHyA/4TEWbs/eRiwiCfJHNRa9PuJ2luusp78CZPTqereLc1W +wF5ZtbXU6ZXi1dKxR6NXn4ZTBwBJyKq+wCLmNlo0aW4IbH1yUdmvp2CjLpg4GHYt +RkcYNlkBLHqVwxCCoTzATTBk2iyPjU3iI7nH/V8BTn30if9KE51eKzqompTvicxy +3qORBOHXz+F4vC4rNSy1TcKOt5jcWD7bcFUkPJB4ifU= +-----END CERTIFICATE----- diff --git a/common/src/test/resources/cert/key.pem b/common/src/test/resources/cert/key.pem new file mode 100644 index 0000000..f3fb3c8 --- /dev/null +++ b/common/src/test/resources/cert/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCvMp5LLjx64nzu +a2FLRMUYzjW2ElaRHlrhkyJbl99hCLRpKaK3wYhckm3HRBYwt/j9ECYYA0ytpbuR +TI3nyJWWIwclTGmlppyZ1u1Yxrto3b2ZBbLcpUrHxce/V8aB5mt29Guo/jl00fx6 +69srS7KdJE0nMKNkx2zZZixSB2YCFLy88DgCx23zpVQ5F67d/4SZ5ZvuLLAhGMnE +kXNpRpbwdH1y8TGwaCQLbKs3ks5fhKbVH9ncgfOPZ8F91y7WCziO4GNoyjYjJ/mZ +xDOSAZaiD8EtBgqn0T7lVKa/g1eMOJ/CSutlA9uKJp6JoUY4NY2bsm+XsAyOJ8Gg +eYI6ICbjAgMBAAECggEATkMyayswYUSjwm29fL4vvbEAVWFDwnfo6TOs+XWSl+on +jYLH6YZOv+u5lnZX41OLqqB4I+n1auzKKVIlYhE8oWDsZEEKQLF461ATnsDIH0RO +2fitudss2KkFXfh7+LNR9kWhglBuojzbqJ2Lvn+GPqRkwsj7dJ2RhlwaGFqtuueC +3YNA+HWtN9C+2mq0pfwMlnKbTmOb5/JwRP38lp3101vQ0jhYLGqkNzgPSEj3VFYI +8CAs1pwaz1Jk42TbFfC4rbDqQ1kUzAN3uoTyVdseUTWFCCTRuD3JIqGleFyb9w8R +A+je7bc4GfCBPzKKHpHAsuvArjzeqd7SMyNalsVeIQKBgQDkEEi1p4RcIAIZGeUC +7B7Gmt/P4LyqJ3e3e/iR/wy/I222UxRIBgETRUeCNVCMpwb0r8UzTX9nRxfgyV2M +Dc2dsp5PDoU2I5d7L0Pa+OEGlyIgm6SujLMGJrzSoRcC3a8gudHuCvfZeQ54K5HL +XJVZV0z6hErrC/m8NHpFXTQcFQKBgQDEqIse6wf6YPbfqcPWFi2rio4E2OA+9Q/F +7spTKAa8rov4bMSnBuSy8r0vcRCycQ4bTeIcIOSGYFS831eduJKK0dIm7GBH+OqZ +FiE8IxDJTER92w/GrEdgykBQaUG5sxe2wtnaNjYR77h1a0ioEvYUiWcjxU/SXZST +EDzRZMZdFwKBgFGirpQvoYZkgru/dCVmpeGLoJ/Fn2L8+7J3MtP3yvVEVkpUVMcv +NwVR4DXwpaOjSi8eF+W0UO2EGj0Bd3Xhnv9a56X+2Zo2hUu38H8aZVo5kSLA8+Lz +REXoaeCvfxAskDqTqVyfGncDCTXkyqxTuLYhNNHbtwGJ6NwAoN/ha/y9AoGAOP4j +e21f3YcWZNF9SOEakTlRWURFENnSnWlLx3e1JB9tvyw+fa14wAerHkGlNiGflfgn +TEGYGP138VjEupfQGF0gi1k7ugAAdSc9sID1D3GD8/l1g/1PnlRe+S7X9mpZuASW +QDAv0Vjo21ahMtxz5pW/h1VagbvPICO3jHOpLTcCgYAyi6oiIUsPcTv00wRWwL9R ++gHDxjAyIORnFQlrc6ZtsH9sJpipwyDIT5OiaJ5HZMM8ezq+aTDl0sUUKpkmPtks +6uIDhkDzBK+86A98nl3tZ92zLvZbZnxCLZRXqQKmZnERCJoQsRW/o92MZFpZonqJ +jKMFKV7ctU50n5yMLhPlsQ== +-----END PRIVATE KEY----- diff --git a/common/src/test/resources/cert/protected-key.pass b/common/src/test/resources/cert/protected-key.pass new file mode 100644 index 0000000..7aa311a --- /dev/null +++ b/common/src/test/resources/cert/protected-key.pass @@ -0,0 +1 @@ +password \ No newline at end of file diff --git a/common/src/test/resources/cert/protected-key.pem b/common/src/test/resources/cert/protected-key.pem new file mode 100644 index 0000000..cafa2a1 --- /dev/null +++ b/common/src/test/resources/cert/protected-key.pem @@ -0,0 +1,29 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIE4jAcBgoqhkiG9w0BDAEBMA4ECPlGrgu2rA1JAgIIAASCBMCWwmevE5bgkpg2 +yaPUmtA3CpUSisRaO2ZSpfECguUEU3GvII1j7y9PTynuu1v7KKab/gKiA2jEj4AO +AUSmzGwdCsT4rzBPq34t2hkAV028YPmrb7KvjPJbqskIguyIbkfszLVdjj5sdzg6 +rTdu7p5q9zsxjgI1JJ2Zoh8F5C4CvqXyFx0EOxx1jBWS2unwKT+Cuk4IJ6P9vHDe +skJpnSwHLb9TGVVeJIsqXbQB1/BvCSadLjKfPOUCKwiTMLrqyKi1o8g+kQS4LxCN +oSV6NOmJqRWOZ7JWW3ufi2mYsuNgo6Jc1s0JDIRuGtB9+86CGrm1FW1D83ttvDCX +9/PE8dcVQ0AwN/bHcpG7ZEjIsDGLVuWFpmhlZJpcRn3AyhaikSiQXyMnkMYBag7P +FNTWIKLPFlfC17A1mvnri1CQTiRF9rorNNe81v+jMa4uyDwixkd5i5xr8mBc9uWE +MB2cKPf7RKHxG4PqPpD1BIuwaCfN+8KVoJ4Q4Nh4WlS+Z679egwpkqodHoU47YB2 +P+hcYmH32rNwZTn/AILLYCMCbgEccSkcb52/DY6xDWq+HsrkgeAwYcQDK8sXoALU +s7cEPeQI41S0KMd37Do0E9CfRzxcJO4zQVn1nvnvBv7x5x/v3h0CS6ADzw/igxqY +uHY4dhpRPo5YjKL7nFepr4dW5G2I9GlquLStYYR/mZ8FMhTTFF+8Z/OFNGys12Id +tmUu+gRazExD86J2nnLyQWzmSjCYcObScaBP7i1e5+Ihd8joXjCkwu0VmBsJ6Cci +tJtemzS3p86wdUR9LGYltDmP8vsiVbEr2KRvoi1SZo5STgg7LgaU/dvOrKWeFYmz +yNgnEH2y8aS0N+aYwoSaLxZTfcbhDU/Bmr0osB7Ya6NG2OppKX89HoJyQKl6dYVy +alkqmwCZWTH6fqW6vCnb7jW7P0msIpfA4Gz7f4pxI1blTb+bDVkFGYZymHCiYikw +8E0fF42CS1HhZhPmaOvqlnhkI2IiIZ4+uFe+zeWUnjUV6gfXO3/OaDl7RCdLIbUN +8P6vYTrLdTQRsRlEgfW+vqTHtdcWsovjtIHT5xr7LoESOz1uoLQ9Nxv3xAWp2n0N +7x97LuHE6oICfwUKzMyidlxjosWiulW4fTBiGMuzEr6yYuj74XPDUIPv4+XXApKx +0u1X5qo3qD7PTe6zZ0FIMvCcTFIctta8xyiovq9gwMajPN94rNCrsjDINQkdfvAZ +gOFVvI3Na3zvCreMp6t4llXRR/i4dkuFe7tk5axJPXS+Ri7F3HIF6WjXpnTyO/Ok +f9fJUBCSgvlNODlGLVc3SEXnFVO0t5/2lraRBuoi/yAEPKJ59tE0la2O7Sg5zn3H +k631neviXTwnhXBdFWXopREaXULa7Z89U/P6i5r/eQGU2bXXb8+KALLgt0UMbhB9 +OKMtPjQKgkZ2MWS5PDWwcCCZKIOMbI48uI01BRLXwQtPw+GkgT2dUhksd3jDMfWi +Dic/skbVUvtbc3NEoZqcXj4Vnxal34xT8ukWWoHviB1Sn417xaY+Ro79q4ZvetZi +dyJT7ABbshTwyb15v56vxNZMxzlzoj1n/Bhb8XRC6nFpwIqQ+IA1VXRYMmrS6drC +lCAmx33A +-----END ENCRYPTED PRIVATE KEY----- diff --git a/grafana/instaclustr/cluster-overview.json b/grafana/instaclustr/cluster-overview.json new file mode 100644 index 0000000..9bf350b --- /dev/null +++ b/grafana/instaclustr/cluster-overview.json @@ -0,0 +1,2016 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "VAR_NODE_DASHBOARD_URL", + "type": "constant", + "label": "node_dashboard_url", + "value": "/d/WZGSOV8mk/node-overview", + "description": "" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.4.3" + }, + { + "type": "panel", + "id": "grafana-polystat-panel", + "name": "Polystat", + "version": "1.0.16" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "A cluster-wide overview that's designed for multi-DC topologies", + "editable": true, + "gnetId": null, + "graphTooltip": 0, + "id": null, + "iteration": 1574742754507, + "links": [], + "panels": [ + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 62, + "panels": [], + "title": "Cluster Stats", + "type": "row" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "${DS_PROMETHEUS}", + "decimals": 3, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 106, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "#0a50a1", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "avg(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Current Cluster Availability", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "${DS_PROMETHEUS}", + "format": "bytes", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 4, + "y": 1 + }, + "id": 22, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "sum(cassandra_storage_load_bytes{cassandra_cluster=\"$cluster\"})", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Current Storage Load", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + }, + { + "columns": [ + { + "text": "Current", + "value": "current" + } + ], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "90%", + "gridPos": { + "h": 6, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 58, + "links": [], + "options": {}, + "pageSize": null, + "scroll": false, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Schema Component", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "Metric", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Count", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "Current", + "thresholds": [], + "type": "number", + "unit": "short" + } + ], + "targets": [ + { + "expr": "count(count(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\",keyspace!~\"system.*\"}) by (keyspace))", + "format": "time_series", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Keyspaces", + "refId": "A" + }, + { + "expr": "count(count(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\",keyspace!~\"system.*\",table_type=\"table\"}) by (table)) or vector(0)", + "format": "time_series", + "hide": false, + "instant": true, + "intervalFactor": 1, + "legendFormat": "Tables", + "refId": "B" + }, + { + "expr": "count(count(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\",keyspace!~\"system.*\",table_type=\"view\"}) by (table)) or vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Materialized Views", + "refId": "C" + }, + { + "expr": "count(count(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\",keyspace!~\"system.*\",table_type=\"index\"}) by (table)) or vector(0)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "Indexes", + "refId": "D" + } + ], + "title": "Schema (exc. system keyspaces)", + "transform": "timeseries_aggregations", + "type": "table" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "${DS_PROMETHEUS}", + "decimals": 3, + "format": "percentunit", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 4 + }, + "id": 54, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "options": {}, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "#0a50a1", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "avg(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "refId": "A" + } + ], + "thresholds": "", + "title": "Average Cluster Availability for Period", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 18, + "panels": [], + "title": "$cluster Data Centers", + "type": "row" + }, + { + "colors": [ + "#299c46", + "rgba(237, 129, 40, 0.89)", + "#d44a3a" + ], + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 4, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 14, + "links": [], + "options": {}, + "polystat": { + "animationSpeed": 2500, + "columnAutoSize": true, + "columns": 1, + "defaultClickThrough": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell_name}&from=${__from}&to=${__to}", + "defaultClickThroughSanitize": false, + "displayLimit": 100, + "fontAutoScale": true, + "fontSize": 5, + "fontType": "Roboto", + "globalDecimals": 2, + "globalDisplayMode": "all", + "globalDisplayTextTriggeredEmpty": "OK", + "globalOperatorName": "current", + "globalUnitFormat": "none", + "gradientEnabled": false, + "hexagonSortByDirection": "asc", + "hexagonSortByField": "name", + "maxMetrics": 0, + "polygonBorderColor": "black", + "polygonBorderSize": 2, + "polygonGlobalFillColor": "#0a50a1", + "radius": "", + "radiusAutoSize": true, + "rowAutoSize": true, + "rows": 1, + "shape": "hexagon_pointed_top", + "tooltipDisplayMode": "all", + "tooltipDisplayTextTriggeredEmpty": "OK", + "tooltipFontSize": 12, + "tooltipFontType": "Roboto", + "tooltipPrimarySortDirection": "desc", + "tooltipPrimarySortField": "thresholdLevel", + "tooltipSecondarySortDirection": "desc", + "tooltipSecondarySortField": "value", + "tooltipTimestampEnabled": true + }, + "repeat": "datacenter", + "repeatDirection": "h", + "savedComposites": [], + "savedOverrides": [ + { + "clickThrough": "", + "colors": [ + "#299c46", + "#e5ac0e", + "#bf1b00", + "#ffffff" + ], + "decimals": 2, + "enabled": true, + "label": "OVERRIDE 1", + "metricName": ".*", + "operatorName": "current", + "prefix": "", + "sanitizeURLEnabled": false, + "scaledDecimals": null, + "suffix": "", + "thresholds": [ + { + "color": "#bf1b00", + "state": 2, + "value": 0 + }, + { + "color": "#e5ac0e", + "state": 1, + "value": 0.1 + }, + { + "color": "#299c46", + "state": 0, + "value": 1 + } + ], + "unitFormat": "none" + } + ], + "targets": [ + { + "expr": "avg(cassandra_endpoint_active{cassandra_cluster=\"$cluster\", endpoint_datacenter=\"$datacenter\"}) by (endpoint)", + "format": "time_series", + "instant": true, + "intervalFactor": 1, + "legendFormat": "{{endpoint}}", + "refId": "A" + } + ], + "timeFrom": null, + "title": "Data Center \"$datacenter\"", + "type": "grafana-polystat-panel" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 12 + }, + "id": 77, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "datacenter", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_client_request_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\", operation=~\"read|rangeslice\"}[1m]))", + "legendFormat": "Reads", + "refId": "A" + }, + { + "expr": "sum(irate(cassandra_client_request_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\", operation=~\"write|viewwrite\"}[1m]))", + "legendFormat": "Writes", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Requests/s ($datacenter)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "reqps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 219, + "panels": [], + "title": "Top $topn Worst Performing Nodes by Client Latency", + "type": "row" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 21 + }, + "id": 192, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 8, + "desc": true + }, + "styles": [ + { + "alias": "Latency", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(max(cassandra_client_request_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\", operation=~\"read|rangeslice\", quantile=\"0.95\"}) by (cassandra_rack, cassandra_node)[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Max p95 Client Read Latency", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 29 + }, + "id": 209, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 8, + "desc": true + }, + "styles": [ + { + "alias": "Latency", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(max(cassandra_client_request_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\", operation=~\"write|viewwrite\", quantile=\"0.95\"}) by (cassandra_rack, cassandra_node)[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Max p95 Client Write Latency", + "transform": "table", + "type": "table" + }, + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 116, + "panels": [], + "title": "Top $topn Worst Performing Nodes by OS Stats", + "type": "row" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 38 + }, + "id": 108, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 8, + "desc": true + }, + "styles": [ + { + "alias": "Disk Usage", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(((cassandra_storage_filesystem_bytes_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"} - cassandra_storage_filesystem_usable_bytes{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}) / cassandra_storage_filesystem_bytes_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"})[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Disk Usage", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 46 + }, + "id": 123, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 7, + "desc": true + }, + "styles": [ + { + "alias": "CPU Usage", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "percentunit" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(cassandra_os_recent_cpu_load_ratio{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Host CPU Usage", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 54 + }, + "id": 132, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 7, + "desc": true + }, + "styles": [ + { + "alias": "1m Load Avg.", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(cassandra_os_1m_load_average{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by 1 Minute Load Average", + "transform": "table", + "type": "table" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 167, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 30 + }, + "id": 150, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "scopedVars": { + "datacenter": { + "selected": false, + "text": "dc1", + "value": "dc1" + } + }, + "showHeader": true, + "sort": { + "col": 7, + "desc": true + }, + "styles": [ + { + "alias": "Hints/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(rate(cassandra_storage_hints_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[1m])[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Hints in Progress/s", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 30 + }, + "id": 205, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574741927132, + "repeatPanelId": 150, + "scopedVars": { + "datacenter": { + "selected": false, + "text": "dc2", + "value": "dc2" + } + }, + "showHeader": true, + "sort": { + "col": 7, + "desc": true + }, + "styles": [ + { + "alias": "Hints/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(rate(cassandra_storage_hints_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[1m])[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Hints in Progress/s", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 30 + }, + "id": 206, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574741927132, + "repeatPanelId": 150, + "scopedVars": { + "datacenter": { + "selected": false, + "text": "dc3", + "value": "dc3" + } + }, + "showHeader": true, + "sort": { + "col": 7, + "desc": true + }, + "styles": [ + { + "alias": "Hints/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(rate(cassandra_storage_hints_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[1m])[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Hints in Progress/s", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 38 + }, + "id": 151, + "options": {}, + "pageSize": null, + "repeat": "datacenter", + "repeatDirection": "h", + "scopedVars": { + "datacenter": { + "selected": false, + "text": "dc1", + "value": "dc1" + } + }, + "showHeader": true, + "sort": { + "col": 3, + "desc": true + }, + "styles": [ + { + "alias": "Messages/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(sum(irate(cassandra_dropped_messages_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[1m])) by (cassandra_node, cassandra_rack)[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Dropped Messages/s", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 38 + }, + "id": 207, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574741927132, + "repeatPanelId": 151, + "scopedVars": { + "datacenter": { + "selected": false, + "text": "dc2", + "value": "dc2" + } + }, + "showHeader": true, + "sort": { + "col": 3, + "desc": true + }, + "styles": [ + { + "alias": "Messages/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(sum(irate(cassandra_dropped_messages_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[1m])) by (cassandra_node, cassandra_rack)[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Dropped Messages/s", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 38 + }, + "id": 208, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574741927132, + "repeatPanelId": 151, + "scopedVars": { + "datacenter": { + "selected": false, + "text": "dc3", + "value": "dc3" + } + }, + "showHeader": true, + "sort": { + "col": 3, + "desc": true + }, + "styles": [ + { + "alias": "Messages/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Node", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${node_dashboard_url:raw}?var-cluster=${cluster}&var-node=${__cell}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "cassandra_node", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "Rack", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "cassandra_rack", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "topk($topn,max_over_time(sum(irate(cassandra_dropped_messages_total{cassandra_cluster=\"$cluster\", cassandra_datacenter=\"$datacenter\"}[1m])) by (cassandra_node, cassandra_rack)[$__range:]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Nodes by Dropped Messages/s", + "transform": "table", + "type": "table" + } + ], + "title": "Top $topn Worst Performing Nodes by Internode Stats", + "type": "row" + } + ], + "refresh": "1m", + "schemaVersion": 20, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_endpoint_active, cassandra_cluster)", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": "label_values(cassandra_endpoint_active, cassandra_cluster)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": "", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"}, cassandra_datacenter)", + "hide": 0, + "includeAll": true, + "label": "Data Center", + "multi": true, + "name": "datacenter", + "options": [], + "query": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"}, cassandra_datacenter)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "5", + "value": "5" + }, + "hide": 0, + "includeAll": false, + "label": "Top 𝑛", + "multi": false, + "name": "topn", + "options": [ + { + "selected": true, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "10", + "value": "10" + }, + { + "selected": false, + "text": "20", + "value": "20" + } + ], + "query": "5,10,20", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "value": "${VAR_NODE_DASHBOARD_URL}", + "text": "${VAR_NODE_DASHBOARD_URL}" + }, + "hide": 2, + "label": null, + "name": "node_dashboard_url", + "options": [ + { + "value": "${VAR_NODE_DASHBOARD_URL}", + "text": "${VAR_NODE_DASHBOARD_URL}" + } + ], + "query": "${VAR_NODE_DASHBOARD_URL}", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Cluster Overview", + "uid": "rYzfx5yik", + "version": 76 +} \ No newline at end of file diff --git a/grafana/instaclustr/node-overview.json b/grafana/instaclustr/node-overview.json new file mode 100644 index 0000000..145066d --- /dev/null +++ b/grafana/instaclustr/node-overview.json @@ -0,0 +1,6605 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + }, + { + "name": "VAR_TABLE_DASHBOARD_URL", + "type": "constant", + "label": "table_dashboard_url", + "value": "/d/nfHOqL8ik/table-details", + "description": "" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.4.3" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "panel", + "id": "natel-discrete-panel", + "name": "Discrete", + "version": "0.0.9" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 1, + "id": null, + "iteration": 1574742784877, + "links": [], + "panels": [ + { + "backgroundColor": "rgba(128, 128, 128, 0.1)", + "colorMaps": [ + { + "color": "#3f6833", + "text": "Up" + }, + { + "color": "#890f02", + "text": "Down" + }, + { + "color": "rgb(66, 66, 66)", + "text": "Unknown" + } + ], + "crosshairColor": "#8F070C", + "datasource": "${DS_PROMETHEUS}", + "display": "timeline", + "expandFromQueryS": 0, + "extendLastValue": true, + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 0 + }, + "highlightOnMouseover": true, + "id": 12, + "legendSortBy": "-ms", + "lineColor": "rgba(128, 128, 128, 1.0)", + "links": [], + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "metricNameColor": "rgb(255, 255, 255)", + "options": {}, + "rangeMaps": [ + { + "from": "null", + "text": "Unknown", + "to": "null" + } + ], + "rowHeight": 30, + "showDistinctCount": false, + "showLegend": true, + "showLegendCounts": false, + "showLegendNames": false, + "showLegendPercent": true, + "showLegendTime": true, + "showLegendValues": true, + "showTimeAxis": true, + "showTransitionCount": true, + "targets": [ + { + "expr": "avg(cassandra_endpoint_active{cassandra_cluster=\"$cluster\", endpoint=\"$node\"})", + "format": "time_series", + "intervalFactor": 1, + "refId": "A" + } + ], + "textSize": 18, + "textSizeTime": 12, + "timeOptions": [ + { + "name": "Years", + "value": "years" + }, + { + "name": "Months", + "value": "months" + }, + { + "name": "Weeks", + "value": "weeks" + }, + { + "name": "Days", + "value": "days" + }, + { + "name": "Hours", + "value": "hours" + }, + { + "name": "Minutes", + "value": "minutes" + }, + { + "name": "Seconds", + "value": "seconds" + }, + { + "name": "Milliseconds", + "value": "milliseconds" + } + ], + "timePrecision": { + "name": "Minutes", + "value": "minutes" + }, + "timeTextColor": "#d8d9da", + "title": "Status", + "transparent": true, + "type": "natel-discrete-panel", + "units": "short", + "useTimePrecision": false, + "valueMaps": [ + { + "op": "=", + "text": "Unknown", + "value": "null" + }, + { + "op": "=", + "text": "Up", + "value": "1" + }, + { + "op": "=", + "text": "Down", + "value": "0" + } + ], + "valueTextColor": "rgb(255, 255, 255)", + "writeAllValues": true, + "writeLastValue": true, + "writeMetricNames": false + }, + { + "aliasColors": { + "Reads (rangeslice)": "yellow", + "Reads (read)": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "description": "\n### Notes\n\n`casread` is not included, since `read` already includes `casread` values.", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 4 + }, + "id": 43, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_client_request_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\",operation=~\"read|rangeslice\"}[1m])) by (operation)", + "legendFormat": "Reads ({{operation}})", + "refId": "A" + }, + { + "expr": "sum(irate(cassandra_client_request_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\",operation=~\"read|rangeslice\"}[1m]))", + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Reads/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "rps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Writes (viewwrite)": "semi-dark-yellow", + "Writes (write)": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 4 + }, + "id": 44, + "legend": { + "avg": true, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_client_request_latency_seconds_count{cassandra_node=\"$node\",operation=~\"write|viewwrite\"}[1m])) by (operation)", + "legendFormat": "Writes ({{operation}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Writes/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "wps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Mean Read Latency (rangeslice)": "semi-dark-yellow", + "Mean Read Latency (read)": "blue", + "Read Latency (rangeslice)": "yellow", + "Read Latency (read)": "blue", + "p95 Read Latency (casread)": "semi-dark-green", + "p95 Read Latency (rangeslice)": "semi-dark-yellow", + "p95 Read Latency (read)": "blue", + "p99 Read Latency (casread)": "green", + "p99 Read Latency (rangeslice)": "semi-dark-yellow", + "p99 Read Latency (read)": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 12 + }, + "id": 46, + "legend": { + "alignAsTable": false, + "avg": false, + "current": true, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/p99/", + "dashLength": 3, + "dashes": true + }, + { + "alias": "/p95/", + "dashLength": 3, + "dashes": true, + "spaceLength": 3 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(irate(cassandra_client_request_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"read|rangeslice\"}[1m]) / irate(cassandra_client_request_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"read|rangeslice\"}[1m])) by (operation)", + "hide": false, + "legendFormat": "Mean Read Latency ({{operation}})", + "refId": "D" + }, + { + "expr": "max(cassandra_client_request_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"read|rangeslice\", quantile=\"0.95\"}) by (operation)", + "hide": false, + "legendFormat": "p95 Read Latency ({{operation}})", + "refId": "C" + }, + { + "expr": "max(cassandra_client_request_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"read|rangeslice\", quantile=\"0.99\"}) by (operation)", + "format": "time_series", + "hide": false, + "instant": false, + "legendFormat": "p99 Read Latency ({{operation}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Read Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": { + "Mean Read Latency (viewwrite)": "semi-dark-yellow", + "Mean Read Latency (write)": "blue", + "Mean Write Latency (viewwrite)": "semi-dark-yellow", + "Mean Write Latency (write)": "blue", + "Read Latency (rangeslice)": "yellow", + "Read Latency (read)": "blue", + "p95 Read Latency (casread)": "semi-dark-green", + "p95 Read Latency (rangeslice)": "dark-yellow", + "p95 Read Latency (read)": "blue", + "p95 Read Latency (viewwrite)": "semi-dark-yellow", + "p95 Read Latency (write)": "blue", + "p95 Write Latency (viewwrite)": "semi-dark-yellow", + "p95 Write Latency (write)": "blue", + "p99 Read Latency (casread)": "green", + "p99 Read Latency (rangeslice)": "dark-yellow", + "p99 Read Latency (read)": "blue", + "p99 Read Latency (viewwrite)": "semi-dark-yellow", + "p99 Read Latency (write)": "blue", + "p99 Write Latency (viewwrite)": "semi-dark-yellow", + "p99 Write Latency (write)": "blue" + }, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 12 + }, + "id": 60, + "legend": { + "avg": false, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "/p99/", + "dashLength": 3, + "dashes": true + }, + { + "alias": "/p95/", + "dashLength": 3, + "dashes": true, + "spaceLength": 3 + }, + { + "alias": "p95 Write Latency (write)", + "yaxis": 1 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "max(irate(cassandra_client_request_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"write|viewwrite\"}[1m]) / irate(cassandra_client_request_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"write|viewwrite\"}[1m])) by (operation)", + "hide": false, + "legendFormat": "Mean Write Latency ({{operation}})", + "refId": "A" + }, + { + "expr": "max(cassandra_client_request_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"write|viewwrite\", quantile=\"0.95\"}) by (operation)", + "hide": false, + "legendFormat": "p95 Write Latency ({{operation}})", + "refId": "C" + }, + { + "expr": "max(cassandra_client_request_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"write|viewwrite\", quantile=\"0.99\"}) by (operation)", + "format": "time_series", + "hide": false, + "instant": false, + "legendFormat": "p99 Write Latency ({{operation}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Write Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 114, + "panels": [], + "title": "Top $topn Worst Performing Tables by Storage Engine Performance", + "type": "row" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 21 + }, + "id": 156, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Reads/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "rps" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "Op", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "operation", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"read|range_read\"}[1m])[$__range:])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max Reads/s for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 21 + }, + "id": 136, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Writes/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "wps" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"write\"}[1m])[$__range:])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max Writes/s for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 21 + }, + "id": 146, + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Ops/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "ops" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "Op", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "operation", + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"cas.*\"}[1m])[$__range:])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max CAS Operations/s for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 28 + }, + "id": 111, + "options": {}, + "pageSize": null, + "repeat": "quantile", + "repeatDirection": "v", + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Latency", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "Op", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "operation", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"read|range_read\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Read Latency for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 28 + }, + "id": 166, + "options": {}, + "pageSize": null, + "repeat": "quantile", + "repeatDirection": "v", + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Latency", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "Op", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "operation", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"write\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Write Latency for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 28 + }, + "id": 179, + "options": {}, + "pageSize": null, + "repeat": "quantile", + "repeatDirection": "v", + "showHeader": true, + "sort": { + "col": 13, + "desc": true + }, + "styles": [ + { + "alias": "Latency", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "s" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "Op", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "operation", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", operation=~\"cas.*\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile CAS Operation Latency for Period", + "transform": "table", + "type": "table" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 470, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "description": "_Disk Usage_ includes obsolete SSTables pending garbage collection.", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 0, + "y": 22 + }, + "id": 355, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 11, + "desc": true + }, + "styles": [ + { + "alias": "Disk Usage", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Disk Usage for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 8, + "y": 22 + }, + "id": 464, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 11, + "desc": true + }, + "styles": [ + { + "alias": "Disk Usage", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_live_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Live Disk Usage for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "description": "", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 8, + "x": 16, + "y": 22 + }, + "id": 465, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 11, + "desc": true + }, + "styles": [ + { + "alias": "SSTables", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_live_sstables{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Live SSTables for Period", + "transform": "table", + "type": "table" + } + ], + "title": "Top $topn Worst Performing Tables by Disk Usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 36 + }, + "id": 203, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 23 + }, + "id": 189, + "options": {}, + "pageSize": null, + "repeat": "quantile", + "repeatDirection": "h", + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.5", + "value": "0.5" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Partition Size", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Estimated Partition Size for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 23 + }, + "id": 658, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 189, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.75", + "value": "0.75" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Partition Size", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Estimated Partition Size for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 23 + }, + "id": 659, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 189, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.95", + "value": "0.95" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Partition Size", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Estimated Partition Size for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 23 + }, + "id": 660, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 189, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.99", + "value": "0.99" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Partition Size", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "bytes" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Estimated Partition Size for Period", + "transform": "table", + "type": "table" + } + ], + "title": "Top $topn Worst Performing Tables by Estimated Partition Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 37 + }, + "id": 457, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 24 + }, + "id": 449, + "options": {}, + "pageSize": null, + "repeat": "quantile", + "repeatDirection": "h", + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.5", + "value": "0.5" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Tombstones Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Tombstones per Read for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 24 + }, + "id": 661, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 449, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.75", + "value": "0.75" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Tombstones Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Tombstones per Read for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 24 + }, + "id": 662, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 449, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.95", + "value": "0.95" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Tombstones Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Tombstones per Read for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 24 + }, + "id": 663, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 449, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.99", + "value": "0.99" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Tombstones Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile Tombstones per Read for Period", + "transform": "table", + "type": "table" + } + ], + "title": "Top $topn Worst Performing Tables by Tombstones Per Read", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 38 + }, + "id": 239, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 0, + "y": 25 + }, + "id": 216, + "options": {}, + "pageSize": null, + "repeat": "quantile", + "repeatDirection": "h", + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.5", + "value": "0.5" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "SSTables Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile SSTables Per Read for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 6, + "y": 25 + }, + "id": 664, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 216, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.75", + "value": "0.75" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "SSTables Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile SSTables Per Read for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 12, + "y": 25 + }, + "id": 665, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 216, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.95", + "value": "0.95" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "SSTables Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile SSTables Per Read for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 6, + "x": 18, + "y": 25 + }, + "id": 666, + "options": {}, + "pageSize": null, + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596509, + "repeatPanelId": 216, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.99", + "value": "0.99" + } + }, + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "SSTables Per Read", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_11}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max q=$quantile SSTables Per Read for Period", + "transform": "table", + "type": "table" + } + ], + "title": "Top $topn Worst Performing Tables by SSTables Per Read", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 39 + }, + "id": 258, + "panels": [ + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 255, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Pending Compactions", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(cassandra_table_estimated_pending_compactions{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[$__range])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max Estimated Pending Compactions for Period", + "transform": "table", + "type": "table" + }, + { + "columns": [], + "datasource": "${DS_PROMETHEUS}", + "fontSize": "100%", + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 256, + "links": [], + "options": {}, + "pageSize": null, + "repeatDirection": "h", + "showHeader": true, + "sort": { + "col": 12, + "desc": true + }, + "styles": [ + { + "alias": "Bytes Written/s", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "link": false, + "pattern": "Value", + "thresholds": [], + "type": "number", + "unit": "Bps" + }, + { + "alias": "Table", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "link": true, + "linkTooltip": "View ${__cell} details.", + "linkUrl": "${table_dashboard_url:raw}?var-cluster=${cluster}&var-node=${node}&var-table_type=All&var-keyspace=${__cell_8}&var-table=${__cell_10}&from=${__from}&to=${__to}", + "mappingType": 1, + "pattern": "__name", + "thresholds": [], + "type": "string", + "unit": "short", + "valueMaps": [] + }, + { + "alias": "Op", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "operation", + "thresholds": [], + "type": "number", + "unit": "short" + }, + { + "alias": "", + "colorMode": null, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "/.*/", + "thresholds": [], + "type": "hidden", + "unit": "short" + } + ], + "targets": [ + { + "expr": "label_join(label_join(topk($topn,max_over_time(irate(cassandra_table_compaction_bytes_written_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[1m])[$__range:])), \"__name\", \".\", \"keyspace\", \"table\"), \"__name\", \":\", \"table_type\", \"__name\")", + "format": "table", + "instant": true, + "legendFormat": "", + "refId": "A" + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Top $topn Tables by Max Compaction Bytes Written/s for Period", + "transform": "table", + "type": "table" + } + ], + "title": "Top $topn Worst Performing Tables by Compaction Stats", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 106, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 558, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_pending_tasks{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}", + "instant": false, + "legendFormat": "Segments", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Segments Pending fsync", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 560, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_commit_log_completed_tasks_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[1m])", + "instant": false, + "legendFormat": "Segments", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Segments Written/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 35 + }, + "id": 101, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "quantile", + "repeatDirection": "h", + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.5", + "value": "0.5" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_commit_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Commit Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 35 + }, + "id": 649, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596507, + "repeatPanelId": 101, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.75", + "value": "0.75" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_commit_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Commit Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 35 + }, + "id": 650, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596507, + "repeatPanelId": 101, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.95", + "value": "0.95" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_commit_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Commit Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 35 + }, + "id": 651, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596507, + "repeatPanelId": 101, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.99", + "value": "0.99" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_commit_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Commit Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 43 + }, + "id": 559, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "quantile", + "repeatDirection": "h", + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.5", + "value": "0.5" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_segment_allocation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Segment Allocation Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 43 + }, + "id": 652, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596507, + "repeatPanelId": 559, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.75", + "value": "0.75" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_segment_allocation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Segment Allocation Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 43 + }, + "id": 653, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596507, + "repeatPanelId": 559, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.95", + "value": "0.95" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_segment_allocation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Segment Allocation Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 43 + }, + "id": 654, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1573767596507, + "repeatPanelId": 559, + "scopedVars": { + "quantile": { + "selected": false, + "text": "0.99", + "value": "0.99" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_commit_log_segment_allocation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", quantile=~\"$quantile\"}", + "instant": false, + "legendFormat": "Latency", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "q=$quantile Segment Allocation Latency", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Commit Log", + "type": "row" + }, + { + "collapsed": false, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 93, + "panels": [], + "repeat": null, + "title": "Thread Pools", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 42 + }, + "id": 90, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "thread_pool", + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_thread_pool_active_tasks{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", pool=\"$thread_pool\"}", + "legendFormat": "{{pool}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$thread_pool Active Tasks", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Tasks", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 42 + }, + "id": 89, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "thread_pool", + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_thread_pool_blocked_tasks_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", pool=\"$thread_pool\"}[1m])", + "legendFormat": "{{pool}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$thread_pool Blocked Tasks/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Tasks/s", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 42 + }, + "id": 91, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "thread_pool", + "repeatDirection": "v", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_thread_pool_completed_tasks_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\", pool=\"$thread_pool\"}[1m])", + "legendFormat": "{{pool}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "$thread_pool Completed Tasks/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Tasks/s", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 50 + }, + "id": 84, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 81, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_buffer_pool_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}", + "legendFormat": "Size", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Buffer Pool Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 82, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_buffer_pool_misses_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[1m])", + "legendFormat": "Size", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Buffer Pool Misses/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Misses", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Buffer Pool", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 51 + }, + "id": 74, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 46 + }, + "id": 648, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_os_recent_cpu_load_ratio{cassandra_node=\"$node\"}", + "legendFormat": "Host Total", + "refId": "A" + }, + { + "expr": "cassandra_process_recent_cpu_load_ratio{cassandra_node=\"$node\"}", + "legendFormat": "Process", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 46 + }, + "id": 26, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_os_1m_load_average{cassandra_node=\"$node\"}", + "legendFormat": "Load", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "OS 1 Minute Load Average", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 54 + }, + "id": 70, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Maximum", + "color": "#C4162A", + "fill": 0, + "legend": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_process_open_file_descriptors{cassandra_node=\"$node\"}", + "legendFormat": "Open File Descriptors", + "refId": "A" + }, + { + "expr": "cassandra_process_maximum_file_descriptors{cassandra_node=\"$node\"}", + "legendFormat": "Maximum", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Open File Descriptors", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 54 + }, + "id": 72, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "X", + "lines": false, + "yaxis": 2 + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "(cassandra_storage_filesystem_bytes_total{cassandra_node=\"$node\"} - cassandra_storage_filesystem_usable_bytes{cassandra_node=\"$node\"}) / cassandra_storage_filesystem_bytes_total{cassandra_node=\"$node\"}", + "legendFormat": "{{spec}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Used", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": "1", + "min": "0", + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "OS Stats", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 59, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 38 + }, + "id": 30, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_client_native_connections{cassandra_node=\"$node\"}", + "legendFormat": "Connections", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Connections", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 38 + }, + "id": 85, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": false, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_client_authentication_failures_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[1m])", + "legendFormat": "Size", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Client Authentication Failures/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Failures", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 38 + }, + "id": 55, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_cql_statements_executed_total{cassandra_node=\"$node\"}[1m])", + "legendFormat": "{{statement_type}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "CQL Statements Executed/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Clients", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 78, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 64 + }, + "id": 48, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(cassandra_storage_hints_total{cassandra_node=\"$node\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Hints in Progress/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Hints in Progress", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 64 + }, + "id": 14, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_dropped_messages_total{cassandra_cluster=\"$cluster\", cassandra_node=\"$node\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{message_type}}", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dropped Messages/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": false + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Internode", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 54 + }, + "id": 40, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 34 + }, + "id": 35, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_table_operation_latency_seconds_count{cassandra_node=\"$node\",operation=~\"read|range_read\"}[1m])) by (operation)", + "legendFormat": "Reads ({{operation}})", + "refId": "A" + }, + { + "expr": "sum(irate(cassandra_table_operation_latency_seconds_count{cassandra_node=\"$node\",operation=~\"read|range_read\"}[1m]))", + "hide": true, + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Storage Engine Reads/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "rps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "wps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": true, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 34 + }, + "id": 32, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_table_operation_latency_seconds_count{cassandra_node=\"$node\",operation=\"write\"}[1m])) by (operation)", + "hide": false, + "legendFormat": "Writes", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Storage Engine Writes/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "wps", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "none", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": true, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 34 + }, + "id": 41, + "legend": { + "alignAsTable": false, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_table_operation_latency_seconds_count{cassandra_node=\"$node\",operation=~\"cas_.+\"}[1m])) by (operation)", + "legendFormat": "CAS ({{operation}})", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Storage Engine CAS Ops/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": null, + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "wps", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": true, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 42 + }, + "id": 24, + "legend": { + "avg": true, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(cassandra_table_estimated_pending_compactions{cassandra_node=\"$node\"}) by (compaction_strategy_class)", + "legendFormat": "{{compaction_strategy_class}}", + "refId": "A" + }, + { + "expr": "sum(cassandra_table_estimated_pending_compactions{cassandra_node=\"$node\"})", + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Estimated Pending Compactions by Strategy", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Pending Compactions", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 42 + }, + "id": 79, + "legend": { + "avg": true, + "current": true, + "max": false, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false + } + ], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(irate(cassandra_table_compaction_bytes_written_total{cassandra_node=\"$node\"}[1m])) by (compaction_strategy_class)", + "legendFormat": "{{compaction_strategy_class}}", + "refId": "A" + }, + { + "expr": "sum(irate(cassandra_table_compaction_bytes_written_total{cassandra_node=\"$node\"}[1m]))", + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compactions Bytes Written/s by Strategy", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Storage Engine", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 55 + }, + "id": 62, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 66 + }, + "id": 20, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_jvm_memory_pool_used_bytes{cassandra_node=~\"$node\"}", + "legendFormat": "{{pool}} ({{type}})", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memory Pool Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 66 + }, + "id": 64, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_jvm_nio_buffer_pool_estimated_buffers{cassandra_node=\"$node\"}", + "legendFormat": "{{pool}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "NIO Buffer Count", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 66 + }, + "id": 66, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_jvm_nio_buffer_pool_estimated_used_bytes{cassandra_node=\"$node\"}", + "legendFormat": "{{pool}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "NIO Buffer Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 74 + }, + "id": 22, + "legend": { + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "rate(cassandra_jvm_gc_estimated_collection_duration_seconds_total{cassandra_node=\"$node\"}[1m])", + "legendFormat": "{{collector}}", + "refId": "A" + }, + { + "expr": "sum(rate(cassandra_jvm_gc_estimated_collection_duration_seconds_total{cassandra_node=\"$node\"}[1m]))", + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM GC Duration", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 74 + }, + "id": 546, + "legend": { + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_jvm_gc_collection_count{cassandra_node=\"$node\"}[1m])", + "legendFormat": "{{collector}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM GC/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 82 + }, + "id": 547, + "legend": { + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Total", + "lines": false, + "stack": false + } + ], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_jvm_thread_count{cassandra_node=\"$node\"}", + "legendFormat": "{{type}}", + "refId": "A" + }, + { + "expr": "sum(cassandra_jvm_thread_count{cassandra_node=\"$node\"})", + "legendFormat": "Total", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM Threads", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 82 + }, + "id": 548, + "legend": { + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_jvm_threads_started_total{cassandra_node=\"$node\"}[1m])", + "legendFormat": "Threads", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "JVM Threads Started/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "JVM", + "type": "row" + } + ], + "refresh": false, + "schemaVersion": 20, + "style": "dark", + "tags": [ + "cassandra" + ], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_endpoint_active, cassandra_cluster)", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": "label_values(cassandra_endpoint_active, cassandra_cluster)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"}, cassandra_node)", + "hide": 0, + "includeAll": false, + "label": "Node", + "multi": false, + "name": "node", + "options": [], + "query": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"}, cassandra_node)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\", cassandra_datacenter=~\"$datacenter\", cassandra_rack=\"$tag\"}, cassandra_node)", + "tags": [], + "tagsQuery": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\", cassandra_datacenter=~\"$datacenter\"}, cassandra_rack)", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_thread_pool_active_tasks{cassandra_cluster=\"$cluster\"}, pool)", + "hide": 0, + "includeAll": true, + "label": "Thread Pool", + "multi": true, + "name": "thread_pool", + "options": [], + "query": "label_values(cassandra_thread_pool_active_tasks{cassandra_cluster=\"$cluster\"}, pool)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "tags": [], + "text": "All", + "value": [ + "$__all" + ] + }, + "hide": 0, + "includeAll": true, + "label": "Quantile", + "multi": true, + "name": "quantile", + "options": [ + { + "selected": true, + "text": "All", + "value": "$__all" + }, + { + "selected": false, + "text": "0.5", + "value": "0.5" + }, + { + "selected": false, + "text": "0.75", + "value": "0.75" + }, + { + "selected": false, + "text": "0.95", + "value": "0.95" + }, + { + "selected": false, + "text": "0.99", + "value": "0.99" + } + ], + "query": "0.5,0.75,0.95,0.99", + "skipUrlSync": false, + "type": "custom" + }, + { + "allValue": null, + "current": { + "tags": [], + "text": "10", + "value": "10" + }, + "hide": 0, + "includeAll": false, + "label": "Top 𝑛", + "multi": false, + "name": "topn", + "options": [ + { + "selected": true, + "text": "5", + "value": "5" + }, + { + "selected": false, + "text": "10", + "value": "10" + }, + { + "selected": false, + "text": "20", + "value": "20" + } + ], + "query": "5,10,20", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "value": "${VAR_TABLE_DASHBOARD_URL}", + "text": "${VAR_TABLE_DASHBOARD_URL}" + }, + "hide": 2, + "label": null, + "name": "table_dashboard_url", + "options": [ + { + "value": "${VAR_TABLE_DASHBOARD_URL}", + "text": "${VAR_TABLE_DASHBOARD_URL}" + } + ], + "query": "${VAR_TABLE_DASHBOARD_URL}", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Node Overview", + "uid": "WZGSOV8mk", + "version": 75 +} \ No newline at end of file diff --git a/grafana/instaclustr/table-details.json b/grafana/instaclustr/table-details.json new file mode 100644 index 0000000..b032dc5 --- /dev/null +++ b/grafana/instaclustr/table-details.json @@ -0,0 +1,7651 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "6.4.3" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "gnetId": null, + "graphTooltip": 1, + "id": null, + "iteration": 1574742809825, + "links": [], + "panels": [ + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 26, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 3, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Disk Usage (inc. obsolete SSTables pending GC)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 1 + }, + "id": 13, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_live_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Live Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 12, + "y": 1 + }, + "id": 111, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_snapshots_size_bytes_total{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Snapshot Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 1 + }, + "id": 15, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_live_sstables{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Live SSTables", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "SSTables", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Disk Usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 38, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 2 + }, + "id": 40, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "operation", + "repeatDirection": "h", + "scopedVars": { + "operation": { + "selected": false, + "text": "read", + "value": "read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ops/s ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 4, + "y": 2 + }, + "id": 293, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 40, + "scopedVars": { + "operation": { + "selected": false, + "text": "write", + "value": "write" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ops/s ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 2 + }, + "id": 294, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 40, + "scopedVars": { + "operation": { + "selected": false, + "text": "range_read", + "value": "range_read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ops/s ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 12, + "y": 2 + }, + "id": 295, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 40, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ops/s ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 16, + "y": 2 + }, + "id": 296, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 40, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ops/s ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 2 + }, + "id": 297, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 40, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Ops/s ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "ops", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 10 + }, + "id": 46, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "operation", + "repeatDirection": "h", + "scopedVars": { + "operation": { + "selected": false, + "text": "read", + "value": "read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m]) / irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Mean Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 4, + "y": 10 + }, + "id": 298, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 46, + "scopedVars": { + "operation": { + "selected": false, + "text": "write", + "value": "write" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m]) / irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Mean Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 10 + }, + "id": 299, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 46, + "scopedVars": { + "operation": { + "selected": false, + "text": "range_read", + "value": "range_read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m]) / irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Mean Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 12, + "y": 10 + }, + "id": 300, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 46, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m]) / irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Mean Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 16, + "y": 10 + }, + "id": 301, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 46, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m]) / irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Mean Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 10 + }, + "id": 302, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 46, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_operation_latency_seconds_sum{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m]) / irate(cassandra_table_operation_latency_seconds_count{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\"}[1m])", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Mean Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 18 + }, + "id": 79, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "operation", + "repeatDirection": "h", + "scopedVars": { + "operation": { + "selected": false, + "text": "read", + "value": "read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 4, + "y": 18 + }, + "id": 303, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 79, + "scopedVars": { + "operation": { + "selected": false, + "text": "write", + "value": "write" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 18 + }, + "id": 304, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 79, + "scopedVars": { + "operation": { + "selected": false, + "text": "range_read", + "value": "range_read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 12, + "y": 18 + }, + "id": 305, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 79, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 16, + "y": 18 + }, + "id": 306, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 79, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 18 + }, + "id": 307, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 79, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 26 + }, + "id": 80, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "operation", + "repeatDirection": "h", + "scopedVars": { + "operation": { + "selected": false, + "text": "read", + "value": "read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 4, + "y": 26 + }, + "id": 308, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 80, + "scopedVars": { + "operation": { + "selected": false, + "text": "write", + "value": "write" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 26 + }, + "id": 309, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 80, + "scopedVars": { + "operation": { + "selected": false, + "text": "range_read", + "value": "range_read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 12, + "y": 26 + }, + "id": 310, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 80, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 16, + "y": 26 + }, + "id": 311, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 80, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 26 + }, + "id": 312, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 80, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 34 + }, + "id": 57, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "operation", + "repeatDirection": "h", + "scopedVars": { + "operation": { + "selected": false, + "text": "read", + "value": "read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 4, + "y": 34 + }, + "id": 313, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 57, + "scopedVars": { + "operation": { + "selected": false, + "text": "write", + "value": "write" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 34 + }, + "id": 314, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 57, + "scopedVars": { + "operation": { + "selected": false, + "text": "range_read", + "value": "range_read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 12, + "y": 34 + }, + "id": 315, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 57, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 16, + "y": 34 + }, + "id": 316, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 57, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 34 + }, + "id": 317, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 57, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 42 + }, + "id": 58, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": "operation", + "repeatDirection": "h", + "scopedVars": { + "operation": { + "selected": false, + "text": "read", + "value": "read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 4, + "y": 42 + }, + "id": 318, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 58, + "scopedVars": { + "operation": { + "selected": false, + "text": "write", + "value": "write" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 8, + "y": 42 + }, + "id": 319, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 58, + "scopedVars": { + "operation": { + "selected": false, + "text": "range_read", + "value": "range_read" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 12, + "y": 42 + }, + "id": 320, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 58, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 16, + "y": 42 + }, + "id": 321, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 58, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 4, + "x": 20, + "y": 42 + }, + "id": 322, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeat": null, + "repeatDirection": "h", + "repeatIteration": 1574128252863, + "repeatPanelId": 58, + "scopedVars": { + "operation": { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + }, + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_operation_latency_seconds{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", operation=\"$operation\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Latency ($operation)", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "repeat": null, + "title": "Storage Engine Performance", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 2 + }, + "id": 288, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 51 + }, + "id": 289, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_columns{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Estimated Rows per Partition", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Rows", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 51 + }, + "id": 290, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_columns{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Estimated Rows per Partition", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Rows", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 51 + }, + "id": 291, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_columns{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Estimated Rows per Partition", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Rows", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 51 + }, + "id": 292, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_columns{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Estimated Rows per Partition", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Rows", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Estimated Rows Per Partition", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 252, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 13 + }, + "id": 253, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 SSTables Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "SSTables", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 13 + }, + "id": 254, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 SSTables Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "SSTables", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 13 + }, + "id": 255, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 SSTables Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "SSTables", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 13 + }, + "id": 256, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_sstables_per_read{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 SSTables Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "SSTables", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "SSTables Per Read", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 242, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 5 + }, + "id": 243, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Estimated Partition Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 5 + }, + "id": 244, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Estimated Partition Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 5 + }, + "id": 245, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Estimated Partition Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 5 + }, + "id": 246, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_partition_size_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Estimated Partition Size", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Estimated Partition Size", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 145, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 0, + "y": 6 + }, + "id": 176, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.5\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p50 Tombstones Scanned Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Tombstones", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 6, + "y": 6 + }, + "id": 208, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.75\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p75 Tombstones Scanned Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 12, + "y": 6 + }, + "id": 209, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.95\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p95 Tombstones Scanned Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 6, + "x": 18, + "y": 6 + }, + "id": 210, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "maxPerRow": 6, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 2, + "points": false, + "renderer": "flot", + "repeatDirection": "h", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_tombstones_scanned{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", quantile=\"0.99\"}", + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "p99 Tombstones Scanned Per Read", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Tombstones Scanned Per Read", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 250, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 5, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_compression_ratio{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compression Ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 10, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_compression_metadata_offheap_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compression Metadata Off-Heap Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Compression", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 248, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 14, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_key_cache_hit_ratio{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Key Cache Hit Ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 143, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_row_cache_hits{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"} / (cassandra_table_row_cache_hits{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"} + cassandra_table_row_cache_misses{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Row Cache Hit Ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Caches", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 30, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 18 + }, + "id": 18, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_memory_used_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", pool=\"memtable\", region=\"off_heap\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memtable Off-heap Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 18 + }, + "id": 19, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_memory_used_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", pool=\"memtable\", region=\"on_heap\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memtable On-heap Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 18 + }, + "id": 21, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_memtable_live_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memtable Live Data Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 27 + }, + "id": 22, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_memtable_switches{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}[1m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memtable Switches/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Switches", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 27 + }, + "id": 20, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_memtable_columns{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Memtable Columns", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Columns", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Memtable Details", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 32, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 19 + }, + "id": 2, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_pending_compactions{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Estimated Pending Compactions", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Compactions", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 19 + }, + "id": 4, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_compaction_bytes_written_total{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Compaction Bytes Written/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Compaction", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 34, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 0, + "y": 11 + }, + "id": 16, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_memory_used_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", pool=\"bloom_filter\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bloom Filter Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 6, + "y": 11 + }, + "id": 7, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_bloom_filter_disk_space_used_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bloom Filter Disk Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 12, + "y": 11 + }, + "id": 8, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_bloom_filter_false_positives_total{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bloom Filter False Positives/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "False Positives", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 6, + "x": 18, + "y": 11 + }, + "id": 9, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_bloom_filter_false_ratio{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bloom Filter False Positives Ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Bloom Filter", + "type": "row" + }, + { + "collapsed": true, + "datasource": "${DS_PROMETHEUS}", + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 11 + }, + "id": 36, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 21 + }, + "id": 23, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_pending_flushes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Pending Flushes", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Flushes", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 21 + }, + "id": 12, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_flushed_bytes_total{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Bytes Flushed/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 30 + }, + "id": 17, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_memory_used_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\", pool=\"index_summary\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Index Summary Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 30 + }, + "id": 24, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_repaired_ratio{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Repaired Ratio", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 39 + }, + "id": 6, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "cassandra_table_estimated_partitions{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Estimated Partitions", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": "Partitions", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 39 + }, + "id": 142, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_speculative_retries_total{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Speculative Retries/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "cps", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "${DS_PROMETHEUS}", + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 48 + }, + "id": 11, + "legend": { + "avg": true, + "current": true, + "max": true, + "min": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null as zero", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "irate(cassandra_table_dropped_mutations_total{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table=\"$table\"}[5m])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{cassandra_node}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Dropped Mutations/s", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "cps", + "label": "", + "logBase": 1, + "max": null, + "min": "0", + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "title": "Misc", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 20, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "allValue": null, + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_endpoint_active, cassandra_cluster)", + "hide": 0, + "includeAll": false, + "label": "Cluster", + "multi": false, + "name": "cluster", + "options": [], + "query": "label_values(cassandra_endpoint_active, cassandra_cluster)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"}, cassandra_node)", + "hide": 0, + "includeAll": true, + "label": "Node", + "multi": true, + "name": "node", + "options": [], + "query": "label_values(cassandra_endpoint_active{cassandra_cluster=\"$cluster\"}, cassandra_node)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\"}, table_type)", + "hide": 0, + "includeAll": true, + "label": "Type", + "multi": true, + "name": "table_type", + "options": [], + "query": "label_values(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\"}, table_type)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", table_type=~\"$table_type\"}, keyspace)", + "hide": 0, + "includeAll": false, + "label": "Keyspace", + "multi": false, + "name": "keyspace", + "options": [], + "query": "label_values(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", table_type=~\"$table_type\"}, keyspace)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": {}, + "datasource": "${DS_PROMETHEUS}", + "definition": "label_values(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table_type=~\"$table_type\"}, table)", + "hide": 0, + "includeAll": false, + "label": "Table", + "multi": false, + "name": "table", + "options": [], + "query": "label_values(cassandra_table_disk_space_bytes{cassandra_cluster=\"$cluster\", cassandra_node=~\"$node\", keyspace=\"$keyspace\", table_type=~\"$table_type\"}, table)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": null, + "current": { + "text": "All", + "value": [ + "$__all" + ] + }, + "hide": 0, + "includeAll": true, + "label": null, + "multi": true, + "name": "operation", + "options": [ + { + "selected": true, + "text": "All", + "value": "$__all" + }, + { + "selected": false, + "text": "read", + "value": "read" + }, + { + "selected": false, + "text": "write", + "value": "write" + }, + { + "selected": false, + "text": "range_read", + "value": "range_read" + }, + { + "selected": false, + "text": "cas_propose", + "value": "cas_propose" + }, + { + "selected": false, + "text": "cas_prepare", + "value": "cas_prepare" + }, + { + "selected": false, + "text": "cas_commit", + "value": "cas_commit" + } + ], + "query": "read,write,range_read,cas_propose,cas_prepare,cas_commit", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "Table Details", + "uid": "nfHOqL8ik", + "version": 36 +} \ No newline at end of file diff --git a/standalone/pom.xml b/standalone/pom.xml index d539c16..fc6ea01 100644 --- a/standalone/pom.xml +++ b/standalone/pom.xml @@ -16,7 +16,7 @@ 18.0 3.4.0 - 4.0.47.Final + 4.1.42.Final 1.2.3 1.7.16 diff --git a/standalone/src/main/java/com/zegelin/cassandra/exporter/Application.java b/standalone/src/main/java/com/zegelin/cassandra/exporter/Application.java index 4ceb30e..6a602ec 100644 --- a/standalone/src/main/java/com/zegelin/cassandra/exporter/Application.java +++ b/standalone/src/main/java/com/zegelin/cassandra/exporter/Application.java @@ -6,7 +6,6 @@ import com.datastax.driver.core.policies.RoundRobinPolicy; import com.datastax.driver.core.policies.WhiteListPolicy; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.zegelin.picocli.InetSocketAddressTypeConverter; import com.zegelin.picocli.JMXServiceURLTypeConverter; import com.zegelin.cassandra.exporter.cli.HarvesterOptions; @@ -78,6 +77,9 @@ protected int defaultPort() { @Option(names = "--cql-password", paramLabel = "PASSWORD", description = "CQL authentication password.") private String cqlPassword; + + @Option(names = "--cql-ssl", paramLabel = "PASSWORD", description = "Native connection to be encrypted") + private boolean ssl; @Option(names = {"-v", "--verbose"}, description = "Enable verbose logging. Multiple invocations increase the verbosity.") boolean[] verbosity = {}; @@ -128,7 +130,7 @@ public void onMaterializedViewRemoved(final MaterializedViewMetadata view) { }); - Server.start(httpServerOptions.listenAddresses, harvester, httpServerOptions.helpExposition); + Server.start(harvester, httpServerOptions); return null; } @@ -145,6 +147,9 @@ private Cluster establishClusterConnection() { if (cqlUser != null && cqlPassword != null) { clusterBuilder.withCredentials(cqlUser, cqlPassword); } + if(ssl) { + clusterBuilder.withSSL(); + } final Cluster cluster = clusterBuilder.build(); diff --git a/standalone/src/main/java/com/zegelin/cassandra/exporter/JMXHarvester.java b/standalone/src/main/java/com/zegelin/cassandra/exporter/JMXHarvester.java index 44b07db..a5f8a40 100644 --- a/standalone/src/main/java/com/zegelin/cassandra/exporter/JMXHarvester.java +++ b/standalone/src/main/java/com/zegelin/cassandra/exporter/JMXHarvester.java @@ -33,31 +33,43 @@ public class JMXHarvester extends Harvester { addCollectorFactory(RemoteGossiperMBeanMetricFamilyCollector.factory(metadataFactory)); } - private Set currentMBeans = ImmutableSet.of(); + private Set currentMBeans = Sets.newHashSet(); void reconcileMBeans() { try { - final Set mBeans = mBeanServerConnection.queryMBeans(null, null); + final Set newMBeans = mBeanServerConnection.queryMBeans(null, null); // unregister { - final Set removedMBeans = Sets.difference(currentMBeans, mBeans); + final Set removedMBeans = Sets.difference(currentMBeans, newMBeans); logger.debug("Removing {} old MBeans.", removedMBeans.size()); for (final ObjectInstance instance : removedMBeans) { unregisterMBean(instance.getObjectName()); + currentMBeans.remove(instance); } } // register { - final Set addedMBeans = Sets.difference(mBeans, currentMBeans); + final Set addedMBeans = Sets.difference(newMBeans, currentMBeans); logger.debug("Found {} new MBeans.", addedMBeans.size()); for (final ObjectInstance instance : addedMBeans) { - final MBeanInfo mBeanInfo = mBeanServerConnection.getMBeanInfo(instance.getObjectName()); + final MBeanInfo mBeanInfo; + try { + mBeanInfo = mBeanServerConnection.getMBeanInfo(instance.getObjectName()); + + } catch (final InstanceNotFoundException e) { + // We may get an InstanceNotFoundException if the mBean was + // really short lived (such as for a repair job or similar) + // and Cassandra unregistered it between the probe and this + // instance being evaluated + continue; + } + final Descriptor mBeanDescriptor = mBeanInfo.getDescriptor(); final String interfaceClassName = (String) mBeanDescriptor.getFieldValue(JMX.INTERFACE_CLASS_NAME_FIELD); @@ -79,7 +91,7 @@ void reconcileMBeans() { logger.debug("Registering MBean/MXBean {}.", instance); - final boolean isMXBean = Boolean.valueOf((String) mBeanDescriptor.getFieldValue(JMX.MXBEAN_FIELD)); + final boolean isMXBean = Boolean.parseBoolean((String) mBeanDescriptor.getFieldValue(JMX.MXBEAN_FIELD)); final ObjectName objectName = instance.getObjectName(); final Object mBeanProxy; @@ -90,11 +102,10 @@ void reconcileMBeans() { } registerMBean(mBeanProxy, objectName); + currentMBeans.add(instance); } } - currentMBeans = mBeans; - } catch (final Throwable e) { logger.error("Failed to reconcile MBeans.", e); }