# Audit Logging (/operate/observability/audit)



KubeMQ records a built-in audit trail of security, control-plane, and data-plane error
events. Every audit event follows the [CloudEvents v1.0](https://cloudevents.io/)
specification, so the trail is interoperable with any CloudEvents-aware tooling, and it is
queryable through a REST API on the management API port (`:8080`).

## Overview [#overview]

Audit logging is **on by default**. Events are persisted to a local durable store on each
node and synchronized across cluster nodes over the cluster mesh, so every node holds the
full audit trail for the entire cluster. Each event is a CloudEvents v1.0 envelope carrying
a structured `data` payload that captures who did what, on which channel, over which
transport, and whether it succeeded.

Three kinds of events are recorded:

* **Control events** — security, connection lifecycle, and administrative operations
  (authentication, authorization, client connect/disconnect, subscriptions, channel
  create/delete, cluster membership, server lifecycle).
* **Data error events** — failures in message send and receive operations across the
  patterns.
* **System error events** — infrastructure-level failures such as storage or broker errors.

## Configure it [#configure-it]

Audit logging has three settings: a master `enable` toggle, the retention window in hours,
and how often expired records are purged.

<Tabs items="[&#x22;Docker&#x22;, &#x22;Helm&#x22;]">
  <Tab value="Docker">
    ```yaml title="config.yaml"
    audit:
      enable: true                  # on by default
      retentionHours: 720           # retain events for 30 days
      cleanupIntervalMinutes: 60    # purge expired events hourly
    ```
  </Tab>

  <Tab value="Helm">
    ```yaml title="values.yaml"
    spec:
      audit:
        enable: true                # on by default
        retentionHours: 720         # retain events for 30 days
        cleanupIntervalMinutes: 60  # purge expired events hourly
    ```
  </Tab>
</Tabs>

<Callout type="warn">
  **Version floor:** the `spec.audit.*` fields are present throughout the current GA chart
  line — `kubemq-crds` and `kubemq-cluster` **3.x** (latest **3.2.0**) with
  `kubemq-controller` **2.x** (operator **v2.3.0**). Anything older than the 3.0.0 / 2.0.0 GA
  release predates this reference and will reject these fields; upgrade to the current line.
  On Docker the `audit.*` keys are available regardless of chart version.
</Callout>

For the full settings table — types, defaults, valid values, and the Docker/Helm naming for
each key — see the [Observability settings reference](/configure/reference/observability).

## Event format [#event-format]

Each audit event is a CloudEvents v1.0 envelope. The envelope carries the standard
CloudEvents attributes; the audit-specific payload lives in `data`.

```json
{
  "specversion": "1.0",
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "source": "kubemq://my-cluster/node-1",
  "type": "io.kubemq.audit.auth.success",
  "time": "2026-03-26T12:34:56.789Z",
  "datacontenttype": "application/json",
  "data": {
    "category": "control",
    "subcategory": "success",
    "client_id": "my-producer",
    "source_ip": "10.0.0.5",
    "transport": "grpc",
    "channel": "orders",
    "action": "auth.success",
    "outcome": "success",
    "metadata": {
      "method": "SendEvent"
    }
  }
}
```

### Envelope fields [#envelope-fields]

| Field             | Description                                    |
| ----------------- | ---------------------------------------------- |
| `specversion`     | Always `"1.0"`.                                |
| `id`              | Unique UUID for each event.                    |
| `source`          | `kubemq://{cluster_name}/{node_id}`.           |
| `type`            | `io.kubemq.audit.{event_type}`.                |
| `time`            | ISO 8601 timestamp with millisecond precision. |
| `datacontenttype` | Always `"application/json"`.                   |

### Data fields [#data-fields]

| Field            | Type   | Description                                     |
| ---------------- | ------ | ----------------------------------------------- |
| `category`       | string | Event category: `control`, `data`, or `system`. |
| `subcategory`    | string | Sub-category (e.g. `success`, `error`).         |
| `client_id`      | string | Client identifier (if applicable).              |
| `source_ip`      | string | Client IP address (if applicable).              |
| `transport`      | string | Transport layer (`grpc`, `rest`).               |
| `channel`        | string | Channel name (if applicable).                   |
| `message_id`     | string | Message, event, or request ID (if applicable).  |
| `action`         | string | Event type name (same as the `type` suffix).    |
| `outcome`        | string | `success` or `error`.                           |
| `error`          | string | Error message (only when `outcome` is `error`). |
| `error_category` | string | Error classification (if applicable).           |
| `metadata`       | map    | Additional key-value metadata.                  |

## Event catalog [#event-catalog]

### Control events [#control-events]

Control-plane events track security, connection lifecycle, and administrative operations.
These events carry `category: "control"`.

| Event type             | Description                                        |
| ---------------------- | -------------------------------------------------- |
| `server.started`       | Server completed startup.                          |
| `server.stopped`       | Server shutting down.                              |
| `server.ready`         | Server ready to accept traffic.                    |
| `auth.success`         | Authentication succeeded.                          |
| `auth.failure`         | Authentication failed.                             |
| `authz.denied`         | Authorization denied.                              |
| `client.connected`     | Client established a connection.                   |
| `client.disconnected`  | Client disconnected.                               |
| `client.connect_error` | Client connection failed.                          |
| `subscription.created` | Subscription established.                          |
| `subscription.deleted` | Subscription removed.                              |
| `subscription.error`   | Subscription failed.                               |
| `channel.created`      | Channel created (detected by the channel monitor). |
| `channel.deleted`      | Channel deleted (detected by the channel monitor). |
| `stream.opened`        | Bidirectional stream opened.                       |
| `stream.closed`        | Bidirectional stream closed.                       |
| `cluster.node_joined`  | Cluster node joined.                               |
| `cluster.node_left`    | Cluster node left.                                 |

A channel monitor watches for channels appearing and disappearing and emits
`channel.created` / `channel.deleted` control events accordingly.

### Data error events [#data-error-events]

Data-plane error events track failures in message send and receive operations. These events
carry `category: "data"`.

| Event type                | Description                  |
| ------------------------- | ---------------------------- |
| `events.send_error`       | Event publish failed.        |
| `events_store.send_error` | Events Store publish failed. |
| `command.send_error`      | Command send failed.         |
| `query.send_error`        | Query send failed.           |
| `queue.send_error`        | Queue message send failed.   |
| `queue.batch_send_error`  | Queue batch send failed.     |
| `queue.receive_error`     | Queue receive failed.        |

### System error events [#system-error-events]

System-level errors from infrastructure components. These events carry
`category: "system"`.

| Event type             | Description                 |
| ---------------------- | --------------------------- |
| `system.storage_error` | Persistent storage failure. |
| `system.broker_error`  | Message broker error.       |

## Retention & cleanup [#retention--cleanup]

Audit events are retained for the window set by `retentionHours` (default `720` hours = 30
days). A background cleanup runs at the interval set by `cleanupIntervalMinutes` (default
`60` minutes) and deletes every event older than the retention window. Both settings accept
a minimum of `1`. Tune `retentionHours` to your compliance window and lower
`cleanupIntervalMinutes` only if you need expired events purged more aggressively.

Retention applies per node, but because the trail is synchronized over the cluster mesh,
every node holds — and prunes — the same cluster-wide set of events.

## Query the audit log (REST) [#query-the-audit-log-rest]

The audit trail is queryable through the management API port (`:8080`). Two endpoints are
available: one to list matching events and one to aggregate them.

### List events [#list-events]

```text
GET /api/v1/audit
```

| Parameter     | Type           | Default    | Description                                       |
| ------------- | -------------- | ---------- | ------------------------------------------------- |
| `from`        | RFC3339 string | 1 hour ago | Start time.                                       |
| `to`          | RFC3339 string | now        | End time.                                         |
| `category`    | string         | (all)      | Filter by category (`control`, `data`, `system`). |
| `subcategory` | string         | (all)      | Filter by subcategory.                            |
| `event_type`  | string         | (all)      | Filter by event type (e.g. `auth.success`).       |
| `channel`     | string         | (all)      | Filter by channel name.                           |
| `client_id`   | string         | (all)      | Filter by client ID.                              |
| `limit`       | int            | 50         | Results per page (1–1000).                        |
| `offset`      | int            | 0          | Pagination offset.                                |

```bash
curl "http://localhost:8080/api/v1/audit?category=control&event_type=auth.failure&limit=10"
```

### Aggregate statistics [#aggregate-statistics]

```text
GET /api/v1/audit/stats
```

| Parameter  | Type           | Default      | Description         |
| ---------- | -------------- | ------------ | ------------------- |
| `from`     | RFC3339 string | 1 hour ago   | Start time.         |
| `to`       | RFC3339 string | now          | End time.           |
| `group_by` | string         | `event_type` | Grouping dimension. |

```bash
curl "http://localhost:8080/api/v1/audit/stats?group_by=category&from=2026-03-25T00:00:00Z"
```

### Error responses [#error-responses]

| HTTP code | Error                  | Description                                     |
| --------- | ---------------------- | ----------------------------------------------- |
| 404       | `ErrAuditDisabled`     | Audit service is disabled or not initialized.   |
| 400       | `ErrAuditInvalidParam` | Invalid query parameter (e.g. bad date format). |
| 500       | `ErrAuditQueryFailed`  | Query failed.                                   |

## Access control [#access-control]

When control-plane authentication is enabled, the audit query endpoints require at least the
**ReadOnly** role, like the rest of the management API. See the
[Management API](/operate/observability/api-reference) overview for the response envelope,
status codes, and access-control model.

## Feed a SIEM [#feed-a-siem]

The REST query API makes it straightforward to feed audit events into an external SIEM. Poll
`GET /api/v1/audit` on an interval, advancing the `from` / `to` window each pass, and forward
the returned CloudEvents records into Splunk, Elastic, or any log-management platform. Because
the trail is synchronized cluster-wide, you can poll a single node and still capture every
event from the cluster.

## Related [#related]

* [Observability settings reference](/configure/reference/observability) — the audit
  configuration keys with their Docker and Helm naming, defaults, and valid values.
* [Management API](/operate/observability/api-reference) — the response envelope, status codes,
  and access-control model shared by the audit query endpoints.
