# Cassandra

> Monitor Apache Cassandra metrics with OpenTelemetry and Last9

Source: https://last9.io/docs/integrations/databases/cassandra/

Use OpenTelemetry to monitor your Apache Cassandra cluster and send telemetry data to Last9. This integration runs the `opentelemetry-jmx-metrics` JAR as a service alongside Cassandra to collect JMX metrics, which are forwarded to the OTel Collector via OTLP.

Read the [sample configuration](https://github.com/last9/opentelemetry-examples/tree/main/otel-collector/cassandra) for more details.

## Prerequisites

- Apache Cassandra 3.x or 4.x installed and running
- Java 11+ installed on the host (required by the JMX metrics JAR)
- JMX enabled in Cassandra (enabled by default on port 7199)
- Last9 account with integration credentials

## Verify JMX Access

Cassandra enables JMX on port 7199 by default. Verify it is reachable:

```bash
ss -tlnp | grep 7199
```

:::note
If Cassandra JMX authentication is enabled, add `username` and `password` fields to the `jmx` receiver configuration.
:::

## Install OpenTelemetry Collector

**AMD64**

```bash
sudo apt-get update && sudo apt-get install -y wget
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_linux_amd64.deb
sudo dpkg -i otelcol-contrib_0.144.0_linux_amd64.deb
```

**ARM64**

```bash
sudo apt-get update && sudo apt-get install -y wget
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_linux_arm64.deb
sudo dpkg -i otelcol-contrib_0.144.0_linux_arm64.deb
```

**RPM (RHEL/CentOS)**

```bash
wget https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.144.0/otelcol-contrib_0.144.0_linux_amd64.rpm
sudo rpm -ivh otelcol-contrib_0.144.0_linux_amd64.rpm
```

## Download JMX Metrics JAR

The JMX receiver requires a metrics collection JAR:

```bash
sudo mkdir -p /opt
sudo wget -O /opt/opentelemetry-jmx-metrics.jar \
  https://github.com/open-telemetry/opentelemetry-java-contrib/releases/download/v1.43.0/opentelemetry-jmx-metrics.jar
```

## Configure JMX Metrics Collection

1. **Create the JMX config**

   Create `/etc/otelcol-contrib/jmx-config.properties`:

   ```properties
   otel.exporter.otlp.endpoint = http://localhost:4317
   otel.jmx.interval.milliseconds = 60000
   otel.jmx.service.url = service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi
   otel.jmx.target.system = cassandra
   otel.metrics.exporter = otlp
   ```

   If JMX authentication is enabled, add:

   ```properties
   otel.jmx.username = <jmx_username>
   otel.jmx.password = <jmx_password>
   ```

2. **Run the JMX metrics JAR as a service**

   Create `/etc/systemd/system/cassandra-jmx-metrics.service`:

   ```ini
   [Unit]
   Description=Cassandra JMX Metrics Collector
   After=cassandra.service

   [Service]
   ExecStart=java -jar /opt/opentelemetry-jmx-metrics.jar -config /etc/otelcol-contrib/jmx-config.properties
   Restart=always
   RestartSec=10

   [Install]
   WantedBy=multi-user.target
   ```

   ```bash
   sudo systemctl daemon-reload
   sudo systemctl enable --now cassandra-jmx-metrics
   ```

3. **Create the Collector Configuration**

   Create `/etc/otelcol-contrib/config.yaml`:

   ```yaml
   receivers:
     otlp:
       protocols:
         grpc:
           endpoint: 0.0.0.0:4317

     hostmetrics:
       collection_interval: 60s
       scrapers:
         cpu:
           metrics:
             system.cpu.logical.count:
               enabled: true
         memory:
           metrics:
             system.memory.utilization:
               enabled: true
             system.memory.limit:
               enabled: true
         load:
         disk:
         filesystem:
           metrics:
             system.filesystem.utilization:
               enabled: true
         network:
         paging:

   processors:
     batch:
       timeout: 5s
       send_batch_size: 10000
       send_batch_max_size: 10000
     resourcedetection/system:
       detectors: ["system"]
       system:
         hostname_sources: ["os"]
     transform/add_db_system:
       metric_statements:
         - context: datapoint
           statements:
             - set(attributes["host.name"], resource.attributes["host.name"])
             - set(attributes["db.system"], "cassandra")

   exporters:
     otlp/last9:
       endpoint: "{{ .Logs.WriteURL }}"
       headers:
         "Authorization": "{{ .Logs.AuthValue }}"

   service:
     pipelines:
       metrics/jmx:
         receivers: [otlp]
         processors: [batch, transform/add_db_system]
         exporters: [otlp/last9]
       metrics/host:
         receivers: [hostmetrics]
         processors: [batch, resourcedetection/system, transform/add_db_system]
         exporters: [otlp/last9]
   ```

   Replace `endpoint` and `Authorization` with your Last9 credentials from the [Integrations page](https://app.last9.io/integrations).

4. **Start the Collector**

   ```bash
   sudo systemctl enable --now otelcol-contrib
   ```

## Nodetool Metrics (Extended Collection)

JMX covers per-table latency and request counts, but some cluster-level metrics are only accessible via `nodetool`. The integration includes a nodetool exporter that runs alongside Cassandra and exposes these additional metrics on port 9500.

**Bare-metal setup** — create `/etc/systemd/system/cassandra-nodetool-exporter.service`:

```ini
[Unit]
Description=Cassandra Nodetool Prometheus Exporter
After=cassandra.service

[Service]
Environment=CASSANDRA_HOST=localhost
Environment=CASSANDRA_JMX_PORT=7199
Environment=EXPORTER_PORT=9500
ExecStart=python3 /opt/nodetool-exporter.py
Restart=always
RestartSec=15

[Install]
WantedBy=multi-user.target
```

Download the exporter script:

```bash
sudo wget -O /opt/nodetool-exporter.py \
  https://raw.githubusercontent.com/last9/opentelemetry-examples/main/otel-collector/cassandra/nodetool-exporter.py
sudo systemctl daemon-reload && sudo systemctl enable --now cassandra-nodetool-exporter
```

Add the following receiver and pipeline to your OTel Collector config:

```yaml
receivers:
  prometheus/nodetool:
    config:
      scrape_configs:
        - job_name: cassandra_nodetool
          scrape_interval: 60s
          static_configs:
            - targets: ["localhost:9500"]

service:
  pipelines:
    metrics/nodetool:
      receivers: [prometheus/nodetool]
      processors: [batch, transform/add_db_system]
      exporters: [otlp/last9]
```

## Metrics Collected

| Metric category    | Examples                                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------------------------- |
| Read/write latency | `cassandra_client_request_read_latency_50p_microseconds`, `cassandra_client_request_write_latency_99p_microseconds` |
| Request counts     | `cassandra_client_request_count_total`, `cassandra_client_request_error_count_total`                                |
| Compaction         | `cassandra_compaction_tasks_completed_total`, `cassandra_compaction_tasks_pending`                                  |
| Storage            | `cassandra_storage_load_count_bytes`, `cassandra_storage_hints_count_total`                                         |
| Cluster topology   | `cassandra_nodetool_nodes_up`, `cassandra_nodetool_nodes_down`                                                      |
| Thread pools       | `cassandra_nodetool_thread_pool_pending`, `cassandra_nodetool_thread_pool_blocked`                                  |
| Heap & cache       | `cassandra_nodetool_heap_used_mb`, `cassandra_nodetool_key_cache_hit_rate`                                          |
| System             | CPU, memory, disk, network via `hostmetrics`                                                                        |

## Verification

1. **Check Collector Status**

   ```bash
   sudo systemctl status otelcol-contrib
   ```

2. **View Collector Logs**

   ```bash
   sudo journalctl -u otelcol-contrib -f
   ```

3. **Verify Metrics in Last9**

   Log into your Last9 account and check that Cassandra metrics are being received. Look for metric names starting with `cassandra.`.

---

## Troubleshooting

- **JMX connection refused**

  ```bash
  # Verify JMX port is listening
  ss -tlnp | grep 7199

  # Check Cassandra is running
  nodetool status

  # Test JMX connectivity
  java -jar /opt/opentelemetry-jmx-metrics.jar \
    -targetSystem cassandra \
    -endpoint service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi
  ```

- **`ClassNotFoundException` or JAR issues**

  ```bash
  # Verify Java is installed
  java -version

  # Check JAR is present and readable
  ls -la /opt/opentelemetry-jmx-metrics.jar
  ```

- **Collector not starting**

  ```bash
  sudo journalctl -u otelcol-contrib -n 100 --no-pager
  ```

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
