How to Audit OpenAI API Usage with Token Tracking and Logs
Purpose
This post demonstrates how to audit OpenAI API usage with detailed token tracking and request logs.
My team was getting charged for OpenAI API usage, but we had no idea which application or user was consuming tokens. I logged into the OpenAI dashboard and saw:
Total Usage: $127.43 this monthAPI Calls: 15,234Tokens: 2.1M
But which app caused this? No clue.The dashboard shows aggregate numbers but nothing about per-request granularity. I needed to know:
- Which applications are making the most calls?
- What prompts are being sent?
- How many tokens per request?
Environment
- Python 3.11
- OpenAI API (multiple applications)
- ai-menshen v0.3.0
- SQLite 3.39
What happened?
We have multiple applications calling the OpenAI API:
+------------------+ +------------------+| App A | | App B || (Chatbot) | | (Code Gen) |+--------+---------+ +--------+---------+ | | v v+-----------------------------------------------+| OpenAI API || (api.openai.com) |+-----------------------------------------------+
Each app has its own API key, but the dashboard only shows totals.I tried using OpenAI’s usage API:
import openai
# Get usage for the monthusage = openai.Usage.list( start_date="2026-03-01", end_date="2026-03-30")
print(usage)The response:
<OpenAIObject at 0x7f8a1b2c3d40> JSON: { "object": "list", "data": [ { "object": "usage", "total_tokens": 2100000, "n_requests": 15234 } ]}Just totals. No breakdown by app, no individual request details, no prompt/response bodies.
I tried another approach - adding logging to each application manually. But this meant modifying every codebase:
import openaiimport logging
logger = logging.getLogger("openai-usage")
def chat_with_logging(prompt): logger.info(f"Prompt: {prompt}") response = openai.ChatCompletion.create( model="gpt-4", messages=[{"role": "user", "content": prompt}] ) logger.info(f"Response: {response}") logger.info(f"Tokens: {response.usage.total_tokens}") return responseThis approach failed because:
- We have 12 different applications - too many to modify
- Some apps use streaming responses - harder to track
- Each app needed its own logging setup
- No centralized view of all usage
How to solve it?
I found ai-menshen, a local proxy that sits between your applications and OpenAI. It logs everything automatically.
Step 1: Install and configure ai-menshen
pip install ai-menshen
# Create config directorymkdir -p ~/.config/ai-menshenCreate the configuration file:
[proxy]port = 8080host = "127.0.0.1"
[storage]retention_days = 90 # Auto-purge logs older than 90 days
[storage.sqlite]path = "~/.local/share/ai-menshen/audit.db"
[logging]log_request_body = true # Persist full request bodieslog_response_body = true # Persist full response bodiesStep 2: Point applications to the proxy
Instead of modifying each app, I just changed the base URL:
import openai
# Before: direct to OpenAI# openai.api_base = "https://api.openai.com/v1"
# After: through ai-menshen proxyopenai.api_base = "http://localhost:8080/v1"
# That's it. No other changes needed.Or set the environment variable once:
export OPENAI_API_BASE=http://localhost:8080/v1Step 3: Start the proxy and view the dashboard
ai-menshen start
# Output:# Starting ai-menshen proxy on http://127.0.0.1:8080# Dashboard available at http://localhost:8080# SQLite database: ~/.local/share/ai-menshen/audit.dbNow when I open http://localhost:8080 in my browser, I see:
+----------------------------------------------------------+| ai-menshen Dashboard |+----------------------------------------------------------+| Overview | Trends | Audit Logs |+----------------------------------------------------------+| Today's Usage: | [Graph showing | Request List || - Requests: 342 | daily token | - 10:23:45 || - Tokens: 45,678 | consumption] | gpt-4 || - Est. Cost: $0.91| | 1,234 tokens|+----------------------------------------------------------+Step 4: Query the SQLite database directly
For custom reports, I query the database:
sqlite3 ~/.local/share/ai-menshen/audit.db "SELECT timestamp, model, prompt_tokens, completion_tokens, total_tokensFROM audit_logsORDER BY total_tokens DESCLIMIT 10;"Output:
2026-03-30 10:15:23|gpt-4|8234|2100|103342026-03-30 09:42:11|gpt-4|7891|1856|97472026-03-30 11:05:33|gpt-3.5-turbo|3456|890|43462026-03-30 08:30:45|gpt-4|2890|1023|3913For programmatic access:
import sqlite3from datetime import datetime, timedelta
conn = sqlite3.connect('~/.local/share/ai-menshen/audit.db')cursor = conn.cursor()
# Get daily token usage for the last 7 dayscursor.execute(""" SELECT date(timestamp) as day, SUM(total_tokens) as tokens, COUNT(*) as requests FROM audit_logs WHERE timestamp > datetime('now', '-7 days') GROUP BY day ORDER BY day DESC""")
print("Daily usage report:")print("-" * 40)for row in cursor.fetchall(): day, tokens, requests = row print(f"{row[0]}: {tokens:,} tokens ({requests} requests)")Output:
Daily usage report:----------------------------------------2026-03-30: 45,678 tokens (342 requests)2026-03-29: 38,901 tokens (287 requests)2026-03-28: 52,341 tokens (401 requests)2026-03-27: 41,234 tokens (312 requests)The reason
The key insight is that ai-menshen acts as a transparent proxy:
Before:+--------+ +--------+| App |------->| OpenAI |+--------+ +--------+ | v [No visibility]
After:+--------+ +------------+ +--------+| App |----->| ai-menshen |----->| OpenAI |+--------+ +------------+ +--------+ | v +--------------+ | SQLite DB | | (Full Audit) | +--------------+ | v +--------------+ | Dashboard | +--------------+This works because:
- Zero code changes: Just change the API endpoint URL
- Streaming support: Token counts are captured even for streaming responses
- Full request/response: Bodies are stored when
log_request_bodyandlog_response_bodyare enabled - Automatic retention: Old logs are purged based on
retention_days - Local control: All data stays on your machine in SQLite
Common mistakes to avoid
Mistake 1: Not enabling body logging
If you skip log_request_body = true, you lose the ability to debug:
[logging]# Missing: log_request_body = true# Missing: log_response_body = trueWithout body logging, you can only see token counts, not the actual prompts and responses.
Mistake 2: Setting retention too short
[storage]retention_days = 7 # Too short for compliance needs!For billing disputes or compliance audits, you may need 90+ days of history.
Mistake 3: Ignoring the dashboard trends
The Trends tab shows patterns:
+--------------------------------------------------+| Weekly Token Trend |+--------------------------------------------------+| Mon: ████████████████ 45,000 || Tue: ██████████ 32,000 || Wed: ██████████████████████████████ 78,000 <-- || Thu: ████████████ 36,000 |+--------------------------------------------------+
Wednesday spike: Code generation app ran bulk jobsUse this data for capacity planning and cost optimization.
Summary
In this post, I showed how to audit OpenAI API usage with ai-menshen’s built-in dashboard and SQLite logs. The key points are:
- OpenAI’s dashboard shows only aggregate usage - no per-request granularity
- ai-menshen acts as a transparent proxy that logs everything automatically
- Enable
log_request_bodyandlog_response_bodyfor full debugging capability - Set appropriate
retention_daysfor your compliance needs - Query the SQLite database directly for custom reports
The beauty of this approach is that no application code needs to be modified - just point your OpenAI client to the proxy URL.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments