Desk workspace with laptop computer books and phone for software development work
Workspace setup for building AI cost tracking tools — Image: Fæ via Wikimedia Commons (CC0)

Every developer I know who started plugging AI APIs into their projects hit the same moment: that first monthly bill arrives, and you realize you have no idea which endpoint ate your budget. Was it the embedding calls? The RAG queries? The 10,000 test requests you fired during development and forgot to turn off?

Desk workspace with laptop computer books and phone for software development work
Workspace setup for building AI cost tracking tools

Here’s the thing — you don’t need a fancy commercial tool to get a handle on this. A simple cost tracker that logs every call, tags it by project and endpoint, and surfaces a weekly breakdown takes about 30 minutes to build and saves you from that “wait, why is this $400?” moment at the end of the month.

I’ve been running a version of this for my own projects for the past few months, and it’s caught more than one runaway test loop before it turned into a real charge. Here’s how to build one yourself.

Why This Matters Now

The AI infrastructure market is growing fast — funding rounds like HiddenLayer’s $100M raise signal how much enterprises are investing in securing and managing their AI deployments — and the broader AI security gold rush has pushed the market to $2.8 billion. But you don’t need enterprise-scale tooling to start tracking your own usage. The same principle applies at any scale: if you’re not measuring it, you’re not managing it.

This tutorial walks you through building a lightweight cost tracker using Python and a simple SQLite database. It logs every API call you make, calculates the cost based on the provider’s pricing, and gives you a clear breakdown by project, model, and endpoint. You can run it locally, extend it to multiple providers, and adapt it to whatever your stack looks like.

The code samples below work with OpenAI’s API as the primary example, but the pattern is the same for Anthropic, Google, or any provider with a per-token pricing model.

What You’ll Build

By the end of this tutorial, you’ll have:

  • A SQLite database that records every AI API call with timestamp, provider, model, prompt tokens, completion tokens, and computed cost
  • A Python wrapper that you drop into existing projects with a single import and two lines of code
  • A weekly cost summary command that tells you exactly where your budget went
  • A simple CSV export for deeper analysis in a spreadsheet

Step 1: Set Up the Database Schema

Start with a single SQLite file. No server to run, no configuration to manage — SQLite’s official documentation covers the full API — it’s a local file that travels with your project.

import sqlite3
from datetime import datetime

