We're in development! Things may crash or break

Examples

Error Tracking

Capture failed, blocked, and rate-limited LLM calls in FluxGate so you can diagnose and alert on them alongside your cost data.

Why track errors?

A high error rate on a specific feature often means a prompt is hitting the model's context window, a user is triggering safety filters, or you're exhausting provider rate limits. Seeing these events alongside cost data in FluxGate lets you catch regressions before they affect revenue.

Automatic tracking (provider wrappers)

When using @fluxgate/openai, @fluxgate/anthropic, or @fluxgate/gemini, errors are recorded automatically. You do not need to catch and re-record them — just let the exception propagate.

// The wrapper records status: "ERROR" before the exception surfaces
try {
  const completion = await openai
    .withContext({ feature: "code-review" })
    .chat.completions.create({ model: "gpt-4o", messages });
} catch (err) {
  // FluxGate already recorded the event.
  // Handle the error for your user here.
  return { error: "AI service temporarily unavailable." };
}

Manual error tracking (core SDK)

If you call LLM providers directly (no wrapper), use fg.recordEvent with an explicit status object:

import { fg } from "@/lib/fluxgate";

const startedAt = performance.now();

try {
  const response = await myLLMProvider.call(prompt);

  await fg.recordEvent({
    usage: {
      model: response.model,
      provider: "custom",
      inputTokens: response.inputTokens,
      outputTokens: response.outputTokens,
      latencyInMs: performance.now() - startedAt,
    },
    status: "SUCCESS",
    metadata: { feature: "my-feature", user: session.user.id },
  });

  return response.text;
} catch (err: any) {
  await fg.recordEvent({
    usage: {
      model: "unknown",
      provider: "custom",
      inputTokens: 0,
      outputTokens: 0,
      latencyInMs: performance.now() - startedAt,
    },
    status: {
      status: "ERROR",
      errorMessage: err.message ?? "Unknown error",
    },
    metadata: { feature: "my-feature", user: session.user.id },
  });

  throw err;
}

Status types and when to use each

StatusWhen to use
SUCCESSCall completed normally
ERRORNetwork error, provider API error, or unhandled exception
BLOCKEDContent was blocked by the model or a safety layer before tokens were generated
MAX_TOKENSResponse was cut off because max_tokens was reached
CONTENT_FILTERProvider-side content filter triggered
RECITATIONModel refused due to copyright recitation risk (Gemini)
MALFORMED_REQUESTYour request payload was invalid

Tracking rate limit retries

If you retry on 429 Too Many Requests, record each attempt separately so you can see the retry overhead in your latency data:

import { fg } from "@/lib/fluxgate";
import { openai } from "@/lib/openai";

async function withRetry(messages: Message[], feature: string, userId: string) {
  const maxAttempts = 3;

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await openai
        .withContext({ feature, user: userId })
        .chat.completions.create({ model: "gpt-4o", messages });
    } catch (err: any) {
      const isRateLimit = err?.status === 429;

      if (!isRateLimit || attempt === maxAttempts) throw err;

      // Record the rate-limited attempt so it's visible in FluxGate
      await fg.recordEvent({
        usage: { inputTokens: 0, outputTokens: 0 },
        status: { status: "ERROR", errorMessage: "429 rate limit — retrying" },
        metadata: { feature, user: userId },
      });

      // Exponential back-off: 1 s, 2 s, 4 s
      await new Promise((r) => setTimeout(r, 1000 * 2 ** (attempt - 1)));
    }
  }
}

Content filter tracking (Gemini safety)

Gemini returns a SAFETY finish reason when a response is blocked. The @fluxgate/gemini wrapper maps this to status: "BLOCKED" automatically.

const result = await geminiPro
  .withContext({ feature: "user-content-gen", user: session.user.id })
  .generateContent(userPrompt);

const tracking = result.fluxGateCostTrackingResponse;

if (tracking.status === "BLOCKED") {
  // The event is already recorded in FluxGate with status "BLOCKED"
  return { error: "Your request was blocked by content safety filters." };
}

return result.response.text();

Setting up an alert for error spikes

Once errors are flowing into FluxGate, create an alert so you're notified when the error rate climbs:

  1. Open Alerts → Create Alert on the dashboard.
  2. Set Metric to requestCount (filter by status = ERROR).
  3. Set Threshold to a count that indicates an anomaly (e.g. > 50 in a 1-hour window).
  4. Add your preferred notification channel (email, Slack, Telegram).