Find which Bridge is draining your OpenAI quota with SaltingIO logs

Per-Bridge request and error counts in the SaltingIO Logs page tell you exactly which proxied endpoint regressed. Here's how to read them.

SaltingIO Team May 20, 2026 6 min read DevOps & CI/CD
openaiapi-monitoringobservabilitylogsrate-limitscost-managementthird-party-apisdebugging
Find which Bridge is draining your OpenAI quota with SaltingIO logs

OpenAI billing went up 40% this month and the team can't say why. Three Bridges sit between the frontend and api.openai.com: one points at the completions endpoint, one at embeddings, one at moderation. Each was created months ago, and nobody has touched them since. Which one is responsible for the spike?

This is the kind of question a generic backend logging stack handles poorly. Request volume against api.openai.com is just one big number unless you've already tagged calls with which feature triggered them. With SaltingIO, every Bridge has its own UUID, so the gateway already knows which one a request was for. The Logs page just surfaces that breakdown.

What the Logs page actually shows

Open the dashboard and click Logs in the left nav. The page splits into three views:

  • A time-series chart of total requests across the date range you set
  • A table of per-UUID aggregates with request count, error count, average latency, and last seen
  • A searchable error log with the raw response body the gateway returned to the caller

Set the date range to the last 30 days if you're chasing a billing spike, or to the last 24 hours if you're hunting a current outage. The per-UUID table is the part you care about for cost attribution. Sort it by request count descending and the noisy Bridges float to the top.

A practical pattern: open two Logs tabs side by side, one set to the previous billing period, one set to the current one. Now you're comparing distributions, not staring at a single number. The Bridge that doubled in volume between the two windows is the answer.

The table shows raw UUIDs by default. If you've named your Bridges descriptively (and you should), hover the row to see the title you gave it at creation time. A naming convention worth standardising on:

openai-chat-prod
openai-chat-staging
openai-embed-prod
openai-moderation-prod

The Bridge title is also what shows up in CSV exports, so a naming pass pays off twice.

CSV export for the spreadsheet workflow

The Logs page has a Download CSV button that exports whatever is currently filtered. Pull that into a spreadsheet and you have a pivot-table-friendly view of usage per Bridge per day. From there, charting cost-per-feature is straightforward: multiply request count by the average upstream tokens for that endpoint and you have a per-Bridge dollar estimate.

A snippet of what the CSV looks like:

timestamp,record_uuid,title,method,status,latency_ms,error
2026-05-18T09:14:02Z,abc123,openai-chat-prod,POST,200,842,
2026-05-18T09:14:03Z,abc123,openai-chat-prod,POST,200,901,
2026-05-18T09:14:05Z,def456,openai-embed-prod,POST,200,310,
2026-05-18T09:14:09Z,abc123,openai-chat-prod,POST,429,12,Rate limit exceeded

That last row is the kind of signal that explains a quota burn: a 429 followed by retries that all hit the same Bridge. Every retry shows up as a fresh row, and each one counts against your SaltingIO monthly quota too, since the gateway processed the request before the upstream rejected it.

Reproducing a hot Bridge from the command line

Once you have identified which UUID is hot, the easiest way to inspect what callers are actually sending is to hit the Bridge yourself with the same shape they use:

curl -X POST https://api.salting.io/r/abc123-uuid \
  -H "X-API-Key: $SALT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role":"user","content":"Summarize this"}]
  }'

If the response looks heavier than it needs to be, that's often where the cost lives. A common case: the frontend only renders choices[0].message.content, but the upstream payload includes full token usage, system fingerprint, and request metadata. Trim it on the gateway side with a select query parameter:

GET https://api.salting.io/r/abc123-uuid?select=choices.0.message.content

That doesn't reduce upstream cost, but it cuts bytes shipped to the browser and makes the next batch of logs easier to scan, since errors stand out against a smaller success body.

Common pitfalls

A few things bite developers the first time they go log-spelunking.

Shared Bridges across environments. If openai-chat serves both production and staging, the per-UUID counts mix them together. You cannot tell whether the spike is a real-traffic event or a CI job hammering staging. Split into two Bridges before you need to attribute, not after.

Failover hits do not get their own row. When a Bridge falls back to a secondary URL, the gateway records the call against the same UUID, but the status reflects whichever upstream actually responded. A successful failover looks identical to a primary success in the table. To see how often failover fired, watch the average latency column. A sudden jump of 200ms or more on a previously stable Bridge usually means the primary is timing out and the secondary is carrying the load.

The 429 retry trap. SaltingIO's own rate limit returns {"error":"Rate limit exceeded","message":"You have exceeded the rate limit for your plan. Please slow down.","retry_after_seconds":1}. Some HTTP clients ignore that hint and retry immediately, which doubles your request count without delivering any successful calls. If a Bridge's error rate is dominated by 429s and the call volume looks suspiciously steady, audit the retry logic on the calling side first. The fix is to honour retry_after_seconds with a real sleep, not to upgrade the plan.

Quota counts the request, not the upstream response. Every call that reaches the gateway counts against your monthly request budget, even if the upstream returns a 500. A flapping third-party API can quietly eat through a Starter or Builder plan in a day. The Logs page makes this visible: look for a Bridge where the success count is low and the total count is high. That is a budget leak.

When to act

If a single Bridge is responsible for more than half your monthly requests and you cannot explain why, it is worth either splitting it into per-feature Bridges or wrapping the calling code in a feature flag so you can throttle it independently. Either move makes the next cost investigation faster.

The Logs page is available on every plan including Starter. The searchable error log and CSV export become available on Scale Defender and above, so if a billing investigation is the reason you are reading this, that upgrade often pays back the same month it lands.

Read the docs for the full Logs reference, including the exact query parameters the date-range picker accepts.