Commit Graph

4 Commits

Author SHA1 Message Date
Stéphane Tailland 05cf2bcce1 Turn on Kong's own AI telemetry instead of improvising it
Four settings, all of them off, which is why the AI gateway produced
HTTP-level telemetry and nothing about the model.

  logging.log_payloads     the prompt and the completion, in the log
                           records and — since OTel instrumentation is on
                           here — in the spans too
  logging.log_statistics   model usage and token counts
  prometheus.ai_metrics    kong_ai_llm_* : requests, tokens by type, cost,
                           provider latency, per model and per consumer
  input_cost / output_cost cost per 1M tokens, which is what makes
                           kong_ai_llm_cost_total mean anything

Also removes this morning's pre-function/post-function body capture from
this gateway. It was the wrong tool for the LLM route: Kong's own
implementation reassembles a streamed SSE answer, while accumulating raw
chunks in kong.ctx.shared does not. The five business domains keep theirs
— their MCP traffic is not streamed the same way.

The costs are a snapshot, checked against OpenRouter's price list for
google/gemini-3.7-flash on 2026-08-27: $0.375 in, $1.875 out per 1M
tokens. They are substitution variables rather than literals precisely
because a stale figure produces confidently wrong money rather than an
error.

Note what this does NOT fix: usage is missing on streamed responses
because the OpenAI-compatible API only reports it when the caller asks
for stream_options.include_usage, and that is LibreChat's request to
make, not Kong's. Expect token counts to stay partial until then.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 14:12:32 +02:00
Stéphane Tailland 11edfa8ed1 Capture request and response bodies on the AI gateway
The audit trail recorded metadata only for this gateway, so the prompts
sent to the LLM and the completions coming back — the one thing worth
auditing on an AI gateway — were never written down. The five business
domains have captured bodies since they were built; this gateway declares
its own copy of the observability plugins and never got them.

Adds the same pre-function/post-function pair the domains use, bound to
the proxy service, and the custom_fields_by_lua that reads them back in
the log phase. If the capture plugins are ever removed the fields go nil
and are silently omitted, so the log degrades to metadata rather than
breaking.

The response accumulator earns its keep here more than elsewhere: LLM
answers stream as SSE, so body_filter runs once per chunk and the
complete answer only exists after the last one.

Still dev-only, for the same reason as the rest of this file: it puts
prompt and completion content in the log stream.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 12:48:00 +02:00
Stéphane Tailland 9893221da0 Propagate trace context on the AI gateway
This gateway declared its own copy of the shared observability plugins,
claiming parity with k8s-platform's dataplane-globalpolicy-template. The
propagation block was later added to that template and never mirrored
here, so while the five business domains continued the caller's trace,
this one minted a fresh trace id on every request and injected nothing
upstream.

That breaks end-to-end tracing at the worst possible hop: LibreChat
enters here, so a transaction that fans out to MCP, the LLM and the
backend was recorded as a set of unrelated traces. Verified live before
the fix — the domain gateways reported
extract: [w3c, b3, jaeger] / inject: [w3c], this one reported
extract: null / inject: null.

Copy the block across and flag in the header comment that the parity is
manual and has already drifted once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 06:48:31 +02:00
Stéphane Tailland 502012a5b2 Add metrics, traces and audit logs to the AI gateway
This gateway had none of the three: no prometheus, opentelemetry or http-log
plugin, so it produced only Kong's own node and shared-dict metrics and was
invisible in Tempo and Loki.

The five business domains inherit these from k8s-platform's
dataplane-globalpolicy-template, but that template also carries
openid-connect, rate-limiting and cors, and this gateway already defines its
own AI-specific versions of all three. Applying it here would duplicate them,
so the observability plugins are declared locally with the same configuration
as the shared template.

prometheus and opentelemetry bind control-plane-wide since they describe the
gateway itself; the audit log binds to the proxy service, matching how the
domains bind theirs.

The trace endpoint now comes from the shared dataplane-template-defaults
ConfigMap rather than being repeated here, so a change of trace backend does
not need a second edit. Its only key overlapping the inline block is
OIDC_ISSUER, and both carry the same value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 07:48:11 +02:00