> ## Documentation Index
> Fetch the complete documentation index at: https://docs.conduktor.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Client metrics Interceptor

> Collect client-side Kafka metrics through KIP-714 and forward them to an OpenTelemetry collector, enriched with Gateway identity labels.

The client metrics Interceptor terminates [Kafka Improvement Proposal 714 (KIP-714)](https://cwiki.apache.org/confluence/display/KAFKA/KIP-714%3A+Client+metrics+and+observability) client telemetry in Gateway and forwards it to an OpenTelemetry (OTLP) collector. Kafka clients from 3.7.0 onward push metrics by default (`enable.metrics.push=true`), so you collect them without changing client code or configuration. Older clients don't support KIP-714 and never push.

Since Gateway handles the telemetry itself, your Kafka broker doesn't need any KIP-714 setup: no `CLIENT_METRICS` resources and no client telemetry reporter plugin. This also works against brokers that don't support KIP-714 at all.

Use this Interceptor to observe producer and consumer health from a single place, even when clients run in networks you don't control or can't instrument directly.

## How it works

Gateway tells each client which metrics to collect and how often to send them. Clients push their metrics to Gateway, which enriches each one with identity labels and forwards it to your collector. None of this reaches your Kafka broker.

The identity labels let you group and filter metrics by client and by <Tooltip tip="A logical Kafka cluster served by Gateway.">Virtual Cluster</Tooltip>:

| Label                   | Description                                          |
| ----------------------- | ---------------------------------------------------- |
| `client_id`             | The client's configured `client.id`                  |
| `client_instance_id`    | Unique per client instance, assigned through KIP-714 |
| `client_source_address` | Source IP address of the client connection           |
| `client_source_port`    | Source port of the client connection                 |
| `principal`             | Authenticated principal (user) of the client         |
| `vcluster`              | Virtual Cluster the client connected to              |

## Configure the client metrics Interceptor

| Name               | Type          | Default                | Description                                                                                                                                                                                                                    |
| :----------------- | :------------ | :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `requestedMetrics` | List\[String] | `["*"]`                | Metric-name prefixes served to clients. Use `["*"]` for all metrics, an empty list for none, or a list of literal prefixes to filter.                                                                                          |
| `pushIntervalMs`   | Integer       | `300000`               | Interval in milliseconds clients wait between pushes. Bounded to Kafka's accepted range of `100` to `3600000` (1 hour).                                                                                                        |
| `maxBytes`         | Integer       | `1048576`              | Maximum size in bytes of a client push accepted for export. Matches KIP-714's `telemetry.max.bytes`.                                                                                                                           |
| `exporterClass`    | String        | Built-in OTLP exporter | Fully-qualified name of the exporter class. Defaults to the built-in OTLP exporter, `io.conduktor.gateway.interceptor.clientmetrics.exporter.otlp.OtlpClientTelemetryExporter`. See [Choose an exporter](#choose-an-exporter). |
| `exporterConfig`   | Map           | `{}`                   | Configuration passed to the exporter selected by `exporterClass`. For the default OTLP exporter, see [OTLP exporter configuration](#otlp-exporter-configuration).                                                              |

<Note>
  Gateway serves one subscription to all clients. Per-client subscriptions aren't supported yet.
</Note>

### Choose an exporter

An exporter forwards each metric out of Gateway. It's a standard Kafka telemetry plugin — a class implementing `org.apache.kafka.server.telemetry.ClientTelemetryExporterProvider`, loaded the same way Kafka loads `metric.reporters`. Gateway ships an OTLP exporter and uses it by default.

To forward metrics somewhere else, set `exporterClass` to your own implementation of that interface and put its settings under `exporterConfig`. The settings a given exporter accepts are defined by that exporter — the ones below are specific to the default OTLP exporter.

<Note>
  Add a custom exporter to Gateway's classpath by bind-mounting its JAR into the container's `/app/lib/` directory.
</Note>

### OTLP exporter configuration

These settings apply to the default OTLP exporter. Set them under `exporterConfig`. Any value can reference a Gateway environment variable with the `${MY_ENV_VAR}` format.

| Name          | Type    | Default                          | Description                                                                                                                                  |
| :------------ | :------ | :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
| `endpoint`    | String  | `${OTEL_EXPORTER_OTLP_ENDPOINT}` | `host:port` of the OTLP gRPC collector. Required. Configuration fails if neither this nor the environment variable is set.                   |
| `insecure`    | Boolean | `false`                          | Use a plaintext (non-TLS) gRPC channel. Falls back to `OTEL_EXPORTER_OTLP_INSECURE`. A `http`/`https` scheme on `endpoint` takes precedence. |
| `compression` | Enum    | `gzip`                           | Outbound compression: `none` or `gzip`. Falls back to `OTEL_EXPORTER_OTLP_COMPRESSION`.                                                      |
| `truststore`  | Object  | JVM default                      | JKS truststore to verify the collector's TLS certificate. Ignored on a plaintext connection.                                                 |
| `keystore`    | Object  |                                  | JKS keystore providing a client certificate for mutual TLS (mTLS). Ignored on a plaintext connection.                                        |

The `truststore` and `keystore` objects take these fields:

| Object       | Fields                                 | Environment variable fallback                                                    |
| :----------- | :------------------------------------- | :------------------------------------------------------------------------------- |
| `truststore` | `trustStorePath`, `trustStorePassword` | `OTEL_EXPORTER_OTLP_TRUST_STORE_PATH`, `OTEL_EXPORTER_OTLP_TRUST_STORE_PASSWORD` |
| `keystore`   | `keyStorePath`, `keyStorePassword`     | `OTEL_EXPORTER_OTLP_KEY_STORE_PATH`, `OTEL_EXPORTER_OTLP_KEY_STORE_PASSWORD`     |

## Client metrics Interceptor example

This example collects all metrics, tells clients to push every 5 minutes, and forwards to a plaintext collector.

<Tabs>
  <Tab title="curl">
    ```bash theme={null}
    curl \
      --request PUT \
      --url 'http://localhost:8888/gateway/v2/interceptor' \
      --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
      --header 'Content-Type: application/json' \
      --data-raw '{
      "kind": "Interceptor",
      "apiVersion": "gateway/v2",
      "metadata": {
        "name": "client-metrics"
      },
      "spec": {
        "pluginClass": "io.conduktor.gateway.interceptor.clientmetrics.ClientMetricsPlugin",
        "priority": 100,
        "config": {
          "requestedMetrics": [
            "*"
          ],
          "pushIntervalMs": 300000,
          "exporterConfig": {
            "endpoint": "<YOUR_OTLP_COLLECTOR_HOST>:4317",
            "insecure": true,
            "compression": "gzip"
          }
        }
      }
    }'
    ```
  </Tab>

  <Tab title="Conduktor CLI">
    ```yaml theme={null}
    apiVersion: gateway/v2
    kind: Interceptor
    metadata:
      name: client-metrics
      scope:
        vCluster: passthrough
    spec:
      pluginClass: io.conduktor.gateway.interceptor.clientmetrics.ClientMetricsPlugin
      priority: 100
      config:
        requestedMetrics:
          - "*"
        pushIntervalMs: 300000
        exporterConfig:
          endpoint: "<YOUR_OTLP_COLLECTOR_HOST>:4317"
          insecure: true
          compression: gzip
    ```
  </Tab>
</Tabs>

To forward over TLS, drop `insecure` and set the collector endpoint to an `https` address or supply a `truststore` (and a `keystore` for mutual TLS).

## Related resources

* [Use and configure Interceptors](/guide/conduktor-concepts/interceptors)
* [View the full Interceptor list](/guide/reference/interceptor-reference)
* [KIP-714: Client metrics and observability](https://cwiki.apache.org/confluence/display/KAFKA/KIP-714%3A+Client+metrics+and+observability) <Icon icon="up-right-from-square" />
