<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

## Metrics

The driver exposes measurements of its internal behavior through the popular [Dropwizard Metrics]
library.  Developers can access these metrics and choose to export them to a monitoring tool.

The driver depends on Metrics 3.2.x, but is compatible with newer versions of Dropwizard Metrics.
For using Metrics 4.x with the driver, see [Metrics 4 Compatibility](#metrics-4-compatibility).

### Structure

Metric names are path-like, dot-separated strings.  Metrics are measured at the `Cluster`-level,
thus the driver prefixes them with the name of the `Cluster` they are associated with (see [withClusterName]
for how to configure this), suffixed by `-metrics`.  For example:

```
cluster1-metrics.connected-to
cluster1-metrics.connection-errors
...
```

### Configuration

By default, metrics are enabled and exposed via JMX as [MXBeans].

Some users may find that they don't want the driver to record and expose metrics.  To disable
metrics collection, use the [withoutMetrics] builder method, i.e.:

```java
Cluster cluster = Cluster.builder()
        .withoutMetrics()
        .build();
```

Note that if you decide to disable metrics, you may also consider excluding metrics as a dependency.
To do this in a maven project:

```xml
<dependency>
  <groupId>org.apache.cassandra</groupId>
  <artifactId>cassandra-driver-core</artifactId>
  <version>3.12.0</version>
  <exclusions>
    <exclusion>
      <groupId>io.dropwizard.metrics</groupId>
      <artifactId>metrics-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>
```

Alternatively, one may not want to expose metrics using JMX.  Disabling JMX reporting is simple
as using the [withoutJMXReporting] builder method, i.e.:

```java
Cluster cluster = Cluster.builder()
        .withoutJMXReporting()
        .build();
```

### Accessing Cluster Metrics

`Cluster` metrics may be accessed via the [getMetrics] method.  The [Metrics] class offers
direct access to all metrics recorded for the `Cluster` via getter methods.  Refer to
the [Metrics javadoc][Metrics] for more details about the metrics offered.

It is very common for applications to record their own metrics.  You can add all metrics
recorded for a `Cluster` to your applications' [MetricRegistry] in the following manner:

```java
MetricRegistry myRegistery = new MetricRegistry();
myRegistry.registerAll(cluster.getMetrics().getRegistry());
```

### Registering a Custom Reporter

Dropwizard Metrics offers a variety of [Reporters] for exporting metrics.  To enable reporting,
access the `Cluster`'s metrics via the [getMetrics] method.  For example, to enable CSV reporting
every 30 seconds:

```java
import com.codahale.metrics.*;

import java.io.File;
import java.util.concurrent.TimeUnit;

Metrics metrics = cluster.getMetrics();

CsvReporter csvReporter = CsvReporter.forRegistry(metrics.getRegistry())
        .convertDurationsTo(TimeUnit.MILLISECONDS)
        .convertRatesTo(TimeUnit.SECONDS)
        .build(new File("."));

csvReporter.start(30, TimeUnit.SECONDS);
```

### Metrics 4 Compatibility

While the driver depends on Metrics 3.2.x, it also works with Metrics 4, with some caveats.

In Metrics 4, JMX reporting was moved to a separate module, `metrics-jmx`.  Because of this you are
likely to encounter the following exception at runtime when initializing a `Cluster`:

```
Exception in thread "main" java.lang.NoClassDefFoundError: com/codahale/metrics/JmxReporter
	at com.datastax.driver.core.Metrics.<init>(Metrics.java:103)
	at com.datastax.driver.core.Cluster$Manager.init(Cluster.java:1402)
	at com.datastax.driver.core.Cluster.init(Cluster.java:159)
	at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:330)
	at com.datastax.driver.core.Cluster.connectAsync(Cluster.java:305)
	at com.datastax.durationtest.core.DurationTest.createSessions(DurationTest.java:360)
        ....
Caused by: java.lang.ClassNotFoundException: com.codahale.metrics.JmxReporter
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
	... 8 more
```

To fix this, use [withoutJMXReporting] when constructing your `Cluster`.  If you still desire JMX
reporting, add `metrics-jmx` as a dependency:

```xml
<dependency>
  <groupId>io.dropwizard.metrics</groupId>
  <artifactId>metrics-jmx</artifactId>
  <version>4.0.2</version>
</dependency>
```

Then create your `Cluster` and `JmxReporter` in the following manner:

```java
Cluster cluster = Cluster.builder()
        .withoutJMXReporting()
        .build();

JmxReporter reporter =
    JmxReporter.forRegistry(cluster.getMetrics().getRegistry())
        .inDomain(cluster.getClusterName() + "-metrics")
        .build();

reporter.start();
```

[Dropwizard Metrics]: http://metrics.dropwizard.io/3.2.2/manual/index.html
[Reporters]: http://metrics.dropwizard.io/3.2.2/manual/core.html#reporters
[MetricRegistry]: http://metrics.dropwizard.io/3.2.2/apidocs/com/codahale/metrics/MetricRegistry.html
[MXBeans]: https://docs.oracle.com/javase/tutorial/jmx/mbeans/mxbeans.html
[withClusterName]: https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/core/Cluster.Builder.html#withClusterName-java.lang.String-
[withoutMetrics]: https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/core/Cluster.Builder.html#withoutMetrics--
[withoutJMXReporting]: https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/core/Cluster.Builder.html#withoutJMXReporting--
[getMetrics]: https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/core/Cluster.html#getMetrics--
[Metrics]: https://docs.datastax.com/en/drivers/java/3.11/com/datastax/driver/core/Metrics.html
