Code Monkey home page Code Monkey logo

cassandra-exporter's Introduction

cassandra-exporter CircleCI

cassandra-exporter is a Java agent (with optional standalone mode) that exports Cassandra metrics to Prometheus.

Project Status: beta

Note - The Cassandra-Exporter tool does not support all versions of Cassandra, see the compatibility section for more details on supported versions.

Introduction

cassandra-exporter enables high performance collection of Cassandra metrics and follows the Prometheus best practices for metrics naming and labeling.

Benchamrk Results

cassandra-exporter is fast. In a worst-case benchmark, where the Cassandra schema contains 1000+ tables (resulting in ~174 thousand metrics), cassandra-exporter completes exposition in ~140ms. Compared to the next-best, jmx_exporter, which completes exposition in ~8 seconds. Other solutions can take tens of seconds, during which CPU time is consumed querying JMX and serialising values.

See the Exported Metrics wiki page for a list of available metrics.

All but a few select metrics exposed by cassandra-exporter are live with no caching involved. The few that are cached are done so for performance reasons.

cassandra-exporter exports metric families, where the names, labels, metric types (gauge, counter, summary, etc), and value scales have been hand-tuned to produce easy-to-query output.

For example, the following PromQL query will return an estimate of the number of pending compactions per-keyspace, per-node.

sum(cassandra_table_estimated_pending_compactions) by (cassandra_node, keyspace)

Compatibility

cassandra-exporter is now Cassandra 4.0+ compatible, but the change is not a backwards compatible. Support for older Cassandra versions is via the older releases, as follows:

Cassandra Version Compatible Exporter Version
Apache Cassandra 4.1.4+ 0.9.14
Apache Cassandra 4.0 up to 4.1.3 0.9.13
Apache Cassandra 4.0 up to 4.1.3 0.9.12
Apache Cassandra 3.0.17, 3.11.2, 3.11.3 0.9.11
Prometheus Version
2.42.0

| Other Cassandra and Prometheus versions will be tested for compatibility in the future.

Usage

Agent

Download the latest release and copy cassandra-exporter-agent-<version>.jar to $CASSANDRA_HOME/lib (typically /usr/share/cassandra/lib in most package installs).

Then edit $CASSANDRA_CONF/cassandra-env.sh (typically /etc/cassandra/cassandra-env.sh) and append the following:

JVM_OPTS="$JVM_OPTS -javaagent:$CASSANDRA_HOME/lib/cassandra-exporter-agent-<version>.jar"

Then (re-)start Cassandra.

Prometheus metrics will now be available at http://localhost:9500/metrics.

Standalone

While it is preferable to run cassandra-exporter as a Java agent for performance, it can instead be run as an external application if required.

Download the latest release and copy cassandra-exporter-standalone-<version>.jar to a location of your choosing.

The exporter can be started via java -jar /path/to/cassandra-exporter-standalone-<version>.jar.

Prometheus metrics will now be available at http://localhost:9500/metrics.

In this mode metrics will be queried via JMX which will incur a performance overhead. The standalone mode was originally designed to assist with benchmarking and development of the exporter.

The set of metrics available is close to that of the agent -- Gossiper related metrics are unavailable as these aren't readily available over JMX.

Currently some additional metadata labels, such as the table type (table, index, view, etc) attached to the cassandra_table_* metrics, are not available (this feature has yet to be written).

Prometheus Configuration

Configure Prometheus to scrape the endpoint by adding the following to prometheus.yml:

scrape_configs:
  ...
  
  - job_name: 'cassandra'
    static_configs:
      - targets: ['<cassandra node IP>:9500', '<cassandra node IP>:9500', '<cassandra node IP>:9500', ...]

See the Prometheus documentation for more details on configuring scrape targets.

