Logging & Evals
Documents a trigger-based logging system, cost tracking, token analytics, and a separate evals dashboard for reviewing LLM interactions.
What this file does
Documents a trigger-based logging system, cost tracking, token analytics, and a separate evals dashboard for reviewing LLM interactions.
When to use it
- You need automatic database change logging with triggers
- You want to track LLM token usage and cost per chat
- You need a separate trace store for evaluating and debugging chat interactions
- You want a settings panel for real-time log inspection and filtering
Assumes this stack
Logging & Evals
Logging System
RA-H uses a trigger-based logging system that automatically captures all database activity in the logs table.
What Gets Logged
Automatically logged via triggers:
- Node operations - Create, update (via
trg_nodes_ai,trg_nodes_au) - Edge operations - Create, update (via
trg_edges_ai,trg_edges_au) - Chat operations - All conversations with token/cost metadata (via
trg_chats_ai)
Log structure:
{
id: number,
ts: timestamp,
table_name: 'nodes' | 'edges' | 'chats',
action: 'INSERT' | 'UPDATE',
row_id: number,
summary: string, // Human-readable description
snapshot_json: string, // Full row data as JSON
enriched_summary: string | null // Enhanced log entry
}
Chat Metadata
Every chat log includes detailed execution metadata. helper-interactions.log is the raw event stream; chats.metadata is the persisted summary used for audits and UI inspection.
metadata: {
// Token tracking
input_tokens: number,
output_tokens: number,
total_tokens: number,
cache_write_tokens?: number,
cache_read_tokens?: number,
// Cost tracking
estimated_cost_usd: number,
model_used: string,
provider: 'anthropic' | 'openai',
// Tool usage
tools_used?: string[], // Unique tool names used in the chat
tool_calls_count?: number, // Total tool invocations
tool_calls?: Array<{
toolName: string,
args: unknown,
result: unknown
}>,
// Workflow tracking
workflow_key?: string,
workflow_node_id?: number,
// Execution trace
session_id?: string,
trace_id?: string,
parent_chat_id?: number
}
Auto-Pruning
Trigger: trg_logs_prune
Behavior: Keeps last 10,000 log entries
Runs: After every INSERT to logs table
This prevents infinite database growth while preserving recent activity history.
Enriched Logs View
View: logs_v
Purpose: Joins log entries with related data for readable activity feed
Enrichment:
- Node logs → show node title
- Edge logs → show from/to node titles
- Chat logs → show agent name, user/assistant message previews
Settings Panel Visibility
Location: Settings → Logs tab
Features:
- Real-time activity feed - Shows last 100 log entries
- Table filtering - Filter by nodes/edges/chats
- Action filtering - Filter by INSERT/UPDATE
- Detailed view - Click to see full snapshot_json
- Token/cost visibility - Chat logs show usage and costs
- Tool usage - See both the tool set used and full per-call payloads when captured
Query:
SELECT * FROM logs_v
ORDER BY ts DESC
LIMIT 100
Cost Tracking
Automatic cost calculation:
- Every chat records token counts from LLM response
- Cost computed using model-specific pricing
- Stored in
chats.metadata.cost(USD) - Aggregated in Settings → Analytics
Model pricing (current defaults):
- GPT-5.4 Mini: $0.75/1M input, $0.075/1M cached input, $4.50/1M output
- GPT-5.4: $2.50/1M input, $0.25/1M cached input, $15.00/1M output
- GPT-5 Mini: $0.25/1M input, $0.025/1M cached input, $2.00/1M output
- GPT-5: $1.25/1M input, $0.125/1M cached input, $10.00/1M output
- GPT-4o Mini: $0.15/1M input, $0.60/1M output
- Claude Sonnet 4.5: $3.00/1M input, $15.00/1M output
Typical costs: Vary by prompt size, tool activity, and provider cache hits.
Token Analytics
Settings → Analytics panel shows:
- Total tokens used (all time)
- Total cost (USD)
- Breakdown by helper
- Breakdown by conversation thread
- Average cost per chat
Query:
SELECT
helper_name,
COUNT(*) as chat_count,
SUM(JSON_EXTRACT(metadata, '$.total_tokens')) as total_tokens,
SUM(JSON_EXTRACT(metadata, '$.estimated_cost_usd')) as total_cost
FROM chats
WHERE metadata IS NOT NULL
GROUP BY helper_name
Evals Dashboard
The generic Settings -> Logs panel is useful for quick inspection, but it is not the primary trace-review surface.
For proper evals, use:
logs/evals.sqliteas the dev-only trace store/evalsas the main review UI
This evals path stores:
- one
llm_chatsrow per traced interaction - one
tool_callsrow per tool execution - shared
trace_idvalues so chat/tool steps can be reviewed together - both synthetic scenarios and live app interactions when eval logging is enabled
How To Run
Start the app with eval logging enabled:
npm run dev:evals
Then:
- use the app normally for live traces
- open http://localhost:3000/evals
To run the scenario suite against the local app:
npm run evals
Requirements:
- the dev server must already be running with eval logging enabled via
npm run dev:evals - the scenario runner targets
http://localhost:3000by default - the runner now waits up to 60s per scenario by default because current real latencies often exceed 10s
Optional overrides:
RAH_EVALS_BASE_URL=http://localhost:3001 npm run evals
RAH_EVALS_TIMEOUT_MS=90000 npm run evals
The /evals UI lets you review:
- live runs vs scenario runs
- full system message
- user/assistant turn
- tool spans with args/results
- latency
- token and cost data
- cache fields
- timing breakdown fields when available
Why This Is Separate From The Logs Table
logs in the main SQLite database is trigger-based change logging. It mirrors a compact snapshot of chat rows, nodes, and edges.
logs/evals.sqlite is the trace store for evaluation and review. It is the correct place to inspect:
- per-trace chat rows
- per-tool spans
- scenario IDs
- live-vs-scenario separation
If you want to understand one interaction deeply, prefer /evals over Settings -> Logs.
What's inside
7 sections: logging system, chat metadata, auto-pruning, enriched view, settings panel, cost tracking, token analytics, evals dashboard with run instructions
Change this for your project
- Replace model pricing values like
$0.75/1M inputwith your actual LLM provider costs - Replace
npm run dev:evalsandnpm run evalswith your project's script names - Replace
http://localhost:3000with your app's base URL - Replace
logs/evals.sqlitewith your preferred evals database path
Where it goes
Keep in docs/ or alongside the feature. Agents read it to implement against a defined contract.
Worth borrowing
- Using database triggers to automatically log all mutations to a separate logs table
- Storing detailed LLM execution metadata (tokens, cost, tool calls) alongside chat records
- Separating operational change logs from a dedicated evals database for trace review
Related Documents
Community AI Agent Skills Discovery Sources
Catalogs 50+ platforms, repositories, directories, and communities for discovering and sharing AI agent skills across multiple coding tools.
GPU Selection Guide for Large Language Models (LLMs)
Guides GPU selection for LLM inference, fine-tuning, and training by mapping model sizes, precision levels, and budgets to VRAM requirements.
ReleaseKit - Technical Requirements Document
Specifies a Go library and CLI for release automation with conventional commit parsing, validation checks, and workflow orchestration.
Python Development Environment Setup with Ruff
Defines a complete Python development environment using Ruff for linting and formatting, with pytest, mypy, pre-commit hooks, and VSCode configuration.