Class KafkaAuditSink
- All Implemented Interfaces:
McpAuditSink
McpAuditSink that publishes audit records to a Kafka topic.
Select it with MCP_AUDIT_SINK=com.mcpdbwizard.pub.KafkaAuditSink.
MCP_AUDIT_KAFKA_BOOTSTRAP | Required. Bootstrap servers. |
MCP_AUDIT_KAFKA_TOPIC | Topic, default "mcp-audit". |
MCP_AUDIT_KAFKA_ON_FULL | block (default) or drop. |
MCP_AUDIT_KAFKA_BLOCK_MS | How long block waits, default
"5000". |
What this does and does not guarantee — read before relying on it
This is a reference implementation, not a durable audit pipeline. Buffering is the Kafka
producer's in-memory buffer. If the broker is unreachable for longer than that buffer and the
configured block time absorb, records are dropped — counted and reported, but gone. Nothing
here spools to disk and replays, and a disk spool is the substantial work that a genuinely durable
trail needs (see docs/mcp-audit-sink-plan.md §2.3).
The two policies express the honest trade:
block— a tool call waits up toMCP_AUDIT_KAFKA_BLOCK_MSfor buffer space, so a broker outage slows the database work. Closer to audit semantics, at the cost of coupling Oracle calls to Kafka's availability.drop— the call never waits, and the record is lost on a full buffer. Correct when the trail is valuable but not load-bearing; wrong when somebody will later rely on it being complete.
acks=all is set, so a record acknowledged by the broker is on every in-sync replica.
That covers durability after hand-off; it says nothing about records that never got there.
Copyright 2003-2026 ATB Consultancy Services Ltd
(formerly Orinda Software Ltd, Dublin, Ireland)
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()booleanflush()Confirm that everything handed toMcpAuditSink.record(com.mcpdbwizard.pub.McpAuditEvent)since the last flush is durably accepted.longHow many records have been lost.voidrecord(McpAuditEvent theEvent) Record one call.static StringThe configured topic, or "mcp-audit" when the setting is absent or blank.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface com.mcpdbwizard.pub.McpAuditSink
describe, getDeliveredCount, getPendingCount
-
Field Details
-
BOOTSTRAP_VARIABLE
- See Also:
-
TOPIC_VARIABLE
- See Also:
-
ON_FULL_VARIABLE
- See Also:
-
BLOCK_MS_VARIABLE
- See Also:
-
DEFAULT_TOPIC
- See Also:
-
DEFAULT_BLOCK_MS
- See Also:
-
-
Constructor Details
-
KafkaAuditSink
public KafkaAuditSink()Built reflectively byMcpAuditSinks.fromEnvironment().
-
-
Method Details
-
topicFrom
The configured topic, or "mcp-audit" when the setting is absent or blank.Public so a status page can show the topic records will actually go to, rather than restating this default somewhere else and drifting from it.
-
record
Record one call. Must not throw.Never throws: this runs in a
finallyon the tool-call path, and an audit failure must not replace the caller's real result.- Specified by:
recordin interfaceMcpAuditSink- Parameters:
theEvent- the call to record; never null
-
flush
public boolean flush()Confirm that everything handed toMcpAuditSink.record(com.mcpdbwizard.pub.McpAuditEvent)since the last flush is durably accepted.This is what makes a spool possible. A spool writes each record to disk first and may only delete it once the sink has genuinely taken it — and for an asynchronous sink like Kafka,
recordreturning tells you nothing, because the send has not completed yet.The default returns true, which is correct for a sink that delivers synchronously inside
record. An asynchronous sink must override it, and must return false if anything since the last flush was lost — returning true on a failed batch would let a spool delete records that never arrived, which is the one way a spool can be worse than no spool.Blocks until the producer has completed every outstanding send, then reports whether any of them failed. A spool depends on this answer being honest: saying "delivered" about a batch that did not arrive would let it delete records that were never received.
- Specified by:
flushin interfaceMcpAuditSink- Returns:
- true if everything since the last flush is safely delivered
-
getDroppedCount
public long getDroppedCount()How many records have been lost. Non-zero means the trail has holes.- Specified by:
getDroppedCountin interfaceMcpAuditSink
-
close
public void close()- Specified by:
closein interfaceMcpAuditSink
-