To view the raw, plain text metrics (in the Prometheus text exposition format), request the endpoint (by default, http://localhost:9500/metrics) with a HTTP client such as a browser or cURL.

Experimental JSON output is also provided if the Accept: application/json header or ?x-accept=application/json URL parameter is specified. The format/structure of the JSON output is subject to change.

Options

The available command line options may be seen by passing -h/--help:

Usage: cassandra-exporter [-hV] [--enable-collector-timing]
                          [--enable-per-thread-cpu-times]
                          [--exclude-system-tables] [--no-fast-float]
                          [--no-global-labels] [--no-table-labels] [-v]...
                          [--cql-address=[ADDRESS][:PORT]]
                          [--cql-password=PASSWORD] [--cql-user=NAME]
                          [--family-help=VALUE] [--jmx-password=PASSWORD]
                          [--jmx-service-url=URL] [--jmx-user=NAME]
                          [--keyspace-metrics=FILTER] [--node-metrics=FILTER]
                          [--table-metrics=FILTER]
                          [--exclude-keyspaces=<excludedKeyspaces>]...
                          [--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...]
                            Select which global labels to include on all exported
                              metrics. Valid options are: 'CLUSTER' (cluster name),
                              'NODE' (node endpoint IP address), 'DATACENTER' (DC
                              name), 'RACK' (rack name). The default is to include
                              all global labels except HOST_ID. To disable all
                              global labels use --no-global-labels.
  -t, --table-labels=LABEL[,LABEL...]
                            Select which labels to include on table-level metrics.
                              Valid options are: 'TABLE_TYPE' (table, view or
                              index), 'INDEX_TYPE' (for indexes -- keys, composites
                              or custom), 'INDEX_CLASS' (the index class name for
                              custom indexes),  'COMPACTION_STRATEGY_CLASS' (for
                              tables & views, compaction-related metrics only). The
                              default is to include all table labels. To disable all
                              table labels use --no-table-labels.
      --table-metrics=FILTER
                            Select which table-level metrics to expose. Valid
                              options are: 'ALL' (all metrics), 'HISTOGRAMS' (only
                              histograms & summaries), 'NONE' (no metrics). The
                              default is 'ALL'.
      --keyspace-metrics=FILTER
                            Select which keyspace-level aggregate metrics to expose.
                              Valid options are: 'ALL' (all metrics), 'HISTOGRAMS'
                              (only histograms & summaries), 'NONE' (no metrics).
                              The default is 'HISTOGRAMS'.
      --node-metrics=FILTER Select which node-level aggregate metrics to expose.
                              Valid options are: 'ALL' (all metrics), 'HISTOGRAMS'
                              (only histograms & summaries), 'NONE' (no metrics).
                              The default is 'HISTOGRAMS'.
      --enable-per-thread-cpu-times
                            Collect per-thread CPU times, where each thread gets its
                              own time-series. (EXPERIMENTAL)
      --enable-collector-timing
                            Record the cumulative time taken to run each collector
                              and export the results.
      --exclude-keyspaces=<excludedKeyspaces>

  -e, --exclude=EXCLUSION...
                            Exclude a metric family or MBean from exposition.
                              EXCLUSION may be the full name of a metric family
                              (wildcards or patterns not allowed) or the ObjectName
                              of a MBean or a ObjectName pattern that matches
                              multiple MBeans. ObjectNames always contain a colon
                              (':'). See the ObjectName JavaDoc for details. If
                              EXCLUSION is prefixed with an '@', it is interpreted
                              (sans @ character) as a path to a file containing
                              multiple EXCLUSION values, one per line. Lines
                              prefixed with '#' are considered comments and are
                              ignored. This option may be specified more than once
                              to define multiple exclusions.
      --no-global-labels    Disable all global labels.
      --no-table-labels     Disable all table labels.
      --no-fast-float       Disable the use of fast float -> ascii conversion.
      --exclude-system-tables
                            Exclude system table/keyspace metrics.
  -l, --listen=[ADDRESS][:PORT]
                            Listen address (and optional port). ADDRESS may be a
                              hostname, IPv4 dotted or decimal address, or IPv6
                              address. When ADDRESS is omitted, 0.0.0.0 (wildcard)
                              is substituted. PORT, when specified, must be a valid
                              port number. The default port 9500 will be substituted
                              if omitted. If ADDRESS is omitted but PORT is
                              specified, PORT must be prefixed with a colon (':'),
                              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
                              clients (cURL, browsers, etc). Currently Prometheus
                              discards help strings. Excluding help strings saves
                              bandwidth. Can be overridden with the "?
                              help=true|false" URI query parameter. Valid values:
                              INCLUDE, EXCLUDE, AUTOMATIC. Defaults to AUTOMATIC.
      --jmx-service-url=URL JMX service URL of the Cassandra instance to connect to
                              and collect metrics. Defaults to 'service:jmx:rmi:
                              ///jndi/rmi://localhost:7199/jmxrmi'
      --jmx-user=NAME       JMX authentication user name.
      --jmx-password=PASSWORD
                            JMX authentication password.
      --cql-address=[ADDRESS][:PORT]
                            Address/hostname and optional port for the CQL metadata
                              connection. Defaults to 'localhost:9042'
      --cql-user=NAME       CQL authentication user name.
      --cql-password=PASSWORD
                            CQL authentication password.
  -v, --verbose             Enable verbose logging. Multiple invocations increase
                              the verbosity.
  -h, --help                Show this help message and exit.
  -V, --version             Print version information and exit.

Options may also be provided via an @-file:

  • Standalone

    java -jar /path/to/cassandra-exporter-standalone-<version>.jar @/path/to/options/file
    
  • Agent

    JVM_OPTS="$JVM_OPTS -javaagent:$CASSANDRA_HOME/lib/cassandra-exporter-agent-<version>.jar=@/path/to/options/file"
    

    @$CASSANDRA_CONF/cassandra-exporter.options is a good choice.

Note that --jmx-service-url, --jmx-user, --jmx-password, --cql-address, --cql-user and --cql-password are only applicable to the standalone version -- the agent does not use JMX or CQL connections.

To protect the JMX password and prevent it from showing up in ps, top and other utilities, use an @-file that contains --jmx-password=PASSWORD.

When run as an agent, command line options must be provided as part of the -javaagent flag, with an equals sign (=) separating the JAR path and the agent options. Multiple options, or option arguments can be separated by commas (,) or spaces. Commas are preferred as the whitespace quoting rules of cassandra-env.sh are quite complex. Options with values containing whitespace must be quoted appropriately. Alternatively use an @-file (see above).

For example, to change the agent listening port to 1234 and exclude some metrics:

JVM_OPTS="$JVM_OPTS -javaagent:$CASSANDRA_HOME/lib/cassandra-exporter-agent-<version>.jar=--listen=:1234,--exclude=@$CASSANDRA_CONF/prometheus-exclusions"

Endpoints

  • /

    Root document with links for convenience.

    Content-type: text/html

  • /metrics

    Metrics exposition.

    Content-type: text/plain;version=0.0.4, text/plain, application/json

    URI parameters:

    • x-accept=<mime> -- override Accept header for browsers (e.g, ?x-accept=application/json will force JSON output)
    • help=true|false -- include/exclude per-metric family help in the output. Overrides --family-help CLI option. See above for more details.

Features

Performance

JMX is slow, really slow. JMX adds significant overhead to every method invocation on exported MBean methods, even when those methods are called from within the same JVM. On a 300-ish table Cassandra node, trying to collect all exposed metrics via JVM resulted in a collection time that was upwards of 2-3 seconds. For exporters that run as a separate process there is additional overhead of inter-process communications and that time can reach the 10's of seconds.

cassandra-exporter on the same node collects all metrics in 10-20 milliseconds.

Best practices

The exporter attempts to follow Prometheus' best practices for metric names, labels and data types.

Cassandra has keyspace- and node-level metrics that are aggregates of the per-table metrics. By default, only a subset of these aggregate metrics, specifically histograms, are exposed by cassandra-exporter. All other keyspace- and node-level metrics are skipped in favour of only exporting the per-table metrics. The rationale behind this is that apart from the histograms, the aggregate metrics are essentially duplicates. If they are needed they may be computed on-the-fly via PromQL or once, at scrape time, using Prometheus recording rules.

Unlike the metrics exported via JMX, where each table metric has a unique name, Cassandras metrics are coalesced when appropriate so they share the same exported metric family name, opting for labels to differentiate individual time series. For example, each table level metric has a constant name and at minimum a table & keyspace label, which allows for complex PromQL queries.

For example the cassandra_table_operation_latency_seconds[_count|_sum] summary metric combines read, write, range read, CAS prepare, CAS propose and CAS commit latency metrics together into a single metric family. A summary exposes percentiles (via the quantile label), a total count of recorded samples (via the _count metric), and (if available, NaN otherwise) an accumulated sum of all samples (via the _sum metric).

Individual time-series are separated by different labels. In this example, the operation type is exported as the operation label. The source keyspace, table, table_type (table, view or index), table_id (CF UUID), and numerous other metadata labels are available.

cassandra_table_operation_latency_seconds_count{keyspace="system_schema",table="tables",table_type="table",operation="read",...}
cassandra_table_operation_latency_seconds_count{keyspace="system_schema",table="tables",table_type="table",operation="write",...}

cassandra_table_operation_latency_seconds_count{keyspace="system_schema",table="keyspaces",table_type="table",operation="read",...}
cassandra_table_operation_latency_seconds_count{keyspace="system_schema",table="keyspaces",table_type="table",operation="write",...}

These metrics can then be queried:

sum(cassandra_table_operation_latency_seconds_count) by (keyspace, operation) # total operations by keyspace & type
Element Value
{keyspace="system",operation="write"} 13989
{keyspace="system",operation="cas_commit"} 0
{keyspace="system",operation="cas_prepare"} 0
{keyspace="system",operation="cas_propose"} 0
{keyspace="system",operation="range_read"} 10894
{keyspace="system",operation="read"} 74
{keyspace="system_schema",operation="write"} 78
{keyspace="system_schema",operation="cas_commit"} 0
{keyspace="system_schema",operation="cas_prepare"} 0
{keyspace="system_schema",operation="cas_propose"} 0
{keyspace="system_schema",operation="range_read"} 75
{keyspace="system_schema",operation="read"} 618

Global Labels

The exporter does attach global labels to the exported metrics. These may be configured with the --global-labels (or disabled via --no-global-labels) CLI option.

These labels are:

  • cassandra_cluster

    The name of the cluster, as specified in cassandra.yaml.

  • cassandra_host_id

    The unique UUID of the node. Not enabled by default

  • cassandra_node

    The IP address of the node.

  • cassandra_datacenter

    The configured data center name of the node.

  • cassandra_rack

    The configured rack name of the node.

These labels allow aggregation of metrics at the cluster, data center and rack levels.

While these labels could be defined in the Prometheus scrape config, we feel that having these labels be automatically applied simplifies things, especially when Prometheus is monitoring multiple clusters across numerous DCs and racks.

Exported Metrics

See the Exported Metrics wiki page for a list.

We suggest viewing the metrics endpoint (e.g., http://localhost:9500/metrics) in a browser to get an understanding of what metrics are exported by your Cassandra node.

Testing

Java

There are unit tests in the various projects which will get executed with the maven commands.

Integration test harness

There is an integration test harness available in the /test/ folder. This harness is a work in progress, and is currently only useful for manual verification.

Requirements

The test harness uses Python (tested with 3.10).

Initialise the project by using the pyproject.toml file

pip install .

The tool can be launched via

python test_tool.py

Operation

There are four modes of operation:

  • benchmark

    Not Implemented - TBA - Intended to test the speed of collection.

  • demo

    Usage: test_tool.py demo [OPTIONS]
    
      Start a Cassandra cluster with cassandra-exporter installed (agent or
      standalone). Optionally setup a schema. Wait for ctrl-c to shut everything
      down.
    
      Working Directory:
        -C, --working-directory PATH  location to install Cassandra and/or Prometheus.
                                      Must be empty or not exist. Defaults to a
                                      temporary directory.
        --cleanup-working-directory [on-error|always|never]
                                      how to delete the working directory on exit:
                                      "on-error": delete working directory on exit
                                      unless an error occurs, "always": always delete
                                      working directory on exit, "never": never delete
                                      working directory.  [default: on-error]
    
      Cassandra:
        --cluster-name TEXT           name of the Cassandra cluster  [default: test-
                                      cluster]
        --cassandra-version TEXT      Cassandra version to run  [default: 4.1.0]
        --topology DCS RACKS NODES    number of data centers, racks per data center,
                                      and nodes per rack.  [default: 2, 3, 1]
        -j, --exporter-jar PATH       path of the cassandra-exporter jar to use,
                                      either agent or standalone builds, or one of
                                      "agent" or "standalone" for the currently built
                                      jar of that type in the project directory
                                      (assumes that the sources for this test tool are
                                      in the standard location within the project, and
                                      that the jar(s) have been built).  [default:
                                      agent]
        -s, --schema PATH             path of the CQL schema YAML file to apply on
                                      cluster start. The YAML file must contain a list
                                      of CQL statement strings, which are applied in
                                      order.  [default: /root/source/forks/cassandra-
                                      exporter/test/schema.yaml]
    
  • dump

    Usage: test_tool.py dump [OPTIONS] COMMAND [ARGS]...
    
      Commands to capture, validate and diff metrics dumps
    
      Options:
        --help  Show this message and exit.
    
      Commands:
        capture   Start a Cassandra cluster, capture metrics from each node's...
        diff      Compare two metrics dumps and output the difference
        validate  Validate a metrics dump using Prometheus's promtool.
    
  • e2e - Note no tests are run at the moment

    Usage: test_tool.py e2e [OPTIONS]
    
      Run cassandra-exporter end-to-end tests.
    
      - Start C* with the exporter JAR (agent or standalone). 
      - Setup a schema. 
      - Configure and start prometheus. 
      - Wait for all scrape targets to get healthy.
      - Run some tests.
    
    Working Directory:
      -C, --working-directory PATH   location to install Cassandra and/or
                                    Prometheus. Must be empty or not exist.
                                    Defaults to a temporary directory.
      --cleanup-working-directory [on-error|always|never]
                                    how to delete the working directory on exit:
                                    "on-error": delete working directory on exit
                                    unless an error occurs, "always": always delete
                                    working directory on exit, "never": never
                                    delete working directory.  [default: on-error]
    
    Cassandra:
      --cluster-name TEXT            name of the Cassandra cluster  [default: test-
                                    cluster]
      --cassandra-version TEXT       Cassandra version to run  [default: 4.1.0]
      --topology DCS RACKS NODES     number of data centers, racks per data center,
                                    and nodes per rack.  [default: 2, 3, 1]
      -j, --exporter-jar PATH        path of the cassandra-exporter jar to use,
                                    either agent or standalone builds, or one of
                                    "agent" or "standalone" for the currently built
                                    jar of that type in the project directory
                                    (assumes that the sources for this test tool
                                    are in the standard location within the
                                    project, and that the jar(s) have been built).
                                    [default: agent]
      -s, --schema PATH              path of the CQL schema YAML file to apply on
                                    cluster start. The YAML file must contain a
                                    list of CQL statement strings, which are
                                    applied in order.  [default:
                                    /root/source/forks/cassandra-
                                    exporter/test/schema.yaml]
    
    Prometheus Archive: [mutually exclusive]
      --prometheus-version TAG
      --prometheus-archive PATH/URL
    

Unstable, Missing & Future Features

See the project issue tracker for a complete list.

  • Embedded HTML metrics viewer

    Early versions supported outputting metrics as a HTML document for easier viewing in a browser.

    The format writer was complicated and we didn't want to add dependencies on a templating library (e.g. Freemarker) to make it simpler. Instead the JSON format writer has been improved and optimized with the intent that the data could be consumed by simple static JavaScript webapp.

  • Add some example queries

  • Add Grafana dashboard templates

  • Documentation improvements

  • Improve standalone JMX exporter

    • Systemd service file
    • Package
  • Packages for standard distributions (Debian, Fedora, Arch, etc) that install the JARs in the correct locations.

Please see https://www.instaclustr.com/support/documentation/announcements/instaclustr-open-source-project-status/ for Instaclustr support status of this project.

cassandra-exporter's People

Contributors

chrisgoffinet avatar eperott avatar jfleming-ic avatar johndelcastillo avatar serban21 avatar slater-ben avatar smiklosovic avatar suhailpatel avatar zegelin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cassandra-exporter's Issues

Provide a mean to reproduce benchmarks results

Hello,

I am the author of criteo/cassandra_exporter and I would like to be able to reproduce your benchmarks in order to understand where are coming from the differences in performance from the other exporters you compare.

On my side, even on a pretty loaded cluster with a lot of keyspaces/tables the scraping time does not take more than 9sec (the machines have big cpus). But even while, when I switched from jmx_exporter, I haven't noticed a huge performance drop regarding the scrapping time. So I am a bit concerned on how you end-up with those results.

Can you please provide a mean to reproduce your benchmarks and the config you are running them on ?

Thanks in advance :)

Export Raw Histogram Data If Possible

Determine if it's possible to export raw histogram data as a Prometheus Histogram, rather than as a Summary.

This would allow for aggregation and other things.

Choose specific percentiles from histogram

Currently there is a vast number of metrics at node level as well as table level. Every metrics is important and has its own significance. However, capturing every thing will leads to space issues in case of large clusters. Though there are option to filter out some metrics, I don't see an option to capture only a specific percentiles from histogram metrics. Having this option saves a lot of space in case of bigger clusters with huge tables. For example, cassandra_table_coordinator_latency_seconds contains many number of metrics, out of them I may need only 99th percentile and 75 percentile metrics.

Buffer overflow in nio exposition

The change to the Netty ChunkedNioStream introduced a regression.

This happens because the ChunkedNioStream will not flush the buffer unless it has reached the actual chunk limit, instead it will just make another call to ReadableByteChannel.read().

WARN  [prometheus-netty-pool-0] 2020-03-31 14:48:24,928 Slf4JLogger.java:151 - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.nio.BufferOverflowException: null
	at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:189) ~[na:1.8.0_201]
	at java.nio.ByteBuffer.put(ByteBuffer.java:859) ~[na:1.8.0_201]
	at com.zegelin.prometheus.exposition.NioExpositionSink.writeAscii(NioExpositionSink.java:34) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.writeMetric(TextFormatMetricFamilyWriter.java:136) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.lambda$visit$1(TextFormatMetricFamilyWriter.java:167) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.lambda$metricWriter$0(TextFormatMetricFamilyWriter.java:155) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter.writeMetric(TextFormatMetricFamilyWriter.java:227) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.exposition.text.TextFormatExposition.nextSlice(TextFormatExposition.java:81) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.exposition.FormattedByteChannel.read(FormattedByteChannel.java:24) ~[cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at io.netty.handler.stream.ChunkedNioStream.readChunk(ChunkedNioStream.java:107) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.stream.ChunkedNioStream.readChunk(ChunkedNioStream.java:29) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.http.HttpChunkedInput.readChunk(HttpChunkedInput.java:95) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.http.HttpChunkedInput.readChunk(HttpChunkedInput.java:42) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.stream.ChunkedWriteHandler.doFlush(ChunkedWriteHandler.java:225) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:139) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:771) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:797) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:808) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:789) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:825) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at com.zegelin.cassandra.exporter.netty.HttpHandler.sendMetrics(HttpHandler.java:303) [cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:94) [cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:39) [cassandra-exporter-agent-0.9.11-SNAPSHOT.jar:na]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:643) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:566) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_201]

