Files
new-api-analytics/docs/database.md

72 lines
1.9 KiB
Markdown

# Database Contract
This app reads an existing New API PostgreSQL schema. It does not own migrations.
## Required Environment
```bash
PG_CONNECTION_STRING=postgres://user:password@host:5432/database
```
## Tables Read By The App
### `logs`
Primary analytics source. Only rows with `type = 2` are included.
Expected columns:
- `id`: monotonically increasing log id, used for latest-first log pagination.
- `created_at`: Unix timestamp in seconds.
- `type`: log type; analytics filters to `2`.
- `user_id`: user id.
- `username`: username captured on the log row.
- `model_name`: requested model name.
- `channel_id`: upstream channel id.
- `prompt_tokens`: input token count.
- `completion_tokens`: output token count.
- `quota`: New API quota units.
- `use_time`: request latency in milliseconds.
- `is_stream`: stream flag.
- `token_name`: API token display name.
- `other`: JSON text with optional `upstream_model_name`, `cache_creation_tokens`, and `cache_tokens`.
### `users`
Used for display-name enrichment.
Expected columns:
- `id`
- `username`
- `display_name`
### `channels`
Used for channel-name enrichment.
Expected columns:
- `id`
- `name`
## Recommended Indexes
For large `logs` tables, add or verify indexes that match dashboard filters:
```sql
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_logs_type_created_at
ON logs (type, created_at);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_logs_type_username_created_at
ON logs (type, username, created_at);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_logs_type_channel_created_at
ON logs (type, channel_id, created_at);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_logs_type_id_desc
ON logs (type, id DESC);
```
Model filtering uses the real-model expression derived from `other::jsonb->>'upstream_model_name'` with fallback to `model_name`. Add an expression index only after validating the exact production column type and query plan.