Einführung
Wenn eine KI-Anfrage fehlschlägt, sieht der Aufrufer nur die endgültige HTTP-Antwort. Diese Antwort zeigt, dass etwas schiefgelaufen ist. Sie zeigt jedoch nicht immer, ob die Anfrage fehlerhaft formatiert, vom Gateway abgelehnt oder vom Upstream-Modellanbieter zurückgewiesen wurde. Beobachtbarkeit bedeutet, genügend Informationen zu sammeln, um eine Anfrage auch nach ihrem Verlassen des Aufrufers zu verfolgen und zu erklären, welche Grenze sie verarbeitet hat.
AI Gateway erstellt für jede Anfrage, die das Gateway erreicht, einen Protokolleintrag. Ein Protokoll kann den Anbieter, das Modell, den HTTP-Status, die Dauer und die Token-Nutzung anzeigen. Sie können außerdem einige benutzerdefinierte Metadaten anhängen: kleine Kennzeichnungen, mit denen Sie eine Anfrage später leichter finden. Metadaten sind kein vertraulicher Tresor. In diesem Lab verwenden Sie nur eine zufällige Trace-ID, einen synthetischen Fallnamen und ein Boolean-Flag – niemals ein Anmeldedaten, einen Prompt, eine E-Mail-Adresse oder eine Konto-ID.
Sie erstellen ein temporäres authentifiziertes Gateway und senden anschließend eine absichtlich fehlerhafte Workers-AI-Anfrage mit einer sicheren Trace-Kennung. Sie suchen das fehlgeschlagene Protokoll, vergleichen Fehler bei der Gateway- und der Upstream-Authentifizierung, korrigieren die Eingabe und bestätigen, dass dieselbe Trace-ID nun eine erfolgreiche Anfrage enthält. So basiert die Fehlerbehebung auf Belegen statt auf Vermutungen.
Wenn Sie direkt in diesen Kurs eingestiegen sind, absolvieren Sie zuerst LabEx mit Ihrem Cloudflare-Konto verbinden. Dort lernen Sie das LabEx-VM-Terminal, die Geräteautorisierung von Wrangler, die Bestätigung des Lernkontos und die explizite Angabe von Konto-IDs kennen. Bearbeiten Sie außerdem zuerst Routeninferenz über ein Gateway, da dieses Lab auf dessen zwei separaten Autorisierungs-Headern aufbaut.
Das Lab verwendet das von Cloudflare gehostete Modell @cf/meta/llama-3.3-70b-instruct-fp8-fast mit der Standardabrechnung von Workers AI. Workers Paid, Unified Billing und ein externes Anbieter-Konto sind nicht erforderlich. Die Anfragen sind klein und synthetisch. Brechen Sie ab, statt wiederholt neue Versuche zu starten, wenn das gemeinsam genutzte tägliche Workers-AI-Kontingent nicht verfügbar ist.
Das Setup installiert Node.js 22.22.0 und Wrangler 4.132.0 lokal im Projekt unter /home/labex/project/ai-gateway-trace. Es bereitet unabhängige Prüfungen mit Leseberechtigung vor, autorisiert Wrangler jedoch nicht, erstellt keine Cloud-Ressourcen und sendet keinen Modellverkehr. LabEx zerstört die temporäre VM am Ende des Labs. Sie müssen das Gateway und das Token trotzdem vor dem Abmelden löschen, da die Zerstörung der VM Cloud-Ressourcen nicht entfernt.
Die VM autorisieren und eine sichere Trace-ID erstellen
In diesem Schritt verbinden Sie die neue VM mit Ihrem Lernkonto und erstellen Namen für ein temporäres Gateway und einen synthetischen Trace.
Eine Trace-ID ist eine Kennzeichnung, die zugehörige Beobachtungen verbindet. Sie sollte eine Anfrage identifizieren, ohne offenzulegen, was der Benutzer gesagt hat oder um wen es sich handelt. Dieses Lab erzeugt einen zufälligen Wert und speichert ihn zusammen mit den Ressourcennamen, nicht zusammen mit Zugangsdaten.
Wechseln Sie in das vorbereitete Projekt, prüfen Sie die festgelegte CLI-Version und autorisieren Sie diese VM:
cd /home/labex/project/ai-gateway-trace
npx wrangler --version
npx wrangler login --device --browser=false --scopes account:read user:read ai:write
Öffnen Sie den angezeigten Link, geben Sie den Code ein und autorisieren Sie das vorgesehene Lernkonto. Prüfen Sie anschließend die strukturierte Identität:
npx wrangler whoami --json
Erwartet werden Wrangler 4.132.0 und loggedIn: true. Ersetzen Sie YOUR_ACCOUNT_ID unten durch die tatsächliche 32-stellige ID, die für das vorgesehene Konto angezeigt wird:
GATEWAY_ID="labex-c09-g02-$(openssl rand -hex 6)"
TOKEN_NAME="$GATEWAY_ID-token"
TRACE_ID="trace-$(openssl rand -hex 8)"
cat > .labex/state.json <<JSON
{
"accountId": "YOUR_ACCOUNT_ID",
"gatewayId": "$GATEWAY_ID",
"tokenName": "$TOKEN_NAME",
"traceId": "$TRACE_ID"
}
JSON
cat .labex/state.json
Die Trace-ID enthält sichere synthetische Daten. Die Konto-ID und die Ressourcennamen bleiben in der lokalen Statusdatei gespeichert, damit die spätere Bereinigung nur die Ressourcen dieses Labs betrifft.
Ein beobachtbares, authentifiziertes Gateway erstellen
In diesem Schritt erstellen Sie ein Gateway, das Anfragen protokolliert, nachdem diese die Authentifizierungsgrenze für Aufrufer passiert haben.
Öffnen Sie das Cloudflare Dashboard und wählen Sie AI → AI Gateway → Create gateway → Custom gateway. Verwenden Sie die gespeicherte gatewayId als Gateway-Namen. Lassen Sie die Protokollierung von Anfragen und die Gateway-Authentifizierung aktiviert. Lassen Sie Cache, Rate Limits, Ausgabenlimits und Wiederholungen deaktiviert. Die Workers-AI-Abrechnung muss auf Standard eingestellt bleiben.
Bestätigen Sie nach der Erstellung die eindeutige Gateway-ID in der Breadcrumb-Navigation und öffnen Sie Settings. Die Protokollierung liefert die in diesem Lab verwendeten Belege. Die Authentifizierung stellt sicher, dass ein unbekannter Aufrufer keine Protokollmenge erzeugen oder Modellnutzung verbrauchen kann.
Wählen Sie Create an AI Gateway authentication token. Verwenden Sie den gespeicherten tokenName, beziehen Sie nur das vorgesehene Lernkonto ein und legen Sie genau diese Berechtigungen fest:
- AI Gateway — Run, um das authentifizierte Gateway aufzurufen;
- AI Gateway — Edit, um Protokolle zu lesen und dieses temporäre Gateway zu löschen.
Fügen Sie keine Workers-AI-Berechtigung hinzu. Wrangler stellt die separate, kurzlebige Upstream-Zugangsdaten bereit. Erstellen Sie das Token, nachdem Sie Konto und Berechtigungen geprüft haben. Speichern Sie den einmalig angezeigten Wert, ohne ihn auszugeben:
bash -c '
while :; do
read -rsp "Paste the AI Gateway token: " GATEWAY_TOKEN
printf "\n"
[ -n "$GATEWAY_TOKEN" ] && break
printf "Token cannot be empty; paste it again.\n" >&2
done
umask 077
printf "%s" "$GATEWAY_TOKEN" > .labex/gateway-token
unset GATEWAY_TOKEN
chmod 600 .labex/gateway-token
'
Prüfen Sie die exakte Ressource über die authentifizierte Verwaltungs-API:
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
| node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s),g=b.result||{};console.log(JSON.stringify({success:b.success,id:g.id,collect_logs:g.collect_logs,authentication:g.authentication},null,2))})'
unset GATEWAY_TOKEN
Erwartet werden die gespeicherte ID sowie collect_logs: true und authentication: true.
Eine markierte Anfrage mit ungültiger Eingabe senden
In diesem Schritt erzeugen Sie kontrolliert einen Eingabefehler. Gateway und Upstream-Zugangsdaten bleiben gültig. Nur die Modelleingabe ist fehlerhaft.
Benutzerdefinierte Metadaten akzeptieren höchstens fünf einfache Werte vom Typ String, Zahl oder Boolean. Schlüssel, die mit cf. beginnen, sind für Cloudflare reserviert. Diese Anfrage verwendet drei sichere Werte: die zufällige Trace-ID, den Fallnamen bad-input und synthetic: true.
Das ausgewählte Modell benötigt einen Prompt. Lassen Sie ihn absichtlich weg und speichern Sie gleichzeitig die Antwort und den HTTP-Status:
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
TRACE_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).traceId')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
METADATA=$(node -e 'process.stdout.write(JSON.stringify({trace_id:process.argv[1],case:"bad-input",synthetic:true}))' "$TRACE_ID")
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(npx wrangler auth token --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).token))')
STATUS=$(curl --http1.1 -sS -D .labex/bad-input-headers.txt \
-o .labex/bad-input-response.json -w '%{http_code}' \
-H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
-H "Authorization: Bearer $UPSTREAM_TOKEN" \
-H "cf-aig-metadata: $METADATA" \
-H 'Content-Type: application/json' \
--data '{"max_tokens":16}' \
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/bad-input-status.txt
Erwartet wird HTTP 400 oder 422. Dies ist ein Fehler in der Client-Eingabe und kein Beleg für ein Autorisierungsproblem. Der Antworttext wird für eine begrenzte Fehleranalyse gespeichert, aber nicht automatisch ausgegeben.
Den Fehler mit dem Gateway-Protokoll verknüpfen
In diesem Schritt verwenden Sie die Trace-ID, um den Anfrageeintrag zu finden, statt ausschließlich nach der Zeit zu suchen.
Es kann kurze Zeit dauern, bis Protokolle angezeigt werden. Lesen Sie den vorhandenen Protokollbestand über die Verwaltungs-API, analysieren Sie jedes flache Metadatenobjekt und geben Sie nur die Felder aus, die zur Erklärung des Fehlers erforderlich sind:
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
TRACE_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).traceId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID/logs?per_page=50" \
> .labex/logs-after-input.json
unset GATEWAY_TOKEN
node - <<'NODE'
const body = require('./.labex/logs-after-input.json')
const trace = require('./.labex/state.json').traceId
const meta = row => {
try { return typeof row.metadata === 'string' ? JSON.parse(row.metadata) : (row.metadata || {}) }
catch { return {} }
}
const matches = (body.result || []).filter(row => meta(row).trace_id === trace && meta(row).case === 'bad-input')
console.log(matches.map(row => ({
id: row.id,
provider: row.provider,
model: row.model,
success: row.success,
status_code: row.status_code,
duration: row.duration,
tokens_in: row.tokens_in,
tokens_out: row.tokens_out,
metadata: meta(row)
})))
if (!matches.some(row => row.success === false)) process.exit(2)
NODE
Erwartet werden die gespeicherte Trace-ID, case: "bad-input", der Workers-AI-Anbieter und ein fehlgeschlagener Status. Token-Zähler können leer sein, weil eine ungültige Eingabe bereits vor Beginn der Generierung fehlschlagen kann. Wenn der Eintrag noch nicht sichtbar ist, warten Sie etwa 20 Sekunden und führen Sie denselben schreibgeschützten Block erneut aus.
Öffnen Sie im Dashboard die Ansicht Logs des Gateways. Verwenden Sie den Metadatenfilter oder den sichtbaren Zeitstempel, um die fehlgeschlagene Zeile zu finden, und öffnen Sie anschließend deren Detailbereich. Bestätigen Sie, dass Modell, Fehlerstatus und benutzerdefinierte Metadaten dieselbe synthetische Anfrage beschreiben.


Fehler bei Gateway- und Upstream-Autorisierung unterscheiden
In diesem Schritt ändern Sie jeweils nur eine Zugangsinformation. Beide Tests können 401 oder 403 zurückgeben. Der Status allein reicht daher nicht aus; der Ort des Protokolleintrags liefert den fehlenden Kontext.
Lassen Sie zuerst die Upstream-Zugangsdaten gültig und verwenden Sie ungültige Gateway-Zugangsdaten. Ein authentifiziertes Gateway weist diese Anfrage zurück, bevor sie möglicherweise das Gateway betritt und ein markiertes Anbieterprotokoll erzeugt:
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
TRACE_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).traceId')
MODEL='@cf/meta/llama-3.3-70b-instruct-fp8-fast'
METADATA=$(node -e 'process.stdout.write(JSON.stringify({trace_id:process.argv[1],case:"bad-gateway-auth",synthetic:true}))' "$TRACE_ID")
UPSTREAM_TOKEN=$(npx wrangler auth token --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).token))')
STATUS=$(curl --http1.1 -sS -o .labex/bad-gateway-auth-response.json -w '%{http_code}' \
-H 'cf-aig-authorization: Bearer deliberately-invalid-gateway' \
-H "Authorization: Bearer $UPSTREAM_TOKEN" \
-H "cf-aig-metadata: $METADATA" \
-H 'Content-Type: application/json' \
--data '{"prompt":"This request must not reach Workers AI.","max_tokens":8}' \
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/bad-gateway-auth-status.txt
Lassen Sie nun die Gateway-Zugangsdaten gültig und ersetzen Sie nur die Workers-AI-Upstream-Zugangsdaten. Diese Anfrage erreicht das Gateway und kann einen fehlgeschlagenen Anbieterprotokolleintrag hinterlassen:
METADATA=$(node -e 'process.stdout.write(JSON.stringify({trace_id:process.argv[1],case:"bad-upstream-auth",synthetic:true}))' "$TRACE_ID")
GATEWAY_TOKEN=$(cat .labex/gateway-token)
STATUS=$(curl --http1.1 -sS -o .labex/bad-upstream-auth-response.json -w '%{http_code}' \
-H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
-H 'Authorization: Bearer deliberately-invalid-upstream' \
-H "cf-aig-metadata: $METADATA" \
-H 'Content-Type: application/json' \
--data '{"prompt":"This request should reach the upstream authorization check.","max_tokens":8}' \
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/bad-upstream-auth-status.txt
Erwartet werden in beiden Fällen 401 oder 403. Warten Sie kurz. Lesen Sie anschließend die Protokolle – erzeugen Sie sie nicht erneut – und vergleichen Sie die beiden Kennzeichnungen:
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID/logs?per_page=50" \
> .labex/logs-after-auth.json
unset GATEWAY_TOKEN
node - <<'NODE'
const rows = require('./.labex/logs-after-auth.json').result || []
const trace = require('./.labex/state.json').traceId
const meta = row => { try { return typeof row.metadata === 'string' ? JSON.parse(row.metadata) : (row.metadata || {}) } catch { return {} } }
for (const name of ['bad-gateway-auth', 'bad-upstream-auth']) {
const found = rows.filter(row => meta(row).trace_id === trace && meta(row).case === name)
console.log(name, found.map(row => ({status_code: row.status_code, success: row.success, provider: row.provider})))
}
NODE
Für die Kennzeichnung der Gateway-Authentifizierung sollte kein Anbieterprotokoll vorhanden sein. Für die Kennzeichnung der Upstream-Authentifizierung sollte eine fehlgeschlagene Workers-AI-Zeile angezeigt werden. Deshalb sind ein Grenzdiagramm und korrelierte Protokolle aussagekräftiger als ein HTTP-Status allein.

Die Anfrage korrigieren und den Erfolg bestätigen
In diesem Schritt stellen Sie beide gültigen Zugangsdaten wieder her und geben den erforderlichen Prompt an. Die Reparatur ist erst abgeschlossen, wenn Laufzeitausgabe und Beobachtbarkeit übereinstimmen.
Verwenden Sie dieselbe Trace-ID mit dem neuen Fallnamen repaired:
METADATA=$(node -e 'process.stdout.write(JSON.stringify({trace_id:process.argv[1],case:"repaired",synthetic:true}))' "$TRACE_ID")
GATEWAY_TOKEN=$(cat .labex/gateway-token)
UPSTREAM_TOKEN=$(npx wrangler auth token --json | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).token))')
STATUS=$(curl --http1.1 -sS -o .labex/repaired-response.json -w '%{http_code}' \
-H "cf-aig-authorization: Bearer $GATEWAY_TOKEN" \
-H "Authorization: Bearer $UPSTREAM_TOKEN" \
-H "cf-aig-metadata: $METADATA" \
-H 'Content-Type: application/json' \
--data '{"prompt":"In one short sentence, explain why trace IDs help debugging.","max_tokens":48}' \
"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/workers-ai/$MODEL")
unset GATEWAY_TOKEN UPSTREAM_TOKEN METADATA
printf '%s\n' "$STATUS" | tee .labex/repaired-status.txt
node -e 'const b=require("./.labex/repaired-response.json"); console.log(b.result?.response ?? b.result)'
Erwartet werden HTTP 200 und ein nichtleerer generierter Text. Warten Sie bei Bedarf auf das Protokoll und führen Sie anschließend die schreibgeschützte Protokollabfrage aus dem vorherigen Schritt erneut aus. Filtern Sie im Dashboard nach der Trace-ID und vergleichen Sie bad-input, bad-upstream-auth und repaired. Die reparierte Zeile sollte Erfolg, den Status 200 und eine Token-Nutzung anzeigen.

Das temporäre Gateway löschen
In diesem Schritt entfernen Sie die Cloud-Ressource, während die Verwaltungszugangsdaten ihre Abwesenheit noch bestätigen können.
ACCOUNT_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).accountId')
GATEWAY_ID=$(node -p 'JSON.parse(require("fs").readFileSync(".labex/state.json")).gatewayId')
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS -X DELETE \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways/$GATEWAY_ID" \
| node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const b=JSON.parse(s);if(!b.success)process.exit(1);console.log("gateway deletion accepted")})'
unset GATEWAY_TOKEN
GATEWAY_TOKEN=$(cat .labex/gateway-token)
curl --http1.1 -fsS \
-H "Authorization: Bearer $GATEWAY_TOKEN" \
"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/ai-gateway/gateways" \
> .labex/gateways-after-delete.json
unset GATEWAY_TOKEN
node -e 'const b=require("./.labex/gateways-after-delete.json"),id=process.argv[1],found=(b.result||[]).some(g=>g.id===id);console.log("gateway absent:",!found);if(found)process.exit(1)' "$GATEWAY_ID"
Erwartet wird gateway absent: true. Dieser authentifizierte Bestand unterscheidet eine tatsächliche Löschung von einer fehlenden Seite, die durch eine Abmeldung oder einen Netzwerkfehler verursacht wurde.
Das Token löschen und sich abmelden
In diesem Schritt widerrufen Sie die verbleibenden Cloud-Zugangsdaten und trennen die VM.
Öffnen Sie im Cloudflare Dashboard My Profile → API Tokens. Suchen Sie den exakt gespeicherten tokenName, öffnen Sie Actions, wählen Sie Delete, prüfen Sie die Bestätigung und löschen Sie nur dieses Token. Der Widerruf ist jetzt sicher, weil die Löschung des Gateways bereits bestätigt wurde.
Löschen Sie die Kopie auf der VM und beenden Sie die separate Autorisierung von Wrangler:
shred -u .labex/gateway-token
npx wrangler logout
npx wrangler whoami --json || true
test ! -e .labex/gateway-token && echo "local gateway token removed"
Erwartet werden loggedIn: false und local gateway token removed. Die Dashboard-Sitzung ist davon unabhängig und bleibt angemeldet. Nach dem Ende des Labs zerstört LabEx diese temporäre VM, anstatt sie zu speichern.
Zusammenfassung
Sie haben sichere benutzerdefinierte Metadaten verwendet, um eine fehlerhaft formatierte Workers-AI-Anfrage mit ihrem AI-Gateway-Protokoll zu verknüpfen. Sie haben gelernt, dass ein HTTP-Status den Kontext der betroffenen Grenze benötigt: Eine ungültige Gateway-Authentifizierung wird vor einem Anbieterprotokoll zurückgewiesen, während eine ungültige Upstream-Autorisierung als fehlgeschlagener Workers-AI-Eintrag erscheint. Anschließend haben Sie die Eingabe korrigiert, generierten Text und ein erfolgreiches korreliertes Protokoll bestätigt und alle temporären Zugangsdaten und Ressourcen entfernt.
Im nächsten Lab wenden Sie denselben evidenzbasierten Ansatz auf das Caching an. Sie wiederholen eine begrenzte öffentliche Anfrage, unterscheiden einen Cache-Treffer von einem neuen Modellaufruf und umgehen den Cache, wenn eine frische Ausgabe erforderlich ist.