NPE in Labels.finalize()

While looking into #46 I discovered that the Labels.finalize() method silently may fail with NPE which would lead to an actual memory leak.

The finalize() method is calling release on two different ByteBuf instances - both may be null.

agent prevents ctrl-c from stopping cassandra

If you use :

and try to stop it using ctrl-c, the server does not stop completely. If you reset the last changes (git reset --hard), rebuild it, start it and try again, it works. It seems the exporter prevents the server from stopping when catching SIGINT.

Cassandra rules

I couldn't find any alert manager rules for this exporter.
Is there such file that I can use?

License

Hi!

This project looks quite interesting! We were hoping to try it out, would you mind adding a license?

Thanks!

Add ring neighbour information for each token range present

In some instances it can be useful to have a quick way of getting the list of all neighbours. Even if this is not available as a Cassandra metric, it is possible to get the information using Storage Service describeRingJMX (https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/service/StorageService.java#L1830), which is probably used only for nodetool describering

Also it can be useful as a way to determine ring information before scaling.

Ways to identify schema changes

While using stand-alone exporter, keeping target database's credential in the config files may be restricted for some clusters. Are there any ways to identify schema changes other than connecting to the database using native transport protocol?

Add support for SSL/TLS

In some of our deployments we require TLS when collecting metrics. Would be nice to get support for this in the exporter.

HTML metrics viewer

Implement a basic webapp that consumes the JSON output and displays:

  • Metirc families
    • Name
    • Type
    • Help
  • Metrics per family
    • Labels
    • Value
    • maybe graph over time

Broken pipe IOException

This exception is thrown regularly. I cannot link it to a specific event or cluster state but it sometime overlaps with scrapping timeouts ( which we set to 20s FYI).
I could see it thrown even on idle mono-node cassandra cluster.

WARN  [prometheus-netty-pool-0] 2019-11-10 06:02:40,697 Slf4JLogger.java:151 - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.io.IOException: Broken pipe
        at sun.nio.ch.FileDispatcherImpl.writev0(Native Method) ~[na:1.8.0_181]
        at sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:51) ~[na:1.8.0_181]
        at sun.nio.ch.IOUtil.write(IOUtil.java:148) ~[na:1.8.0_181]
        at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:504) ~[na:1.8.0_181]
        at io.netty.channel.socket.nio.NioSocketChannel.doWrite(NioSocketChannel.java:336) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:802) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.flush0(AbstractNioChannel.java:313) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannel$AbstractUnsafe.flush(AbstractChannel.java:770) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.flush(DefaultChannelPipeline.java:1256) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:771) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:763) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:744) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.flush(CombinedChannelDuplexHandler.java:530) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.ChannelOutboundHandlerAdapter.flush(ChannelOutboundHandlerAdapter.java:115) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.flush(CombinedChannelDuplexHandler.java:355) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:771) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:763) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:744) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.ChannelDuplexHandler.flush(ChannelDuplexHandler.java:117) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:771) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:763) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:744) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.handler.stream.ChunkedWriteHandler.doFlush(ChunkedWriteHandler.java:311) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:139) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:771) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:797) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:808) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:789) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:825) [netty-all-4.0.44.Final.jar:4.0.44.Final]
        at com.zegelin.cassandra.exporter.netty.HttpHandler.sendMetrics(HttpHandler.java:299) [cassandra-exporter-agent-0.9.8.jar:na]
        at com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:91) [cassandra-exporter-agent-0.9.8.jar:na]
        at com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:36) [cassandra-exporter-agent-0.9.8.jar:na] 

