Kong / Kong/developer.konghq.com

How-to for using the Kafka Log policy

Open Beginner friendly
#6,802 0 comments 0 reactions 0 assignees View on GitHub
internal product:ai-gateway
Dominant language
Ruby
Stars
28
Forks
121
Avg merge
1d 4h
Merged PRs (30d)
313

Description

Transform these toa proper how-to:

# Testing the Kafka Log Policy example locally

This is the minimum setup needed to run the example in
`app/_ai_gateway_policies/kafka-log/index.md` against a local Kafka broker.

Requires [kafkactl](https://github.com/deviceinsight/kafkactl?tab=readme-ov-file#installation), `jq`, and the usual AI Gateway prereqs.

## Working directory and SASL credentials

```bash
mkdir -p ~/kafka-log-test && cd ~/kafka-log-test

cat <<'EOF' > kafka_server_jaas.conf
KafkaServer {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="kafka_user"
password="kafka-password"
user_kafka_user="kafka-password";
};
EOF
```

## Broker

Single-node KRaft broker with two listeners. SASL on `9092` advertised as `host.docker.internal`
for the data plane, plaintext on `9094` advertised as `localhost` for local tooling.
`host.docker.internal` doesn't resolve from the host itself, which is why both exist.

```bash
cat <<'EOF' > docker-compose.yaml
name: kafka_aigw

services:
kafka:
image: apache/kafka:4.3.1
container_name: kafka
ports:
- "9092:9092"
- "9094:9094"
environment:
KAFKA_NODE_ID: 0
KAFKA_PROCESS_ROLES: broker,controller
KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
KAFKA_CONTROLLER_QUORUM_VOTERS: 0@localhost:9093
KAFKA_LISTENERS: CONTROLLER://localhost:9093,SASL_PLAINTEXT://0.0.0.0:9092,PLAINTEXT://0.0.0.0:9094
KAFKA_ADVERTISED_LISTENERS: SASL_PLAINTEXT://host.docker.internal:9092,PLAINTEXT://localhost:9094
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_SASL_ENABLED_MECHANISMS: PLAIN
KAFKA_OPTS: -Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_CLUSTER_ID: 'abcdefghijklmnopqrstuv'
KAFKA_LOG_DIRS: /tmp/kraft-combined-logs
volumes:
- ./kafka_server_jaas.conf:/etc/kafka/kafka_server_jaas.conf
EOF

docker compose up -d
```

## Verify SASL before involving the gateway

Run this from a separate container, not from inside the `kafka` container. It exercises the same
network path the data plane uses.

```bash
cat <<'EOF' > client.properties
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="kafka_user" password="kafka-password";
EOF

docker run --rm \
-v "$PWD/client.properties:/tmp/client.properties" \
apache/kafka:4.3.1 \
/opt/kafka/bin/kafka-broker-api-versions.sh \
--bootstrap-server host.docker.internal:9092 \
--command-config /tmp/client.properties
```

You should get a list of broker API versions ending in `)`, with `SaslHandshake(17)` and
`SaslAuthenticate(36)` present and no `SaslAuthenticationException`.

## Create the log topic

```bash
cat <<'EOF' > kafkactl.yaml
contexts:
direct:
brokers:
- localhost:9094
EOF

kafkactl -C kafkactl.yaml --context direct create topic kong-log
```

## An upstream to proxy to

The AI Agent needs a real HTTP upstream:

```bash
docker run -d --name log-upstream -p 8080:80 nginx:alpine
```

Confirm it's serving before continuing:

```bash
curl -i http://localhost:8080
```

## The Policy, plus an AI Agent to generate traffic

The Policy is global, so it logs every request. The AI Agent gives you a Route to send requests
through, and `config.url` points at the nginx container so the proxied request returns a `200`.

`ssl` is set to `false` here to simplify testing.

```bash
cat <<'EOF' > kafka-log.yaml
_defaults:
kongctl:
namespace: kafka-log-test

ai_gateway_policies:
- ref: kafka-log
ai_gateway: !lookup {id: !env AI_GATEWAY_ID}
name: kafka-log
display_name: Kafka Log
type: kafka-log
enabled: true
global: true
config:
bootstrap_servers:
- host: host.docker.internal
port: 9092
topic: kong-log
authentication:
strategy: sasl
mechanism: PLAIN
user: kafka_user
password: kafka-password
security:
ssl: false

ai_gateway_agents:
- ref: kafka-log-agent
ai_gateway: !lookup {id: !env AI_GATEWAY_ID}
name: kafka-log-agent
display_name: "Kafka Log Agent"
type: http
enabled: true
config:
url: http://host.docker.internal:8080
route:
paths:
- /log-test
protocols:
- http
- https
methods:
- GET
- POST
strip_path: true
EOF

kongctl sync -f kafka-log.yaml --pat "$KONNECT_TOKEN"
```

## Generate traffic, then read the topic

Unlike Kafka Consume, this Policy produces to Kafka. Send requests first, then consume.

Allow a few seconds after `kongctl sync` for the data plane to pick up the new configuration.
Requests sent before it does return `502`.

Generate a few log entries:

```bash
curl -s -o /dev/null "$KONNECT_PROXY_URL/log-test"
curl -s -o /dev/null -X POST "$KONNECT_PROXY_URL/log-test" \
-H 'Content-Type: application/json' \
-d '{"hello":"world"}'
```

Read them back:

```bash
kafkactl -C kafkactl.yaml --context direct consume kong-log --from-beginning --exit | jq .
```

`config.producer_async` defaults to `true`, so allow a second or two before the entries appear.

The `GET` is logged with `response.status: 200`. The `POST` is logged with `405`, because nginx
rejects POST to a static file. Both are logged either way, since the Policy logs regardless of the
response status.

A trimmed entry:

```json
{
"source": "kong",
"client_ip": "192.168.97.1",
"started_at": 1787579347089,
"workspace_name": "default",
"upstream_uri": "/",
"upstream_status": "200",
"request": {
"method": "GET",
"uri": "/log-test",
"url": "http://localhost:8000/log-test",
"size": 86,
"querystring": {},
"headers": {
"host": "localhost:8000",
"user-agent": "curl/8.17.0",
"accept": "*/*"
}
},
"response": {
"status": 200,
"size": 853,
"headers": {
"content-type": "text/html",
"server": "kong/2.0.2-ai-gateway"
}
},
"latencies": {
"kong": 1,
"proxy": 4,
"request": 5
},
"route": {
"name": "kafka-log-agent-route",
"paths": ["/log-test"],
"methods": ["GET", "POST"],
"strip_path": true
},
"service": {
"name": "kafka-log-agent",
"host": "host.docker.internal",
"port": 8080,
"protocol": "http"
},
"tries": []
}
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Open app/_ai_gateway_policies/kafka-log/index.md and compare the existing example with the supplied local setup steps. Follow the setup commands through topic creation, traffic generation, and consumption to check the sequence; done means the page is a clear, complete how-to that readers can follow locally and verify from the Kafka output.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, docker
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.