---
title: Monitor Redis on a host (OpenTelemetry)
source: https://docs.newrelic.com/docs/opentelemetry/integrations/redis/host
---

Monitor your self-hosted Redis instance by installing the OpenTelemetry Collector directly on a server or virtual machine. This guide walks you through configuring the collector to scrape Redis metrics, collect logs, and send all telemetry to New Relic using the OTLP protocol.

## Before you begin [#prereq]

You'll need the following before you set up the collector:

-   Your New Relic license key
-   A Linux host with root or sudo privileges
-   Redis running and accessible — version 6.0 or later recommended (4.0 and later works with a reduced metric set)
-   Network connectivity to your Redis endpoint (default `localhost:6379`)
-   Outbound HTTPS (port 443) to New Relic's [OTLP endpoint](https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp)
-   An OpenTelemetry Collector installed on that host — either the NRDOT collector or the OpenTelemetry Collector Contrib — which you choose in [Installation options](#installation-options)
-   For the Prometheus receiver path only, the [redis_exporter](https://github.com/oliver006/redis_exporter) running alongside Redis

Each path's setup steps cover any installation you still need, whether that's the [NRDOT collector](https://docs.newrelic.com/docs/opentelemetry/nrdot/nrdot-collector/), `otelcol-contrib`, or the redis_exporter.

## Installation options [#installation-options]

Choose the collector distribution that matches your environment:

### NRDOT collector

#### Configure Redis monitoring [#configure-nrdot]

This configuration tells the collector how to gather Redis metrics and send them to New Relic. It handles three main jobs:

-   **Collect** metrics from Redis through the `redis` receiver
-   **Shape** the data — reduce cardinality, convert counters to deltas, and tag it for entity synthesis
-   **Export** the processed metrics to New Relic over OTLP

Create the collector configuration file:

```bash
sudo nano /etc/nrdot-collector/redis-collector-config.yaml
```

Paste the following configuration, updating the Redis `endpoint` if it isn't `localhost:6379`:

```yaml
extensions:
  health_check:
    endpoint: "0.0.0.0:13133"

receivers:
  redis:
    endpoint: "localhost:6379"  # Update with your Redis host:port
    collection_interval: 10s
    metrics:
      redis.maxmemory:
        enabled: true
      redis.role:
        enabled: false
      redis.cmd.calls:
        enabled: true
      redis.cmd.usec:
        enabled: true
      redis.clients.max_input_buffer:
        enabled: false
      redis.clients.max_output_buffer:
        enabled: false
      redis.replication.backlog_first_byte_offset:
        enabled: false
    resource_attributes:
      server.address:
        enabled: true
      server.port:
        enabled: true

processors:
  memory_limiter:
    check_interval: 5s
    limit_mib: 512
    spike_limit_mib: 128

  resource_detection:
    detectors: [env, system]
    timeout: 5s
    override: false
    system:
      resource_attributes:
        host.name:
          enabled: true
        host.id:
          enabled: true

  # Uncomment the section below to use a custom human-readable name for your
  # Redis entity instead of the default server.address:server.port identifier.
  # resource/redis:
  #   attributes:
  #     - key: redis.instance.id
  #       value: "my-redis-instance"
  #       action: upsert

  attributes/entity_tags:
    actions:
      - key: instrumentation.provider
        value: opentelemetry
        action: upsert

  cumulativetodelta:
    include:
      match_type: regexp
      metrics:
        - redis\.commands\.processed
        - redis\.connections\.received
        - redis\.connections\.rejected
        - redis\.keys\.evicted
        - redis\.keys\.expired
        - redis\.keyspace\.hits
        - redis\.keyspace\.misses
        - redis\.net\.input
        - redis\.net\.output
        - redis\.cpu\.time
        - redis\.cmd\.calls
        - redis\.cmd\.usec
        - redis\.uptime

  filter/cardinality:
    metrics:
      datapoint:
        - 'metric.name == "redis.cpu.time" and attributes["state"] != "sys" and attributes["state"] != "user"'
        - 'metric.name == "redis.cmd.calls" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'
        - 'metric.name == "redis.cmd.usec" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'

  transform/metadata_nullify:
    metric_statements:
      - context: metric
        statements:
          - set(description, "")
          - set(unit, "")

  batch:
    send_batch_size: 2048
    send_batch_max_size: 4096
    timeout: 10s

exporters:
  otlp_http:
    endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
    headers:
      api-key: ${env:NEW_RELIC_LICENSE_KEY}
    compression: gzip

service:
  extensions: [health_check]
  pipelines:
    metrics/redis:
      receivers: [redis]
      # If using resource/redis for custom name, add it to the processors list:
      # processors: [memory_limiter, resource_detection, resource/redis, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
```

##### What this configuration does [#config-explanation-nrdot]

Each component in the pipeline has a specific job:

| Component                    | Description                                                                                                                                                        |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `health_check`               | Exposes a health endpoint on `0.0.0.0:13133` so you can confirm the collector is running.                                                                          |
| `redis` receiver             | Connects to your Redis endpoint every 10 seconds and reads metrics from the Redis `INFO` command. `server.address` and `server.port` become the entity's identity. |
| `memory_limiter`             | Caps collector memory usage (512 MiB soft limit, 128 MiB spike) to protect the host.                                                                               |
| `resource_detection`         | Detects the host and adds `host.name` and `host.id`, linking Redis metrics to the underlying host entity.                                                          |
| `attributes/entity_tags`     | Stamps `instrumentation.provider: opentelemetry` on every metric so you can scope queries to the OpenTelemetry path.                                               |
| `cumulativetodelta`          | Converts Redis's cumulative counters — commands, keyspace hits, evictions, and so on — to delta values so New Relic charts rates correctly.                        |
| `filter/cardinality`         | Drops high-cardinality data points (CPU states other than `user` and `sys`, and per-command metrics for uncommon commands) to control ingest cost.                 |
| `transform/metadata_nullify` | Clears metric descriptions and units to reduce payload size.                                                                                                       |
| `batch`                      | Groups data points before export (2,048 per batch, up to 4,096) and flushes at least every 10 seconds to reduce network overhead.                                  |
| `otlp_http`                  | Exports the processed metrics to New Relic over OTLP with gzip compression, authenticated with your license key.                                                   |

> #### 💡 TIP
>
> **Want a user-friendly entity name?** By default, your Redis entity is named using the `server.address:server.port` combination. To use a custom human-readable name instead, uncomment the `resource/redis` section in the config above, set your preferred name in the `redis.instance.id` value, and add `resource/redis` to the processors pipeline.

#### Optional: Configure authentication [#auth-nrdot]

By default, the collector connects to Redis without credentials. If your Redis instance requires authentication, add the matching credentials to the `redis` receiver. Choose the option that matches your setup:

**Legacy password (requirepass)**

For Redis instances using a single shared password (`requirepass` in redis.conf):

```yaml
receivers:
  redis:
    endpoint: "redis-host:6379"
    password: "${env:REDIS_PASSWORD}"
```

Add `REDIS_PASSWORD` to your environment file:

```bash
echo "REDIS_PASSWORD=your-redis-password" | sudo tee -a /etc/nrdot-collector/nrdot-collector.conf
```

**ACL username + password (Redis 6+)**

For Redis 6+ instances using Access Control Lists with per-user credentials:

**Step 1:** Create a monitoring-only user on your Redis server (requires admin access):

```bash
redis-cli ACL SETUSER otel-monitor on >your-monitor-password ~* +info +ping
```

This creates a user that can ONLY run `INFO` and `PING` — the minimum needed for metric collection.

**Step 2:** Add credentials to the receiver config:

```yaml
receivers:
  redis:
    endpoint: "redis-host:6379"
    username: "${env:REDIS_USERNAME}"
    password: "${env:REDIS_PASSWORD}"
```

**Step 3:** Add to your environment file:

```bash
echo "REDIS_USERNAME=otel-monitor" | sudo tee -a /etc/nrdot-collector/nrdot-collector.conf
echo "REDIS_PASSWORD=your-monitor-password" | sudo tee -a /etc/nrdot-collector/nrdot-collector.conf
```

**TLS/SSL encrypted connection**

For Redis instances requiring encrypted connections:

```yaml
receivers:
  redis:
    endpoint: "redis-host:6380"
    password: "${env:REDIS_PASSWORD}"
    tls:
      insecure: false
      ca_file: /etc/ssl/redis/ca.crt
      cert_file: /etc/ssl/redis/client.crt   # For mutual TLS (optional)
      key_file: /etc/ssl/redis/client.key     # For mutual TLS (optional)
```

> #### 💡 TIP
>
> If your Redis uses a self-signed certificate and you want to skip verification (not recommended for production), set `insecure: true` instead of providing `ca_file`.

#### Optional: Collect Redis logs [#logs-nrdot]

Beyond metrics, the collector can forward Redis's log file to New Relic so you can correlate log events — restarts, persistence events, or errors — with metric spikes on the same entity. Add the `filelog` receiver to tail the Redis log:

```yaml
receivers:
  # ... existing redis receiver ...
  file_log/redis:
    include:
      - /var/log/redis/redis-server.log
    start_at: end
    operators:
      - type: regex_parser
        regex: '^\d+:[XCSM] \d+ \w+ \d+ \d+:\d+:\d+\.\d+ (?P<level>.) '
        on_error: send
    resource:
      db.system: redis
```

Log lines from the file have no Redis connection context on their own — you must explicitly attach identity attributes so New Relic associates the logs with your Redis entity. Add a `resource/redis_logs` processor with **hardcoded values matching your Redis entity's identity**:

```yaml
processors:
  # ... existing processors ...
  resource/redis_logs:
    attributes:
      - key: server.address
        value: "localhost"  # Must match your redis receiver endpoint host
        action: upsert
      - key: server.port
        value: 6379  # Must match your redis receiver endpoint port
        action: upsert
      - key: instrumentation.provider
        value: opentelemetry
        action: upsert
```

> #### 💡 TIP
>
> **Using a custom instance ID?** If you enabled the `resource/redis` processor for custom entity naming, replace `server.address` and `server.port` above with your `redis.instance.id`:
>
> ```yaml
>   resource/redis_logs:
>     attributes:
>       - key: redis.instance.id
>         value: "my-redis-instance"  # Must match the value in resource/redis
>         action: upsert
>       - key: instrumentation.provider
>         value: opentelemetry
>         action: upsert
> ```

Add a **separate** logs pipeline to the service section:

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [redis]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
    logs/redis:
      receivers: [file_log/redis]
      processors: [memory_limiter, resource/redis_logs, batch]
      exporters: [otlp_http]
```

> #### ⚠️ IMPORTANT
>
> The collector must have read access to both the Redis log file and its parent directory. Run:
>
> ```bash
> sudo chmod 755 /var/log/redis
> sudo chmod 644 /var/log/redis/redis-server.log
> ```

#### Optional: Collect host metrics [#hostmetrics-nrdot]

Redis performance often tracks host resource pressure — CPU saturation, memory exhaustion, or disk I/O contention. Add the `hostmetrics` receiver to collect system metrics from the host alongside Redis, so you can correlate the two in New Relic:

```yaml
receivers:
  # ... existing receivers ...
  host_metrics:
    collection_interval: 10s
    scrapers:
      cpu:
        metrics:
          system.cpu.utilization: {enabled: true}
          system.cpu.time: {enabled: true}
      load:
        metrics:
          system.cpu.load_average.1m: {enabled: true}
          system.cpu.load_average.5m: {enabled: true}
          system.cpu.load_average.15m: {enabled: true}
      memory:
        metrics:
          system.memory.usage: {enabled: true}
          system.memory.utilization: {enabled: true}
      disk:
        metrics:
          system.disk.io: {enabled: true}
          system.disk.operations: {enabled: true}
      filesystem:
        metrics:
          system.filesystem.usage: {enabled: true}
          system.filesystem.utilization: {enabled: true}
      network:
        metrics:
          system.network.io: {enabled: true}
          system.network.packets: {enabled: true}
```

Add a **separate** `metrics/host` pipeline for host metrics (do not add `hostmetrics` to the Redis pipeline):

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [redis]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
    metrics/host:
      receivers: [host_metrics]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, batch]
      exporters: [otlp_http]
```

#### Optional: Add custom metadata [#custom-metadata-nrdot]

Custom resource attributes tag every Redis metric with context — environment, team, or tier — so you can filter and group your data in New Relic. Add a `resource/custom` processor with the tags you want:

```yaml
processors:
  # ... existing processors ...
  resource/custom:
    attributes:
      - key: environment
        value: "production"
        action: upsert
      - key: team
        value: "platform"
        action: upsert
      - key: redis.cluster
        value: "cache-tier-1"
        action: upsert
```

Include the processor in your pipeline:

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [redis]
      processors: [memory_limiter, resource_detection, resource/custom, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
```

#### Optional: Enable Redis Cluster monitoring [#cluster-nrdot]

Redis Cluster monitoring currently requires the Prometheus receiver approach (using `redis_exporter`). The NRDOT Collector's native Redis receiver does not yet support the `CLUSTER INFO` command needed for cluster metrics. Use the [Prometheus receiver](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/host/#prometheus) tab for cluster monitoring setup.

#### Set environment variables [#env-nrdot]

The collector reads deployment-specific values — your license key, OTLP endpoint, and config path — from an environment file, which keeps secrets out of the config YAML. Create the environment file:

```bash
sudo tee /etc/nrdot-collector/nrdot-collector.conf > /dev/null <<'EOF'
NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY
OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT
# Set the New Relic OTLP endpoint for your region.
# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp
OTELCOL_OPTIONS="--config=/etc/nrdot-collector/redis-collector-config.yaml"
EOF
sudo chmod 600 /etc/nrdot-collector/nrdot-collector.conf
```

Replace the placeholders with your own values:

| Variable                      | Required | Description                                                                                                                                                                   |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEW_RELIC_LICENSE_KEY`       | Yes      | Your New Relic [ingest license key](https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#ingest-license-key).                                                   |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Yes      | New Relic OTLP endpoint for your region. For more information, see [New Relic OTLP endpoint](https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp). |
| `OTELCOL_OPTIONS`             | Yes      | Points the collector at your Redis configuration file.                                                                                                                        |

> #### 💡 TIP
>
> This configuration replaces the default NRDot configuration. If you need to preserve the default NRDot pipelines alongside Redis monitoring, add the default config file as well:
>
> ```bash
> OTELCOL_OPTIONS="--config=/etc/nrdot-collector/config.yaml --config=/etc/nrdot-collector/redis-collector-config.yaml"
> ```
>
> When using multiple config files, ensure there are no conflicting component names between them. Rename any duplicate processors in your Redis config by adding a suffix (e.g., `memory_limiter/redis` instead of `memory_limiter`).

#### Restart and verify [#verify-nrdot]

Restart the collector to load the new configuration:

```bash
sudo systemctl daemon-reload
sudo systemctl restart nrdot-collector
sudo systemctl status nrdot-collector
```

The `status` command should show `Active: active (running)`. If it shows `Active: failed`, check the logs with `journalctl -u nrdot-collector -n 100 --no-pager` — the most common causes are YAML indentation errors and an unreachable Redis endpoint.

Then confirm your metrics are reaching New Relic. Wait about a minute after the restart, then run this query in the [query builder](https://docs.newrelic.com/docs/query-your-data/explore-query-data/query-builder/introduction-query-builder/):

```sql
SELECT count(*) FROM Metric WHERE metricName LIKE 'redis.%' AND instrumentation.provider = 'opentelemetry' SINCE 5 minutes ago
```

A non-zero count confirms Redis metrics are flowing. If it returns `0`, see [Troubleshoot Redis (OpenTelemetry)](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/troubleshooting).

### OpenTelemetry Collector Contrib

#### Install the collector [#install-otel]

Install the [OpenTelemetry Collector Contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/latest) if it's not already present:

**Debian / Ubuntu**

```bash
OTEL_VERSION=$(curl -sf "https://api.github.com/repos/open-telemetry/opentelemetry-collector-releases/releases/latest" | grep tag_name | cut -d '"' -f 4 | sed 's/^v//')
echo "Installing OTel Collector Contrib v${OTEL_VERSION}..."
wget -q "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_VERSION}/otelcol-contrib_${OTEL_VERSION}_linux_amd64.deb"
sudo dpkg -i "otelcol-contrib_${OTEL_VERSION}_linux_amd64.deb"
rm -f "otelcol-contrib_${OTEL_VERSION}_linux_amd64.deb"
```

**RHEL / CentOS**

```bash
OTEL_VERSION=$(curl -sf "https://api.github.com/repos/open-telemetry/opentelemetry-collector-releases/releases/latest" | grep tag_name | cut -d '"' -f 4 | sed 's/^v//')
echo "Installing OTel Collector Contrib v${OTEL_VERSION}..."
wget -q "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${OTEL_VERSION}/otelcol-contrib_${OTEL_VERSION}_linux_amd64.rpm"
sudo rpm -ivh "otelcol-contrib_${OTEL_VERSION}_linux_amd64.rpm"
rm -f "otelcol-contrib_${OTEL_VERSION}_linux_amd64.rpm"
```

After installation, the collector is available as a systemd service named `otelcol-contrib.service`.

#### Configure Redis monitoring [#configure-otel]

This configuration tells the collector how to gather Redis metrics and send them to New Relic. It handles three main jobs:

-   **Collect** metrics from Redis through the `redis` receiver
-   **Shape** the data — reduce cardinality, convert counters to deltas, and tag it for entity synthesis
-   **Export** the processed metrics to New Relic over OTLP

Create the collector configuration file:

```bash
sudo nano /etc/otelcol-contrib/redis-collector-config.yaml
```

Paste the following configuration, updating the Redis `endpoint` if it isn't `localhost:6379`:

```yaml
extensions:
  health_check:
    endpoint: "0.0.0.0:13133"

receivers:
  redis:
    endpoint: "localhost:6379"  # Update with your Redis host:port
    collection_interval: 10s
    metrics:
      redis.maxmemory:
        enabled: true
      redis.role:
        enabled: false
      redis.cmd.calls:
        enabled: true
      redis.cmd.usec:
        enabled: true
      redis.clients.max_input_buffer:
        enabled: false
      redis.clients.max_output_buffer:
        enabled: false
      redis.replication.backlog_first_byte_offset:
        enabled: false
    resource_attributes:
      server.address:
        enabled: true
      server.port:
        enabled: true

processors:
  memory_limiter:
    check_interval: 5s
    limit_mib: 512
    spike_limit_mib: 128

  resource_detection:
    detectors: [env, system]
    timeout: 5s
    override: false
    system:
      resource_attributes:
        host.name:
          enabled: true
        host.id:
          enabled: true

  # Uncomment the section below to use a custom human-readable name for your
  # Redis entity instead of the default server.address:server.port identifier.
  # resource/redis:
  #   attributes:
  #     - key: redis.instance.id
  #       value: "my-redis-instance"
  #       action: upsert

  attributes/entity_tags:
    actions:
      - key: instrumentation.provider
        value: opentelemetry
        action: upsert

  cumulativetodelta:
    include:
      match_type: regexp
      metrics:
        - redis\.commands\.processed
        - redis\.connections\.received
        - redis\.connections\.rejected
        - redis\.keys\.evicted
        - redis\.keys\.expired
        - redis\.keyspace\.hits
        - redis\.keyspace\.misses
        - redis\.net\.input
        - redis\.net\.output
        - redis\.cpu\.time
        - redis\.cmd\.calls
        - redis\.cmd\.usec
        - redis\.uptime

  filter/cardinality:
    metrics:
      datapoint:
        - 'metric.name == "redis.cpu.time" and attributes["state"] != "sys" and attributes["state"] != "user"'
        - 'metric.name == "redis.cmd.calls" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'
        - 'metric.name == "redis.cmd.usec" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'

  transform/metadata_nullify:
    metric_statements:
      - context: metric
        statements:
          - set(description, "")
          - set(unit, "")

  batch:
    send_batch_size: 2048
    send_batch_max_size: 4096
    timeout: 10s

exporters:
  otlp_http:
    endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
    headers:
      api-key: ${env:NEW_RELIC_LICENSE_KEY}
    compression: gzip

service:
  extensions: [health_check]
  pipelines:
    metrics/redis:
      receivers: [redis]
      # If using resource/redis for custom name, add it to the processors list:
      # processors: [memory_limiter, resource_detection, resource/redis, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
```

##### What this configuration does [#config-explanation-otel]

Each component in the pipeline has a specific job:

| Component                    | Description                                                                                                                                                        |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `health_check`               | Exposes a health endpoint on `0.0.0.0:13133` so you can confirm the collector is running.                                                                          |
| `redis` receiver             | Connects to your Redis endpoint every 10 seconds and reads metrics from the Redis `INFO` command. `server.address` and `server.port` become the entity's identity. |
| `memory_limiter`             | Caps collector memory usage (512 MiB soft limit, 128 MiB spike) to protect the host.                                                                               |
| `resource_detection`         | Detects the host and adds `host.name` and `host.id`, linking Redis metrics to the underlying host entity.                                                          |
| `attributes/entity_tags`     | Stamps `instrumentation.provider: opentelemetry` on every metric so you can scope queries to the OpenTelemetry path.                                               |
| `cumulativetodelta`          | Converts Redis's cumulative counters — commands, keyspace hits, evictions, and so on — to delta values so New Relic charts rates correctly.                        |
| `filter/cardinality`         | Drops high-cardinality data points (CPU states other than `user` and `sys`, and per-command metrics for uncommon commands) to control ingest cost.                 |
| `transform/metadata_nullify` | Clears metric descriptions and units to reduce payload size.                                                                                                       |
| `batch`                      | Groups data points before export (2,048 per batch, up to 4,096) and flushes at least every 10 seconds to reduce network overhead.                                  |
| `otlp_http`                  | Exports the processed metrics to New Relic over OTLP with gzip compression, authenticated with your license key.                                                   |

> #### 💡 TIP
>
> **Want a user-friendly entity name?** By default, your Redis entity is named using the `server.address:server.port` combination. To use a custom human-readable name instead, uncomment the `resource/redis` section in the config above, set your preferred name in the `redis.instance.id` value, and add `resource/redis` to the processors pipeline.

#### Optional: Configure authentication [#auth-otel]

By default, the collector connects to Redis without credentials. If your Redis instance requires authentication, add the matching credentials to the `redis` receiver. Choose the option that matches your setup:

**Legacy password (requirepass)**

For Redis instances using a single shared password (`requirepass` in redis.conf):

```yaml
receivers:
  redis:
    endpoint: "redis-host:6379"
    password: "${env:REDIS_PASSWORD}"
```

**ACL username + password (Redis 6+)**

For Redis 6+ instances using Access Control Lists:

```yaml
receivers:
  redis:
    endpoint: "redis-host:6379"
    username: "${env:REDIS_USERNAME}"
    password: "${env:REDIS_PASSWORD}"
```

**TLS/SSL encrypted connection**

For Redis instances requiring encrypted connections:

```yaml
receivers:
  redis:
    endpoint: "redis-host:6380"
    password: "${env:REDIS_PASSWORD}"
    tls:
      insecure: false
      ca_file: /etc/ssl/redis/ca.crt
      cert_file: /etc/ssl/redis/client.crt
      key_file: /etc/ssl/redis/client.key
```

#### Optional: Collect Redis logs [#logs-otel]

Beyond metrics, the collector can forward Redis's log file to New Relic so you can correlate log events — restarts, persistence events, or errors — with metric spikes on the same entity. Add the `filelog` receiver to tail the Redis log:

```yaml
receivers:
  # ... existing redis receiver ...
  file_log/redis:
    include:
      - /var/log/redis/redis-server.log
    start_at: end
    operators:
      - type: regex_parser
        regex: '^\d+:[XCSM] \d+ \w+ \d+ \d+:\d+:\d+\.\d+ (?P<level>.) '
        on_error: send
    resource:
      db.system: redis
```

Log lines from the file have no Redis connection context on their own — you must explicitly attach identity attributes so New Relic associates the logs with your Redis entity. Add a `resource/redis_logs` processor with **hardcoded values matching your Redis entity's identity**:

```yaml
processors:
  # ... existing processors ...
  resource/redis_logs:
    attributes:
      - key: server.address
        value: "localhost"  # Must match your redis receiver endpoint host
        action: upsert
      - key: server.port
        value: 6379  # Must match your redis receiver endpoint port
        action: upsert
      - key: instrumentation.provider
        value: opentelemetry
        action: upsert
```

> #### 💡 TIP
>
> **Using a custom instance ID?** If you enabled the `resource/redis` processor for custom entity naming, replace `server.address` and `server.port` above with your `redis.instance.id`:
>
> ```yaml
>   resource/redis_logs:
>     attributes:
>       - key: redis.instance.id
>         value: "my-redis-instance"  # Must match the value in resource/redis
>         action: upsert
>       - key: instrumentation.provider
>         value: opentelemetry
>         action: upsert
> ```

Add a **separate** logs pipeline to the service section:

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [redis]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
    logs/redis:
      receivers: [file_log/redis]
      processors: [memory_limiter, resource/redis_logs, batch]
      exporters: [otlp_http]
```

> #### ⚠️ IMPORTANT
>
> The collector must have read access to both the Redis log file and its parent directory. Run:
>
> ```bash
> sudo chmod 755 /var/log/redis
> sudo chmod 644 /var/log/redis/redis-server.log
> ```

#### Optional: Collect host metrics [#hostmetrics-otel]

Redis performance often tracks host resource pressure — CPU saturation, memory exhaustion, or disk I/O contention. Add the `hostmetrics` receiver to collect system metrics from the host alongside Redis, so you can correlate the two in New Relic:

```yaml
receivers:
  # ... existing receivers ...
  host_metrics:
    collection_interval: 10s
    scrapers:
      cpu:
        metrics:
          system.cpu.utilization: {enabled: true}
          system.cpu.time: {enabled: true}
      load:
        metrics:
          system.cpu.load_average.1m: {enabled: true}
          system.cpu.load_average.5m: {enabled: true}
          system.cpu.load_average.15m: {enabled: true}
      memory:
        metrics:
          system.memory.usage: {enabled: true}
          system.memory.utilization: {enabled: true}
      disk:
        metrics:
          system.disk.io: {enabled: true}
          system.disk.operations: {enabled: true}
      filesystem:
        metrics:
          system.filesystem.usage: {enabled: true}
          system.filesystem.utilization: {enabled: true}
      network:
        metrics:
          system.network.io: {enabled: true}
          system.network.packets: {enabled: true}
```

Add a **separate** `metrics/host` pipeline for host metrics (do not add `host_metrics` to the Redis pipeline):

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [redis]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
    metrics/host:
      receivers: [host_metrics]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, batch]
      exporters: [otlp_http]
```

#### Optional: Enable Redis Cluster monitoring [#cluster-otel]

Redis Cluster monitoring currently requires the Prometheus receiver approach (using `redis_exporter`). The OpenTelemetry Collector Contrib's native Redis receiver does not yet support the `CLUSTER INFO` command needed for cluster metrics. Use the [Prometheus receiver](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/host/#prometheus) tab for cluster monitoring setup.

#### Set environment variables [#env-otel]

The collector reads deployment-specific values — your license key, OTLP endpoint, and config path — from an environment file, which keeps secrets out of the config YAML. Create the environment file:

```bash
sudo tee /etc/otelcol-contrib/otelcol-contrib.conf > /dev/null <<'EOF'
NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY
OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT
# Set the New Relic OTLP endpoint for your region.
# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp
OTELCOL_OPTIONS="--config=/etc/otelcol-contrib/redis-collector-config.yaml"
EOF
sudo chmod 600 /etc/otelcol-contrib/otelcol-contrib.conf
```

Replace the placeholders with your own values:

| Variable                      | Required | Description                                                                                                                                                                   |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEW_RELIC_LICENSE_KEY`       | Yes      | Your New Relic [ingest license key](https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#ingest-license-key).                                                   |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Yes      | New Relic OTLP endpoint for your region. For more information, see [New Relic OTLP endpoint](https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp). |
| `OTELCOL_OPTIONS`             | Yes      | Points the collector at your Redis configuration file.                                                                                                                        |

> #### 💡 TIP
>
> This configuration replaces the default OTel Collector Contrib configuration. If you need to preserve the default config alongside Redis monitoring, add the default config file as well:
>
> ```bash
> OTELCOL_OPTIONS="--config=/etc/otelcol-contrib/config.yaml --config=/etc/otelcol-contrib/redis-collector-config.yaml"
> ```
>
> When using multiple config files, ensure there are no conflicting component names between them. Rename any duplicate processors in your Redis config by adding a suffix (e.g., `memory_limiter/redis` instead of `memory_limiter`).

#### Restart and verify [#verify-otel]

Restart the collector to load the new configuration:

```bash
sudo systemctl daemon-reload
sudo systemctl restart otelcol-contrib
sudo systemctl status otelcol-contrib
```

The `status` command should show `Active: active (running)`. If it shows `Active: failed`, check the logs with `journalctl -u otelcol-contrib -n 100 --no-pager` — the most common causes are YAML indentation errors and an unreachable Redis endpoint.

Then confirm your metrics are reaching New Relic. Wait about a minute after the restart, then run this query in the [query builder](https://docs.newrelic.com/docs/query-your-data/explore-query-data/query-builder/introduction-query-builder/):

```sql
SELECT count(*) FROM Metric WHERE metricName LIKE 'redis.%' AND instrumentation.provider = 'opentelemetry' SINCE 5 minutes ago
```

A non-zero count confirms Redis metrics are flowing. If it returns `0`, see [Troubleshoot Redis (OpenTelemetry)](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/troubleshooting).

### Prometheus receiver

#### Install redis_exporter [#install-exporter]

The [redis_exporter](https://github.com/oliver006/redis_exporter) exposes Redis metrics in Prometheus format on port 9121.

**Debian / Ubuntu**

```bash
EXPORTER_VERSION=$(curl -sf "https://api.github.com/repos/oliver006/redis_exporter/releases/latest" | grep tag_name | cut -d '"' -f 4 | sed 's/^v//')
echo "Installing redis_exporter v${EXPORTER_VERSION}..."
wget -q "https://github.com/oliver006/redis_exporter/releases/download/v${EXPORTER_VERSION}/redis_exporter-v${EXPORTER_VERSION}.linux-amd64.tar.gz"
tar xzf "redis_exporter-v${EXPORTER_VERSION}.linux-amd64.tar.gz"
sudo mv "redis_exporter-v${EXPORTER_VERSION}.linux-amd64/redis_exporter" /usr/local/bin/
rm -rf "redis_exporter-v${EXPORTER_VERSION}.linux-amd64" "redis_exporter-v${EXPORTER_VERSION}.linux-amd64.tar.gz"
```

**RHEL / CentOS**

```bash
EXPORTER_VERSION=$(curl -sf "https://api.github.com/repos/oliver006/redis_exporter/releases/latest" | grep tag_name | cut -d '"' -f 4 | sed 's/^v//')
echo "Installing redis_exporter v${EXPORTER_VERSION}..."
wget -q "https://github.com/oliver006/redis_exporter/releases/download/v${EXPORTER_VERSION}/redis_exporter-v${EXPORTER_VERSION}.linux-amd64.tar.gz"
tar xzf "redis_exporter-v${EXPORTER_VERSION}.linux-amd64.tar.gz"
sudo mv "redis_exporter-v${EXPORTER_VERSION}.linux-amd64/redis_exporter" /usr/local/bin/
rm -rf "redis_exporter-v${EXPORTER_VERSION}.linux-amd64" "redis_exporter-v${EXPORTER_VERSION}.linux-amd64.tar.gz"
```

Create a systemd service for `redis_exporter`:

```bash
sudo tee /etc/systemd/system/redis_exporter.service > /dev/null <<'EOF'
[Unit]
Description=Redis Exporter
After=network.target

[Service]
ExecStart=/usr/local/bin/redis_exporter --redis.addr=redis://localhost:6379
Restart=always
User=nobody

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now redis_exporter
```

Verify the exporter is running:

```bash
curl -s http://localhost:9121/metrics | grep redis_up
```

You should see `redis_up 1`.

**Redis authentication and TLS**

If your Redis requires a password:

```bash
ExecStart=/usr/local/bin/redis_exporter --redis.addr=redis://localhost:6379 --redis.password=YOUR_PASSWORD
```

For Redis 6+ ACL authentication:

```bash
ExecStart=/usr/local/bin/redis_exporter --redis.addr=redis://localhost:6379 --redis.user=otel-monitor --redis.password=YOUR_PASSWORD
```

For TLS-encrypted Redis, use the `rediss://` scheme:

```bash
ExecStart=/usr/local/bin/redis_exporter --redis.addr=rediss://localhost:6380
```

#### Create the collector configuration [#config-prometheus]

This configuration scrapes metrics from `redis_exporter` and sends them to New Relic. It handles these main jobs:

-   **Scrape** the `redis_exporter` Prometheus endpoint through the `prometheus` receiver
-   **Rename** the Prometheus metrics to New Relic's Redis metric names
-   **Shape** the data — reduce cardinality, convert counters to deltas, and tag it for entity synthesis
-   **Export** the processed metrics to New Relic over OTLP

Create the config file. Use the path appropriate for your collector:

-   NRDOT: `/etc/nrdot-collector/redis-prometheus-config.yaml`
-   OTel Contrib: `/etc/otelcol-contrib/redis-prometheus-config.yaml`

```yaml
extensions:
  health_check:
    endpoint: "0.0.0.0:13133"

receivers:
  prometheus:
    config:
      scrape_configs:
        - job_name: 'redis'
          scrape_interval: 10s
          static_configs:
            - targets: ['localhost:9121']  # Update with your Redis exporter host:port
          metric_relabel_configs:
            - source_labels: [__name__]
              regex: '(go_|process_|promhttp_|redis_exporter_).*'
              action: drop

processors:
  memory_limiter:
    check_interval: 5s
    limit_mib: 512
    spike_limit_mib: 128

  resource_detection:
    detectors: [env, system]
    timeout: 5s
    override: false
    system:
      resource_attributes:
        host.name:
          enabled: true
        host.id:
          enabled: true

  # Required: Set a unique identifier for your Redis entity.
  # The Prometheus receiver does not provide server.address/server.port,
  # so redis.instance.id is required for entity creation in New Relic.
  resource/redis_identity:
    attributes:
      - key: redis.instance.id
        value: "my-redis-instance:6379"  # Update with a unique name for this Redis instance
        action: upsert

  attributes/entity_tags:
    actions:
      - key: instrumentation.provider
        value: opentelemetry
        action: upsert

  metricstransform:
    transforms:
      - include: redis_uptime_in_seconds
        action: update
        new_name: redis.uptime
      - include: redis_connected_clients
        action: update
        new_name: redis.clients.connected
      - include: redis_blocked_clients
        action: update
        new_name: redis.clients.blocked
      - include: redis_memory_used_bytes
        action: update
        new_name: redis.memory.used
      - include: redis_memory_max_bytes
        action: update
        new_name: redis.maxmemory
      - include: redis_mem_fragmentation_ratio
        action: update
        new_name: redis.memory.fragmentation_ratio
      - include: redis_memory_used_rss_bytes
        action: update
        new_name: redis.memory.rss
      - include: redis_memory_used_peak_bytes
        action: update
        new_name: redis.memory.peak
      - include: redis_memory_used_lua_bytes
        action: update
        new_name: redis.memory.lua
      - include: redis_connections_received_total
        action: update
        new_name: redis.connections.received
      - include: redis_rejected_connections_total
        action: update
        new_name: redis.connections.rejected
      - include: redis_commands_processed_total
        action: update
        new_name: redis.commands.processed
      - include: redis_keyspace_hits_total
        action: update
        new_name: redis.keyspace.hits
      - include: redis_keyspace_misses_total
        action: update
        new_name: redis.keyspace.misses
      - include: redis_evicted_keys_total
        action: update
        new_name: redis.keys.evicted
      - include: redis_expired_keys_total
        action: update
        new_name: redis.keys.expired
      - include: redis_net_input_bytes_total
        action: update
        new_name: redis.net.input
      - include: redis_net_output_bytes_total
        action: update
        new_name: redis.net.output
      - include: redis_connected_slaves
        action: update
        new_name: redis.slaves.connected
      - include: redis_db_keys
        action: update
        new_name: redis.db.keys
      - include: redis_db_keys_expiring
        action: update
        new_name: redis.db.expires
      - include: redis_rdb_changes_since_last_save
        action: update
        new_name: redis.rdb.changes_since_last_save
      - include: redis_db_avg_ttl_seconds
        action: update
        new_name: redis.db.avg_ttl
      - include: redis_latest_fork_seconds
        action: update
        new_name: redis.latest_fork
      - include: redis_master_repl_offset
        action: update
        new_name: redis.replication.offset
      - include: redis_repl_backlog_first_byte_offset
        action: update
        new_name: redis.replication.backlog_first_byte_offset
      - include: redis_commands_total
        action: update
        new_name: redis.cmd.calls
      - include: redis_commands_duration_seconds_total
        action: update
        new_name: redis.cmd.usec
      - include: redis_cpu_sys_seconds_total
        action: update
        new_name: redis.cpu.time
        operations:
          - action: add_label
            new_label: state
            new_value: sys
      - include: redis_cpu_user_seconds_total
        action: update
        new_name: redis.cpu.time
        operations:
          - action: add_label
            new_label: state
            new_value: user

  cumulativetodelta:
    include:
      match_type: regexp
      metrics:
        - redis\.commands\.processed
        - redis\.connections\.received
        - redis\.connections\.rejected
        - redis\.keys\.evicted
        - redis\.keys\.expired
        - redis\.keyspace\.hits
        - redis\.keyspace\.misses
        - redis\.net\.input
        - redis\.net\.output
        - redis\.cpu\.time
        - redis\.cmd\.calls
        - redis\.cmd\.usec
        - redis\.uptime

  filter/cardinality:
    metrics:
      datapoint:
        - 'metric.name == "redis.cpu.time" and attributes["state"] != "sys" and attributes["state"] != "user"'
        - 'metric.name == "redis.cmd.calls" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'
        - 'metric.name == "redis.cmd.usec" and attributes["cmd"] != "get" and attributes["cmd"] != "set" and attributes["cmd"] != "del" and attributes["cmd"] != "hget" and attributes["cmd"] != "hset" and attributes["cmd"] != "hgetall" and attributes["cmd"] != "lpush" and attributes["cmd"] != "rpop" and attributes["cmd"] != "zadd" and attributes["cmd"] != "expire"'

  transform/metadata_nullify:
    metric_statements:
      - context: metric
        statements:
          - set(description, "")
          - set(unit, "")

  batch:
    send_batch_size: 2048
    send_batch_max_size: 4096
    timeout: 10s

exporters:
  otlp_http:
    endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT}
    headers:
      api-key: ${env:NEW_RELIC_LICENSE_KEY}
    compression: gzip

service:
  extensions: [health_check]
  pipelines:
    metrics/redis:
      receivers: [prometheus]
      processors: [memory_limiter, resource_detection, resource/redis_identity, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
```

##### What this configuration does [#config-explanation-prometheus]

Each component in the pipeline has a specific job:

| Component                    | Description                                                                                                                                                                       |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `health_check`               | Exposes a health endpoint on `0.0.0.0:13133` so you can confirm the collector is running.                                                                                         |
| `prometheus` receiver        | Scrapes the `redis_exporter` endpoint (default `localhost:9121`) every 10 seconds and drops the exporter's own `go_*`, `process_*`, `promhttp_*`, and `redis_exporter_*` metrics. |
| `memory_limiter`             | Caps collector memory usage (512 MiB soft limit, 128 MiB spike) to protect the host.                                                                                              |
| `resource_detection`         | Detects the host and adds `host.name` and `host.id`, linking Redis metrics to the underlying host entity.                                                                         |
| `resource/redis_identity`    | Sets `redis.instance.id`, which identifies the Redis entity in New Relic. It's required here because the Prometheus receiver doesn't provide `server.address` or `server.port`.   |
| `attributes/entity_tags`     | Stamps `instrumentation.provider: opentelemetry` on every metric so you can scope queries to the OpenTelemetry path.                                                              |
| `metricstransform`           | Renames the exporter's Prometheus metrics (for example, `redis_uptime_in_seconds`) to New Relic's Redis names (`redis.uptime`) and adds the `state` label to CPU metrics.         |
| `cumulativetodelta`          | Converts cumulative counters — commands, keyspace hits, evictions, and so on — to delta values so New Relic charts rates correctly.                                               |
| `filter/cardinality`         | Drops high-cardinality data points (CPU states other than `user` and `sys`, and per-command metrics for uncommon commands) to control ingest cost.                                |
| `transform/metadata_nullify` | Clears metric descriptions and units to reduce payload size.                                                                                                                      |
| `batch`                      | Groups data points before export (2,048 per batch, up to 4,096) and flushes at least every 10 seconds to reduce network overhead.                                                 |
| `otlp_http`                  | Exports the processed metrics to New Relic over OTLP with gzip compression, authenticated with your license key.                                                                  |

> #### ⚠️ IMPORTANT
>
> The `resource/redis_identity` processor with `redis.instance.id` is **required** for the Prometheus receiver approach. Unlike the native Redis receiver, the Prometheus receiver does not provide `server.address` or `server.port` — so `redis.instance.id` is the only way to identify your Redis entity in New Relic. Set it to a unique, descriptive name for each instance (e.g., `prod-redis-cache:6379`).

#### Optional: Enable Redis Cluster monitoring [#cluster-prometheus]

If your Redis is running in Cluster mode, start `redis_exporter` with the `--is-cluster` flag to automatically collect cluster health metrics from all nodes:

```bash
redis_exporter --redis.addr=redis://localhost:7000 --is-cluster
```

The Prometheus receiver configuration above already renames cluster metrics (e.g., `redis_cluster_state` → `redis.cluster.state`). To create a separate cluster entity in New Relic, add a `redis.cluster.name` resource attribute to a **separate pipeline** that does NOT include `redis.instance.id`:

```yaml
  resource/cluster:
    attributes:
      - key: redis.cluster.name
        value: "my-redis-cluster"  # Update with your cluster name
        action: upsert
```

Add a cluster pipeline to your service section:

```yaml
    metrics/cluster:
      receivers: [prometheus]
      processors: [memory_limiter, resource_detection, resource/cluster, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
```

> #### ⚠️ IMPORTANT
>
> The cluster entity requires `redis.cluster.name` to be present AND `redis.instance.id` to be absent. If both are set on the same metrics, only the instance entity will be created. Use separate pipelines for instance and cluster metrics.

#### Optional: Collect Redis logs [#logs-prometheus]

Beyond metrics, the collector can forward Redis's log file to New Relic so you can correlate log events — restarts, persistence events, or errors — with metric spikes on the same entity. Add the `filelog` receiver to tail the Redis log:

```yaml
receivers:
  # ... existing prometheus receiver ...
  file_log/redis:
    include:
      - /var/log/redis/redis-server.log
    start_at: end
    operators:
      - type: regex_parser
        regex: '^\d+:[XCSM] \d+ \w+ \d+ \d+:\d+:\d+\.\d+ (?P<level>.) '
        on_error: send
    resource:
      db.system: redis
```

Log lines from the file have no Redis connection context on their own — you must explicitly attach identity attributes so New Relic associates the logs with your Redis entity. Add a `resource/redis_logs` processor with **hardcoded values matching your Redis entity's identity**:

```yaml
processors:
  # ... existing processors ...
  resource/redis_logs:
    attributes:
      - key: redis.instance.id
        value: "my-redis-instance:6379"  # Must match the value in resource/redis_identity
        action: upsert
      - key: instrumentation.provider
        value: opentelemetry
        action: upsert
```

Add a **separate** logs pipeline to the service section:

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [prometheus]
      processors: [memory_limiter, resource_detection, resource/redis_identity, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
    logs/redis:
      receivers: [file_log/redis]
      processors: [memory_limiter, resource/redis_logs, batch]
      exporters: [otlp_http]
```

> #### ⚠️ IMPORTANT
>
> The collector must have read access to both the Redis log file and its parent directory. Run:
>
> ```bash
> sudo chmod 755 /var/log/redis
> sudo chmod 644 /var/log/redis/redis-server.log
> ```

#### Optional: Collect host metrics [#hostmetrics-prometheus]

Redis performance often tracks host resource pressure — CPU saturation, memory exhaustion, or disk I/O contention. Add the `hostmetrics` receiver to collect system metrics from the host alongside Redis, so you can correlate the two in New Relic:

```yaml
receivers:
  # ... existing receivers ...
  host_metrics:
    collection_interval: 10s
    scrapers:
      cpu:
        metrics:
          system.cpu.utilization: {enabled: true}
          system.cpu.time: {enabled: true}
      load:
        metrics:
          system.cpu.load_average.1m: {enabled: true}
          system.cpu.load_average.5m: {enabled: true}
          system.cpu.load_average.15m: {enabled: true}
      memory:
        metrics:
          system.memory.usage: {enabled: true}
          system.memory.utilization: {enabled: true}
      disk:
        metrics:
          system.disk.io: {enabled: true}
          system.disk.operations: {enabled: true}
      filesystem:
        metrics:
          system.filesystem.usage: {enabled: true}
          system.filesystem.utilization: {enabled: true}
      network:
        metrics:
          system.network.io: {enabled: true}
          system.network.packets: {enabled: true}
```

Add a **separate** `metrics/host` pipeline for host metrics (do not add `host_metrics` to the Redis pipeline):

```yaml
service:
  pipelines:
    metrics/redis:
      receivers: [prometheus]
      processors: [memory_limiter, resource_detection, resource/redis_identity, attributes/entity_tags, metricstransform, cumulativetodelta, filter/cardinality, transform/metadata_nullify, batch]
      exporters: [otlp_http]
    metrics/host:
      receivers: [host_metrics]
      processors: [memory_limiter, resource_detection, attributes/entity_tags, cumulativetodelta, batch]
      exporters: [otlp_http]
```

#### Set environment variables and config path [#env-prometheus]

The collector reads deployment-specific values — your license key, OTLP endpoint, and config path — from an environment file, which keeps secrets out of the config YAML. Set these for whichever collector you installed:

| Variable                      | Required | Description                                                                                                                                                                   |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NEW_RELIC_LICENSE_KEY`       | Yes      | Your New Relic [ingest license key](https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#ingest-license-key).                                                   |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Yes      | New Relic OTLP endpoint for your region. For more information, see [New Relic OTLP endpoint](https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp). |
| `OTELCOL_OPTIONS`             | Yes      | Points the collector at your Redis Prometheus configuration file.                                                                                                             |

For **NRDOT**:

```bash
sudo tee /etc/nrdot-collector/nrdot-collector.conf > /dev/null <<'EOF'
NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY
OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT
# Set the New Relic OTLP endpoint for your region.
# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp
OTELCOL_OPTIONS="--config=/etc/nrdot-collector/redis-prometheus-config.yaml"
EOF
sudo chmod 600 /etc/nrdot-collector/nrdot-collector.conf
```

> #### 💡 TIP
>
> This configuration replaces the default NRDot configuration. If you need to preserve the default NRDot pipelines alongside Redis monitoring, add the default config file as well:
>
> ```bash
> OTELCOL_OPTIONS="--config=/etc/nrdot-collector/config.yaml --config=/etc/nrdot-collector/redis-prometheus-config.yaml"
> ```
>
> When using multiple config files, ensure there are no conflicting component names between them. Rename any duplicate processors in your Redis config by adding a suffix (e.g., `memory_limiter/redis` instead of `memory_limiter`).

For **OTel Collector Contrib**:

```bash
sudo tee /etc/otelcol-contrib/otelcol-contrib.conf > /dev/null <<'EOF'
NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY
OTEL_EXPORTER_OTLP_ENDPOINT=YOUR_OTLP_ENDPOINT
# Set the New Relic OTLP endpoint for your region.
# See https://docs.newrelic.com/docs/opentelemetry/best-practices/opentelemetry-otlp
OTELCOL_OPTIONS="--config=/etc/otelcol-contrib/redis-prometheus-config.yaml"
EOF
sudo chmod 600 /etc/otelcol-contrib/otelcol-contrib.conf
```

#### Restart and verify [#verify-prometheus]

Restart the collector to load the new configuration.

For **NRDOT**:

```bash
sudo systemctl daemon-reload
sudo systemctl restart nrdot-collector
sudo systemctl status nrdot-collector
```

For **OTel Collector Contrib**:

```bash
sudo systemctl daemon-reload
sudo systemctl restart otelcol-contrib
sudo systemctl status otelcol-contrib
```

The `status` command should show `Active: active (running)`. If it shows `Active: failed`, check the logs with `journalctl -u nrdot-collector -n 100 --no-pager` (or `otelcol-contrib`) — the most common causes are YAML indentation errors, an unreachable `redis_exporter`, or the exporter not running.

Then confirm your metrics are reaching New Relic. Wait about a minute after the restart, then run this query in the [query builder](https://docs.newrelic.com/docs/query-your-data/explore-query-data/query-builder/introduction-query-builder/):

```sql
SELECT count(*) FROM Metric WHERE metricName LIKE 'redis.%' AND instrumentation.provider = 'opentelemetry' SINCE 5 minutes ago
```

A non-zero count confirms Redis metrics are flowing. If it returns `0`, see [Troubleshoot Redis (OpenTelemetry)](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/troubleshooting).

> #### 💡 TIP
>
> **Correlate APM with Redis**: To connect your APM application and Redis instance in service maps, include `db.system="redis"` along with your chosen entity identifier pattern — either `redis.instance.id` or `server.address` and `server.port` — as resource attributes in your APM metrics. The values must match what you configured in the collector. This enables cross-service visibility and faster troubleshooting within New Relic.

## Next steps [#next-steps]

-   **[Docker installation](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/docker)**: Deploy with Docker Compose
-   **[Kubernetes installation](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/kubernetes)**: Deploy on Kubernetes with the DaemonSet pattern
-   **[View your data](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/view-data)**: Explore dashboards and set up alerts
-   **[Metrics reference](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/metrics)**: Complete list of available metrics
-   **[Troubleshooting](https://docs.newrelic.com/docs/opentelemetry/integrations/redis/troubleshooting)**: Common issues and solutions