It this harmful? Can this be related to timeouts we observed from time to time?
Note that we use the exporter as java agent.

False positive ByteBuf memory leak detected

I'm getting the following error every once in a while.

LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information. Recent access records:
  Created at:
         io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:349)
         io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
         io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:178)
         io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:115)
         io.netty.buffer.ByteBufUtil.writeUtf8(ByteBufUtil.java:494)
         com.zegelin.prometheus.exposition.text.TextFormatLabels.formatLabels(TextFormatLabels.java:42)
         com.zegelin.prometheus.domain.Labels.asPlainTextFormatUTF8EncodedByteBuf(Labels.java:42)
         com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.writeLabels(TextFormatMetricFamilyWriter.java:111)
         com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.writeLabelSets(TextFormatMetricFamilyWriter.java:123)
         com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.writeMetric(TextFormatMetricFamilyWriter.java:141)
         com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.lambda$visit$2(TextFormatMetricFamilyWriter.java:174)
         com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter$MetricVisitor.lambda$metricWriter$0(TextFormatMetricFamilyWriter.java:155)
         com.zegelin.prometheus.exposition.text.TextFormatMetricFamilyWriter.writeMetric(TextFormatMetricFamilyWriter.java:227)
         com.zegelin.prometheus.exposition.text.TextFormatExposition.nextSlice(TextFormatExposition.java:81)
         com.zegelin.prometheus.exposition.FormattedByteChannel.read(FormattedByteChannel.java:24)
         io.netty.handler.stream.ChunkedNioStream.isEndOfInput(ChunkedNioStream.java:84)
         io.netty.handler.codec.http.HttpChunkedInput.readChunk(HttpChunkedInput.java:93)
         io.netty.handler.codec.http.HttpChunkedInput.readChunk(HttpChunkedInput.java:43)
         io.netty.handler.stream.ChunkedWriteHandler.doFlush(ChunkedWriteHandler.java:240)
         io.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:133)
         io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:749)
         io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
         io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:789)
         io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:757)
         io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:812)
         com.zegelin.cassandra.exporter.netty.HttpHandler.sendMetrics(HttpHandler.java:303)
         com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:94)
         com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:39)
         io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
         io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
         io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
         io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
         io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
         io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
         io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
         io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
         io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328)
         io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302)
         io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
         io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)
         io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)
         io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)
         io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931)
         io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
         io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700)
         io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635)
         io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552)
         io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514)
         io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044)
         io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
         java.lang.Thread.run(Thread.java:748)