def init_database(db_path="ai_cost_tracker.db"):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS calls (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            timestamp TEXT NOT NULL,
            provider TEXT NOT NULL,
            model TEXT NOT NULL,
            endpoint TEXT NOT NULL,
            project TEXT DEFAULT 'default',
            prompt_tokens INTEGER DEFAULT 0,
            completion_tokens INTEGER DEFAULT 0,
            total_tokens INTEGER DEFAULT 0,
            cost_usd REAL DEFAULT 0.0,
            request_body_preview TEXT
        )
    """)
    conn.commit()
    conn.close()

That’s it for the schema. One table, flat and simple. The project field is the key organizational hook — tag each call with a project name so you can filter later. The request_body_preview field stores a truncated version of the request payload for debugging, truncated to keep the database small.

Step 2: Build the Cost Calculation Logic

Cost calculation is where this gets useful. Different providers price differently — OpenAI charges per million tokens for prompts and completions separately, Anthropic has its own tiers, and Google’s Gemini pricing varies by model. Here’s a starter dictionary for OpenAI’s current pricing as of late 2026:

# OpenAI pricing per 1M tokens (approximate, check OpenAI's official pricing page for the latest)
OPENAI_PRICING = {
    "gpt-4o": {"input": 5.00, "output": 15.00},
    "gpt-4o-mini": {"input": 0.15, "output": 0.60},
    "gpt-4-turbo": {"input": 10.00, "output": 30.00},
    "gpt-3.5-turbo": {"input": 0.50, "output": 1.50},
}

def calculate_cost(provider, model, prompt_tokens, completion_tokens):
    if provider == "openai" and model in OPENAI_PRICING:
        pricing = OPENAI_PRICING[model]
        input_cost = (prompt_tokens / 1_000_000) * pricing["input"]
        output_cost = (completion_tokens / 1_000_000) * pricing["output"]
        return round(input_cost + output_cost, 6)
    return 0.0

The key thing here: keep your pricing table in one place and update it when your provider changes prices. This is the single source of truth your tracker relies on, and it’s the one thing that’ll drift over time if you forget to maintain it.

Check your provider’s pricing page regularly — OpenAI updated GPT-4o pricing twice in 2026 alone — and as I covered in Google’s Gemini 3.8 Flash pricing trap, model pricing changes are happening fast across every provider, and those changes compound quickly if you’re running high-volume RAG pipelines.

Step 3: Create the Logging Wrapper

This is the part you’ll actually use in your projects. The wrapper intercepts a call, logs it, and returns the result unchanged — so it’s transparent to the rest of your code.

import json
import sqlite3
from datetime import datetime

def log_call(db_path, provider, model, endpoint, project,
             prompt_tokens, completion_tokens, request_body=None):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    total_tokens = prompt_tokens + completion_tokens
    cost = calculate_cost(provider, model, prompt_tokens, completion_tokens)
    preview = None
    if request_body:
        preview = json.dumps(request_body)[:200]
    cursor.execute("""
        INSERT INTO calls (timestamp, provider, model, endpoint, project,
                          prompt_tokens, completion_tokens, total_tokens, cost_usd, request_body_preview)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    """, (datetime.utcnow().isoformat(), provider, model, endpoint, project,
          prompt_tokens, completion_tokens, total_tokens, cost, preview))
    conn.commit()
    conn.close()
    return cost

To use it in an OpenAI-based project, wrap your call like this:

import openai
from your_tracker import log_call

DB_PATH = "ai_cost_tracker.db"
PROJECT = "my-rag-app"

response = openai.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Explain quantum computing in simple terms"}],
    max_tokens=500
)

# Extract token usage from the response
usage = response.usage
log_call(
    db_path=DB_PATH,
    provider="openai",
    model="gpt-4o",
    endpoint="chat.completions",
    project=PROJECT,
    prompt_tokens=usage.prompt_tokens,
    completion_tokens=usage.completion_tokens,
    request_body={"model": "gpt-4o", "max_tokens": 500}
)

That’s two lines added to each call site. The wrapper doesn’t change how your code works — it just records what happened. For projects with many call sites, you can wrap the entire client with a session-level hook, but for most projects the per-call approach is clearer and easier to debug.

Step 4: Query Your Weekly Breakdown

Now for the part that actually pays off — pulling a report that tells you what you spent. Here’s a query that gives you a per-project, per-model breakdown for the last 7 days:

import sqlite3

def weekly_summary(db_path, days=7):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute(f"""
        SELECT project, model, endpoint,
               SUM(prompt_tokens) as prompt_tokens,
               SUM(completion_tokens) as completion_tokens,
               SUM(total_tokens) as total_tokens,
               SUM(cost_usd) as cost_usd,
               COUNT(*) as call_count
        FROM calls
        WHERE timestamp >= datetime('now', '-{days} days')
        GROUP BY project, model, endpoint
        ORDER BY cost_usd DESC
    """)
    rows = cursor.fetchall()
    conn.close()
    
    total_cost = 0.0
    print(f"=== AI Cost Summary (Last {days} Days) ===")
    print(f"{'Project':<20} {'Model':<15} {'Calls':>6} {'Tokens':>10} {'Cost':>10}")
    print("-" * 65)
    for row in rows:
        project, model, endpoint, prompt, completion, total, cost, count = row
        print(f"{project:<20} {model:<15} {count:>6} {total:>10} ${cost:>8.4f}")
        total_cost += cost
    print("-" * 65)
    print(f"{'TOTAL':<20} {'':<15} {'':>6} {'':>10} ${total_cost:>8.4f}")
    return rows

Running this weekly — or setting it as a cron job that emails you the summary every Monday morning — gives you a regular checkpoint. You’ll spot the project that’s quietly eating tokens, the model you switched to that costs 10x more, and the test loops that never got cleaned up.

Step 5: Export to CSV for Deeper Analysis

Sometimes you need more than a summary — you need the raw data to slice and dice in a spreadsheet. This export gives you everything in a format you can open in Excel, Google Sheets, or import into a dashboard tool:

import csv

def export_csv(db_path, output_path="ai_cost_export.csv"):
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM calls ORDER BY timestamp DESC")
    rows = cursor.fetchall()
    conn.close()
    
    with open(output_path, "w", newline="") as f:
        writer = csv.writer(f)
        writer.writerow(["id", "timestamp", "provider", "model", "endpoint",
                         "project", "prompt_tokens", "completion_tokens",
                         "total_tokens", "cost_usd", "request_body_preview"])
        writer.writerows(rows)
    print(f"Exported {len(rows)} records to {output_path}")

I use this before major project milestones — exporting the full quarter’s data, opening it in a spreadsheet, and filtering by project to see which features drove the most cost. It’s a quick way to answer questions like “did switching to GPT-4o-mini actually save us money?” with real data instead of guesses.

Step 6: Extend to Multiple Providers

The pattern generalizes cleanly. Add a pricing dictionary for each provider, extend the calculate_cost function with a provider switch, and tag each call with the provider name. Here’s what the extended version looks like:

PRICING = {
    "openai": {
        "gpt-4o": {"input": 5.00, "output": 15.00},
        "gpt-4o-mini": {"input": 0.15, "output": 0.60},
    },
    "anthropic": {
        "claude-3-5-sonnet": {"input": 3.00, "output": 15.00},
        "claude-3-haiku": {"input": 0.25, "output": 1.25},
    },
}

def calculate_cost(provider, model, prompt_tokens, completion_tokens):
    if provider in PRICING and model in PRICING[provider]:
        p = PRICING[provider][model]
        return round((prompt_tokens / 1_000_000) * p["input"] +
                     (completion_tokens / 1_000_000) * p["output"], 6)
    return 0.0

The database schema already has a provider column, so no migration needed. Just start logging calls from each provider with the right tag and the tracker handles the rest.

What to Watch For

A few things I’ve learned from running this for a while:

Token counts aren’t always accurate. Some providers round or estimate token counts differently. OpenAI’s tokenizer and Anthropic’s don’t produce identical counts for the same text. Treat the numbers as close enough for budgeting, not as exact billing records — always cross-check against your actual monthly invoice if something looks off.

Cached requests can distort your picture. OpenAI offers prompt caching that discounts repeated prefix tokens. Your tracker won’t know about cache discounts unless you capture that metadata, so your calculated costs may be slightly higher than what you actually pay. That’s fine for a budgeting tool — just know the discrepancy exists.

Don’t log sensitive data. The request_body_preview field stores up to 200 characters of your request. If you’re sending prompts that contain user data, API keys, or anything you wouldn’t want in a plain-text database, either disable that field or sanitize it first. This database lives on your disk with no encryption by default.

Set a budget alert — because as OpenAI’s recurrent depth technique shows, the way models think internally is changing, and cost visibility is only going to get more important. Once you have a week of data, calculate your average daily cost and set a simple threshold check before each call — if the projected monthly run rate exceeds your budget, log a warning. It’s a lightweight version of the enterprise alerting that HiddenLayer and similar platforms sell, built into your own code.

Where to Go From Here

This tracker is intentionally minimal. From here, you can add: a simple web dashboard using Flask or FastAPI to visualize costs over time, Slack or email alerts when a project crosses a threshold, per-environment tagging (development vs. production calls separated), and integration with your CI/CD pipeline to catch runaway test suites before they incur real costs.

The foundation is the same either way: log every call, tag it clearly, calculate the cost, and review it regularly. That 30-minute setup pays for itself the first time it catches a cost problem before the bill arrives — whether you’re calling OpenAI from a cloud function or running local LLMs through Ollama on your own hardware.

Have a cost tracking setup that works for your team? The approaches above are what I’ve found practical for solo and small-team projects — different scales need different tools, and I’d be curious to hear what’s working for larger deployments.

Filed under Tech & Gadgets
Last Update: September 23, 2026 by Felix AlterEgo
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Newest
Oldest Most Voted