The analytics system now supports two storage backends:
- SQLite (recommended): High-performance database with indexing
- JSON (legacy): Original format for backward compatibility
| Metric | JSON | SQLite | Improvement |
|---|---|---|---|
| Complex queries | 500ms+ | 10-50ms | 10-50x faster |
| Data export | 2-5s | 0.2-0.5s | 10x faster |
| Write performance | File I/O | WAL mode | 5x faster |
| Query flexibility | Limited | SQL power | Advanced |
| Scalability | ~10k sessions | 1M+ sessions | 100x better |
cd /path/to/HazeBot
cp Data/app_analytics.json Data/app_analytics.json.backup
cp Data/error_analytics.json Data/error_analytics.json.backupTest the migration without writing to database:
python analytics/json_to_sqlite.py --dry-runExpected output:
📊 Analytics Migration: JSON → SQLite
============================================================
Data directory: Data
Database path: Data/analytics.db
Dry run: True
⚠️ DRY RUN MODE - No data will be written to database
📊 Migrating main analytics data...
✅ Sessions: 1234
✅ User stats: 56
✅ Daily stats: 89
🐛 Migrating error analytics...
✅ Error logs: 123
📦 Migrating archived data...
✅ Files: 3
✅ Archived sessions: 456
python analytics/json_to_sqlite.pyThis will:
- Create
Data/analytics.db - Migrate all sessions, user stats, daily stats
- Migrate error logs
- Migrate archived monthly files
- Optimize database with VACUUM
Edit .env file or set environment variable:
# .env file
ANALYTICS_BACKEND=sqliteOr keep using JSON:
# .env file
ANALYTICS_BACKEND=json# Stop current bot
# Then restart with:
python start_with_api.pyCheck logs for:
📊 Using SQLite backend: Data/analytics.db
Analytics aggregator initialized (backend=SQLite, ...)
The system maintains full backward compatibility:
- JSON Mode: Original behavior, no changes needed
- SQLite Mode: New high-performance backend
- Seamless Switch: Change
ANALYTICS_BACKENDanytime - Dashboard: Works with both backends automatically
After migration:
Data/
├── analytics.db # SQLite database (new)
├── analytics.db-shm # SQLite shared memory
├── analytics.db-wal # SQLite write-ahead log
├── app_analytics.json # Original data (keep as backup)
├── error_analytics.json # Original errors (keep as backup)
└── analytics_archive/ # Archived monthly JSON files
├── 2025-09.json
├── 2025-10.json
└── 2025-11.json
CREATE TABLE sessions (
session_id TEXT PRIMARY KEY,
discord_id TEXT NOT NULL,
username TEXT NOT NULL,
started_at TEXT NOT NULL,
ended_at TEXT,
duration_minutes REAL,
platform TEXT,
device_info TEXT,
app_version TEXT,
ip_address TEXT,
actions_count INTEGER,
endpoints_used TEXT, -- JSON
screens_visited TEXT, -- JSON
created_at TEXT
);idx_sessions_discord_ididx_sessions_started_atidx_sessions_platform- 10+ more optimized indexes
sqlite3 Data/analytics.db
# View tables
.tables
# View schema
.schema sessions
# Example queries
SELECT COUNT(*) FROM sessions;
SELECT discord_id, COUNT(*) as session_count FROM sessions GROUP BY discord_id;
SELECT * FROM sessions WHERE started_at >= '2025-12-01' LIMIT 10;from api.analytics_db import AnalyticsDatabase
db = AnalyticsDatabase(Path("Data/analytics.db"))
# Get sessions
sessions = db.get_sessions(start_date="2025-12-01", limit=100)
# Get user stats
user_stats = db.get_user_stats()
# Complex queries
with db._get_connection() as conn:
cursor = conn.cursor()
cursor.execute("""
SELECT platform, COUNT(*) as count
FROM sessions
GROUP BY platform
ORDER BY count DESC
""")
results = cursor.fetchall()# Check database size
ls -lh Data/analytics.db
# Count records
sqlite3 Data/analytics.db "SELECT COUNT(*) FROM sessions;"
sqlite3 Data/analytics.db "SELECT COUNT(*) FROM user_stats;"
sqlite3 Data/analytics.db "SELECT COUNT(*) FROM daily_stats;"- Start bot with SQLite backend
- Open dashboard:
http://localhost:8089/analytics/analytics_dashboard.html - Verify all charts load correctly
- Test date range filters
- Check feature analytics section
# Run performance tests
python analytics/test_performance.pyCause: SQLite database empty or backend mismatch
Solution:
# 1. Check backend setting
grep ANALYTICS_BACKEND .env
# 2. Verify database has data
sqlite3 Data/analytics.db "SELECT COUNT(*) FROM sessions;"
# 3. Re-run migration if needed
python analytics/json_to_sqlite.pyCause: Database already exists from previous migration
Solution:
# Option 1: Delete and recreate
rm Data/analytics.db Data/analytics.db-*
python analytics/json_to_sqlite.py
# Option 2: Skip migration, use existing database
# (Data already migrated)Cause: Python path issue
Solution:
# Run from HazeBot root directory
cd /path/to/HazeBot
python analytics/json_to_sqlite.pyCause: Database not optimized
Solution:
# Run VACUUM to optimize
sqlite3 Data/analytics.db "VACUUM; ANALYZE;"# In app.py
from pathlib import Path
from api.analytics_db import AnalyticsDatabase
db_path = Path("/custom/path/analytics.db")
db = AnalyticsDatabase(db_path)# In app.py
analytics = analytics_module.AnalyticsAggregator(
analytics_file,
batch_interval=300, # 5 minutes (default)
cache_ttl=300 # 5 minutes (default)
)For high-traffic environments:
- Increase
batch_intervalto 600-900s (reduces writes) - Increase
cache_ttlto 600-900s (more cache hits)
Run monthly to reclaim space:
# Optimize database
sqlite3 Data/analytics.db "VACUUM; ANALYZE;"
# Check database integrity
sqlite3 Data/analytics.db "PRAGMA integrity_check;"- Backup current JSON files
- Run dry-run migration
- Review migration output
- Run actual migration
- Verify database size and record counts
- Set
ANALYTICS_BACKEND=sqlitein .env - Restart bot
- Test dashboard functionality
- Run performance tests
- Monitor logs for errors
- Keep JSON backups for 30 days
- Keep JSON backups: Don't delete JSON files immediately after migration
- Test in TestData first: Use
--data-dir TestDatafor testing - Monitor database size: SQLite is efficient but grows over time
- Use VACUUM monthly: Reclaims space and rebuilds indexes
- Archive old data: Consider moving old sessions to separate database
If you need to rollback:
- Set
ANALYTICS_BACKEND=jsonin .env - Restart bot
- System will use original JSON files
- No data loss (JSON files never deleted)
If you encounter issues:
- Check logs in
Logs/directory - Run migration with
--dry-runto diagnose - Verify database integrity
- Test with TestData first
- Keep JSON backups as fallback
Last Updated: December 2, 2025
Version: 1.0
Tested With: Python 3.11+, SQLite 3.35+