I'm getting this error message when using resent versions of Netty and I'm pretty sure it is showing because of changes in how sampling is done in the resource leak detector:
netty/netty#7232
So, users will see this when using Netty version 4.0.53/4.1.17 or later:
https://netty.io/news/2017/11/08/4-0-53-Final-4-1-17-Final.html
Cassandra 4.0 is using 4.1.37, so will be a problem when we get there.

These ByteBuf instances should get a call on their release() method in the Labels.finalize() method. However (and this is why I believe this is a false positive) the Netty ResourceLeakDetector is implemented using WeakReference. But the finalizer will not run until after WeakReferences are notified. At least that's how I interpret this:
https://docs.oracle.com/javase/8/docs/api/java/lang/ref/package-summary.html#reachability

Still, it is an annoying error so would be nice to get an other solution for releasing these resources. A short-term work-around is to disable the resource leak detector with:
-Dio.netty.leakDetectionLevel=disabled.
But that will also mute actual resource leaks.

cassandra_client_request_latency_seconds metric contains some values without consistency label

Need to confirm this is desired behaviour.

On a test cluster, the following labels are present:

{consistency="LOCAL_QUORUM",operation="write"} | 0
{consistency="TWO",operation="write"} | 0
{consistency="EACH_QUORUM",operation="read"} | 0
{consistency="LOCAL_SERIAL",operation="read"} | 0
{operation="viewwrite"} | 0
{consistency="ANY",operation="write"} | 0
{consistency="SERIAL",operation="read"} | 0
{consistency="LOCAL_ONE",operation="write"} | 0
{consistency="QUORUM",operation="write"} | 0
{consistency="LOCAL_QUORUM",operation="read"} | 0
{consistency="QUORUM",operation="read"} | 0
{consistency="SERIAL",operation="write"} | 0
{consistency="THREE",operation="read"} | 0
{operation="read"} | 0
{consistency="ALL",operation="write"} | 0
{consistency="LOCAL_ONE",operation="read"} | 0
{consistency="LOCAL_SERIAL",operation="write"} | 0
{consistency="ONE",operation="write"} | 0
{consistency="EACH_QUORUM",operation="write"} | 0
{consistency="ONE",operation="read"} | 0
{operation="casread"} | 0
{operation="rangeslice"} | 0
{consistency="ALL",operation="read"} | 0
{consistency="THREE",operation="write"} | 0
{consistency="TWO",operation="read"} | 0
{operation="caswrite"} | 0
{operation="write"} | 0
{consistency="ANY",operation="read"}

Upgrade Picocli dependency to 4.x

The project is currently using Picocli version 3.6.1.
As of this writing the current version of Picocli is 4.1.4.

There have been a number of bug fixes and new features implemented in the newer versions which we can possibly leverage.

Missing histogram metrics

Histograms are exposing only the percentiles, min/max/mean/stddev are missing, and there are situations when these are needed.

Example: SSTablesPerReadHistogram. I like to see the average of it, but P50 is not the same as mean. P50 will show the value of the median sample, and since these values are integers it can be quite different from the mean. In my case the mean was changing from 0.3 to 0.75, while P50 was 0 all the time.

C*4 includes port in IP sent into Connection metric

Testing with latest C*4:

java.lang.IllegalArgumentException: '127.0.0.1_7000' is not an IP string literal.
	at com.google.common.net.InetAddresses.forString(InetAddresses.java:153)
	at com.zegelin.cassandra.exporter.MetadataFactory.endpointLabels(MetadataFactory.java:76)
	at com.zegelin.cassandra.exporter.FactoriesSupplier.lambda$connectionMetric$19(FactoriesSupplier.java:502)
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:75)
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:101)
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:177)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)

The port is included due to CASSANDRA-7544 and apache/cassandra@59b5b6b. A possible solution might be to replace InetAddresses with HostAndPort

Cassandra node process is terminated when there is an issue with Cassandra-exporter agent

Cassandra node process is terminated when cassandra-exporter agent fails to initialize. The impact may be less for smaller Cassandra environments, but the impact is more on bigger Cassandra environments. Agent should not terminate the node process if there any error during initialization. Introduce a new flag based initialization logic to drop agent initialization in case of any error allow the node process to continue.

[Help needed] Minimal metrics setup to monitor node health

I'm very new to Cassandra and need to healthcheck a cluster of 5 Cassandra nodes with ~1000 of keyspaces created.

With the default setup, I'm getting a huge number of metrics in my Prometheus, which makes it impossible to query for a time range of more than 1 hour, then it gets killed by OOM. And all those metrics aren't informative to me.

So for the sake of future users, who faced the same problem, I wonder is there a minimal config for the metrics to scrape so average administrator could take a look at and see if there is (or gonna be) something wrong with Cassandra?

Thanks in advance for any kind of help and excuse me for my barbarian English.

Missing cordinator write metrics on C*3

  1. CoordinatorWriteLatency is not available as a table metric until C*4 (see https://issues.apache.org/jira/browse/CASSANDRA-14232 and apache/cassandra@d38694a). And it's not included anyway in cassandra exporter.
  2. At https://github.com/instaclustr/cassandra-exporter/blob/master/common/src/main/java/com/zegelin/cassandra/exporter/FactoriesSupplier.java#L202-L203 write is not included for null consistency. But in C*3 I only get null consistency, and as described above we don't have table metric to do a total on.

Fix:

  1. Add CoordinatorWriteLatency, prepare for C*4.
  2. Include write when consistency is null

I'll push a PR soon for this. I encountered another issue when testing with C*4

prometheus-exclusions

How prometheus-exclusions file should look like?
Real examples?

How to exclude for example these metrics?

cassandra_dropped_messages_cross_node_latency_seconds
cassandra_dropped_messages_internal_latency_seconds
cassandra_dropped_messages_total

Failed to register collector for some of ClientRequest MBean types in Cassandra 3.0.15

Hi,
I have observed below warning messages where agent is failed to register collector for some of ClientRequest MBean types in in Cassandra 3.0.15. Has anyone faced the same issue? If so, please provide the work-around you have.

2019-12-09 09:43:29,346 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,347 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=TotalLatency.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,348 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Timeouts.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,349 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Unavailables.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,349 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Failures.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,352 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Latency.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,353 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=TotalLatency.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,353 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Timeouts.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,354 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Unavailables.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:29,355 [WARN ] [cassandra-exporter-harvester-defer-0]  Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Failures.
java.lang.NullPointerException: null
        at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_162]
        at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_162]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.9.jar:na]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_162]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_162]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
        at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
2019-12-09 09:43:36,548 [INFO ] [main]  CassandraDaemon.java:687 - No gossip backlog; proceeding



Thanks,
Rohini Podile.

Add Grafana templates

These should be some example Grafana templates that show off the exporter.

  • add some screenshots to the README.

Could it be force to be a generic bean/jmx exporter?

You state right at the beginning that this exporter is faster than jmx_exporter, even when the latter is also run as an Agent. My question would be, could I hack this thing to make it export other beans in other java services and process values (heap, etc) without penalizing much its speed?

Cassandra 3.0.17 cannot start with agent

I tried to test it with Cassandra 3.0.17 running as an agent. It seems it hangs in CassandraDaemon.java, before being able to open log files, so there is no debug info. Killing the process will create a new Java/Cassandra process, which seems to be working (both Cassandra and the agent).

I'm using Java 1.8.0_102 on Amazon Linux 2017.09.

Removal of MBean causing ConcurrentModificationException

When a table/schema is dropped, removal of MBean causing ConcurrentModificationException

java.util.ConcurrentModificationException: null
at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1516)
at com.google.common.collect.Iterators$6.computeNext(Iterators.java:616)
at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:145)
at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:140)
at com.zegelin.cassandra.exporter.JMXHarvester.reconcileMBeans(JMXHarvester.java:48)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)

Some metrics are not filtered

The following metrics are not filtered even if mentioned in --exclude list. These metrics generating too many records in case of larger clusters. For example, a cluster of 250 nodes with 150 keyspaces resulting 37500 metrics.

cassandra_keyspace_effective_ownership_ratio
cassandra_token_ownership_ratio
cassandra_jvm_gc_estimated_collection_duration_seconds_total
cassandra_jvm_nio_buffer_pool_estimated_buffers

StorageServiceMBeanMetricFamilyCollector is the source of the first two metrics, is there any reason for not filtering it? If not, I will do code change to filter the metrics and raise a PR.

Availability of jars in maven repo

Can the cassandra-exporter artifacts (agent,standalone) be uploaded into maven repository to enable users to embed exporter into their existing applications?

NPE in LabelMaker

I get these exceptions on startup when running version 0.9.9 on 3.11.5:

WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,403 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,405 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=TotalLatency.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,406 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Timeouts.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,407 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Unavailables.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,409 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Failures.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,412 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Latency.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,413 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=TotalLatency.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,414 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Timeouts.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,415 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Unavailables.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]
WARN  [cassandra-exporter-harvester-defer-0] 2019-12-09 13:50:30,416 Harvester.java:191 - Failed to register collector for MBean org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Failures.
java.lang.NullPointerException: null
	at java.util.HashMap.putMapEntries(HashMap.java:501) ~[na:1.8.0_181]
	at java.util.HashMap.putAll(HashMap.java:785) ~[na:1.8.0_181]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$withLabelMaker$0(FactoriesSupplier.java:65) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.FactoriesSupplier$FactoryBuilder.lambda$build$1(FactoriesSupplier.java:91) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at com.zegelin.cassandra.exporter.Harvester.lambda$registerMBean$0(Harvester.java:174) ~[cassandra-exporter-agent-0.9.10-SNAPSHOT.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_181]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]

Seem to be related to this commit:
034c598

exporter incompatible with cassandra trunk (4.0)

When trying to collect metrics from trunk I've run into this:

WARN  [prometheus-netty-pool-0] 2019-05-01 15:22:18,501 Slf4JLogger.java:151 - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.lang.NoSuchMethodError: org.apache.cassandra.utils.FBUtilities.getBroadcastAddress()Ljava/net/InetAddress;
	at com.zegelin.prometheus.cassandra.InternalMetadataFactory.localBroadcastAddress(InternalMetadataFactory.java:85)
	at com.zegelin.prometheus.cassandra.Harvester.globalLabels(Harvester.java:280)
	at com.zegelin.prometheus.netty.HttpHandler.sendMetrics(HttpHandler.java:283)
	at com.zegelin.prometheus.netty.HttpHandler.channelRead0(HttpHandler.java:91)
	at com.zegelin.prometheus.netty.HttpHandler.channelRead0(HttpHandler.java:36)

The call FBUtilities.getBroadcastAddress() was removed in process of making C* run multiple instances on one machine. It should be replaced with FBUtilities.getLocalAddressAndPort

Metric for tables created post-start are missing metatdata labels

Creating a table via CQL results in new metrics appearing, but these metrics don't have any additional matadata labels (table_id, table_type, etc.)

cassandra_table_partition_size_minimum_bytes{keyspace="system",table_id="0290003c-977e-397c-ac3e-fdfdc01d626b",table="batchlog",table_type="table",cassandra_cluster_name="3_11_3",cassandra_host_id="64531943-2183-461e-baed-5cde6dbc1121",cassandra_node="127.0.0.1",cassandra_datacenter="dc1",cassandra_rack="r1"} 0.0 1537822838677
cassandra_table_partition_size_minimum_bytes{keyspace="lotsotables",table="table619",cassandra_cluster_name="3_11_3",cassandra_host_id="64531943-2183-461e-baed-5cde6dbc1121",cassandra_node="127.0.0.1",cassandra_datacenter="dc1",cassandra_rack="r1"} 0.0 1537822838677

NPE on endpoint snitch

I've observed this error just after restart of a node.

Exception while processing HTTP request HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: 
success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 0, cap: 0, components=0)) GET /metrics HTTP/1.1 Host: 192.168.189.15:9500 User-Agent: Prometheus/2.10.0 Accept: application/openmetrics-text; version=0.0.1,text/plain;ve
rsion=0.0.4;q=0.5,*/*;q=0.1 Accept-Encoding: gzip X-Prometheus-Scrape-Timeout-Seconds: 10.000000 content-length: 0."}
java.lang.NullPointerException: null
        at com.zegelin.cassandra.exporter.InternalMetadataFactory$3.dataCenter(InternalMetadataFactory.java:70) ~[cassandra-exporter-agent.jar:na]
        at com.zegelin.cassandra.exporter.LabelEnum.addIfEnabled(LabelEnum.java:14) ~[cassandra-exporter-agent.jar:na]
        at com.zegelin.cassandra.exporter.Harvester.globalLabels(Harvester.java:288) ~[cassandra-exporter-agent.jar:na]
        at com.zegelin.cassandra.exporter.netty.HttpHandler.sendMetrics(HttpHandler.java:292) [cassandra-exporter-agent.jar:na]
        at com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:94) [cassandra-exporter-agent.jar:na]
        at com.zegelin.cassandra.exporter.netty.HttpHandler.channelRead0(HttpHandler.java:39) [cassandra-exporter-agent.jar:na]
        at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) [netty-all-4.1.42.Final.jar:4.1.42.Final]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_222]

Add missing jmx metrics

I like the speed of your exporter, however it's missing some metrics that are available in the default exporter and useful. For now I'm using both exporters with the following configuration for the default one to get those that are missing https://pastebin.com/raw/DvW435Lr

Any reason why those metrics are missing ? Do you recommend using both the default exporter and yours ?

Add support for Cassandra version 2.2.x

We would like to implement this on our systems, but we are currently running 2.2.5. We will be looking at moving to either 2.2.11 or 2.2.13 very shortly. Seeing support added for any/all of these would be great for us.

NullPointerException on startup

Tried the latest release, noticed this NPE on startup, I think it might be related to the fact im using G1 for Cassandra and not CMS:

WARN  [prometheus-netty-pool-0] 2018-10-13 18:37:14,350 Harvester.java:214 - Metrics collector java.lang:type=GarbageCollector failed to collect. Skipping.
java.lang.NullPointerException: null
	at com.zegelin.prometheus.cassandra.collector.jvm.GarbageCollectorMXBeanMetricFamilyCollector.collect(GarbageCollectorMXBeanMetricFamilyCollector.java:77) ~[cassandra-exporter-agent-0.9.3.jar:na]
	at com.zegelin.prometheus.cassandra.Harvester.lambda$collect$3(Harvester.java:211) ~[cassandra-exporter-agent-0.9.3.jar:na]
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:267) ~[na:1.8.0_181]
	at java.util.HashMap$EntrySpliterator.tryAdvance(HashMap.java:1717) ~[na:1.8.0_181]
	at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294) ~[na:1.8.0_181]
	at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206) ~[na:1.8.0_181]
	at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:169) ~[na:1.8.0_181]
	at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300) ~[na:1.8.0_181]
	at java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681) ~[na:1.8.0_181]
	at com.zegelin.prometheus.exposition.TextFormatChunkedInput.nextSlice(TextFormatChunkedInput.java:309) ~[cassandra-exporter-agent-0.9.3.jar:na]
	at com.zegelin.prometheus.exposition.TextFormatChunkedInput.readChunk(TextFormatChunkedInput.java:357) ~[cassandra-exporter-agent-0.9.3.jar:na]
	at com.zegelin.prometheus.exposition.TextFormatChunkedInput.readChunk(TextFormatChunkedInput.java:26) ~[cassandra-exporter-agent-0.9.3.jar:na]
	at io.netty.handler.stream.ChunkedWriteHandler.doFlush(ChunkedWriteHandler.java:225) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.stream.ChunkedWriteHandler.flush(ChunkedWriteHandler.java:139) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:771) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:797) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:808) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:789) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:825) ~[netty-all-4.0.44.Final.jar:4.0.44.Final]
	at com.zegelin.prometheus.netty.HttpHandler.sendMetrics(HttpHandler.java:275) ~[cassandra-exporter-agent-0.9.3.jar:na]
	at com.zegelin.prometheus.netty.HttpHandler.channelRead0(HttpHandler.java:88) ~[cassandra-exporter-agent-0.9.3.jar:na]```

Are Thread Pool blocked_tasks_total and blocked_tasks similar?

blocked_tasks is a gauge, blocked_tasks_total is a counter.

Cassandra (3.11.x), increments both when something is blocked:

metrics.totalBlocked.inc();
metrics.currentBlocked.inc();
s.awaitUninterruptibly();
metrics.currentBlocked.dec();

blocked_tasks_total is more useful, since blocked_tasks may change/reset faster than Prometheus collects, resulting in incorrect metrics.

500 server error/exception thrown if metrics are queried during startup.

If a HTTP GET /metrics is issued while Cassandra is still starting up, the following exception is thrown:

ERROR [prometheus-netty-pool-0] 2018-10-03 15:18:31,224 HttpHandler.java:99 - Exception while processing HTTP request HttpObjectAggregator$AggregatedFullHttpRequest(decodeResult: success, version: HTTP/1.1, content: CompositeByteBuf(ridx: 0, widx: 0, cap: 0, components=0))
GET /metrics HTTP/1.1
Host: localhost:9500
User-Agent: Prometheus/2.2.1
Accept: text/plain;version=0.0.4;q=1,*/*;q=0.1
Accept-Encoding: gzip
X-Prometheus-Scrape-Timeout-Seconds: 10.000000
Content-Length: 0.
java.lang.NullPointerException: null
	at org.apache.cassandra.service.StorageService.getLocalHostId(StorageService.java:1865) ~[apache-cassandra-3.11.3.jar:3.11.3]
	at com.zegelin.prometheus.cassandra.Harvester.globalLabels(Harvester.java:233) ~[cassandra-exporter-agent-0.9.4-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.netty.HttpHandler.sendMetrics(HttpHandler.java:267) [cassandra-exporter-agent-0.9.4-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.netty.HttpHandler.channelRead0(HttpHandler.java:88) [cassandra-exporter-agent-0.9.4-SNAPSHOT.jar:na]
	at com.zegelin.prometheus.netty.HttpHandler.channelRead0(HttpHandler.java:35) [cassandra-exporter-agent-0.9.4-SNAPSHOT.jar:na]
	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:86) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:336) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:357) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:343) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:643) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:566) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:131) [netty-all-4.0.44.Final.jar:4.0.44.Final]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]

Add support for Netty 4.1

The exporter is currently built against Cassandra 3.11.2 and Netty 4.0.

This is one of the reasons as to why it currently is not compatible with Cassandra 4.0, but there are other reasons as well - #23

However, this is preventing us from using the exporter since we back ported selected parts from Cassandra/trunk to 3.11, which includes bumping the Netty version to 4.1.

Using --exclude

I am using file to specify the main arguments, and using another file to exclude metrics families. However, the the metrics supposed to be excluded still appearing in /metrics. Can you please go through the below configuration and check if there are any issues?

Version: V0.9.10

JVM_OPTS="$JVM_OPTS -javaagent:$CASSANDRA_HOME/lib/cassandra-exporter-agent.jar=@$CASSANDRA_HOME/conf/metrics-exporter.properties"

I made sure the config files are exist.

metrics-exporter.properties

--listen=*****************
--global-labels=CLUSTER,NODE,DATACENTER
--exclude-system-tables
--no-table-labels
--exclude=@/opt/nosql/clusters/cassandra-3004/conf/exclude-metrics.properties

exclude-metrics.properties

cassandra_buffer_pool_misses_total
cassandra_buffer_pool_size_bytes
cassandra_cache_capacity_bytes
cassandra_cache_entries
cassandra_cache_estimated_size_bytes
cassandra_cache_hits_total
cassandra_cache_miss_latency_seconds
cassandra_cache_requests_total
cassandra_client_authentication_successes_total
cassandra_commit_log_commit_latency_seconds
cassandra_commit_log_completed_tasks_total

Metrics pull Response contains excluded metrics

# HELP cassandra_buffer_pool_misses_total Total number of requests to the BufferPool requiring allocation of a new ByteBuffer.
# TYPE cassandra_buffer_pool_misses_total counter
cassandra_buffer_pool_misses_total{cassandra_cluster="GLDPS_CAAS_UAT",cassandra_node="147.107.191.84",cassandra_datacenter="CST"} 0.0 1582203227803

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.