Debug Mode
Debug mode provides detailed logging and diagnostic information for troubleshooting SupaScan indexing, API, and database issues.
Enabling Debug Mode
Environment Variables
# Enable debug logging
export LOG_LEVEL=debug
export NODE_ENV=development
export SUPASCAN_DEBUG=true
# Run SupaScan
npm start
In .env File
LOG_LEVEL=debug
NODE_ENV=development
SUPASCAN_DEBUG=true
CLICKHOUSE_DEBUG=true
INDEXING_DEBUG=true
Runtime Configuration
// Enable debug at runtime
import { logger } from './utils/logger';
import { config } from './config';
config.debug = true;
logger.level = 'debug';
Debug Output
Log Levels
| Level | Description | Use Case |
|---|---|---|
| error | Critical errors | System failures |
| warn | Warnings | Potential issues |
| info | Information | Normal operations |
| debug | Debug details | Development/troubleshooting |
| silly | Everything | Deep debugging |
Debug Information Examples
[2024-01-15 10:23:45] DEBUG: Processing block 12345678
slot: 12345678
transactions: 45
tokenTransfers: 23
dexSwaps: 12
processingTime: 234ms
clickhouseInsertTime: 12ms
[2024-01-15 10:23:46] DEBUG: API Request
endpoint: /v1/tokens/So111.../analysis
userId: user_123
responseTime: 89ms
cacheHit: false
Debug Commands
API Debug Endpoints
GET /debug/status
Shows current system status:
{
"debugMode": true,
"logLevel": "debug",
"environment": "development",
"memoryUsage": "124MB / 512MB",
"uptime": "2h 34m",
"indexingStatus": "active",
"clickhouseConnections": 8,
"queueSize": 3
}
GET /debug/indexing
Indexing performance metrics:
{
"blocksProcessed": 12345,
"blocksPerSecond": 2.3,
"lastProcessedSlot": 12345678,
"currentSlot": 12345680,
"lagSeconds": 2,
"failedBlocks": 3,
"averageProcessingTime": "234ms"
}
GET /debug/clickhouse
ClickHouse cluster status:
{
"clusterHealth": "healthy",
"activeConnections": 8,
"queryCount": 1234,
"averageQueryTime": "12ms",
"slowQueries": 2,
"memoryUsage": "2.1GB",
"diskUsage": "45GB"
}
GET /debug/api
API performance metrics:
{
"totalRequests": 5678,
"averageResponseTime": "89ms",
"p95ResponseTime": "234ms",
"errorRate": "0.5%",
"cacheHitRate": "87%",
"rateLimitHits": 12
}
Debug Features
Indexing Debug
// Block processing debug
class IndexingDebugger {
async processBlock(slot: number) {
const start = Date.now();
logger.debug('Processing block', { slot });
try {
const block = await this.fetchBlock(slot);
logger.debug('Block fetched', {
slot,
transactions: block.transactions?.length || 0,
fetchTime: Date.now() - start
});
const parsed = await this.parseBlock(block);
logger.debug('Block parsed', {
slot,
tokenTransfers: parsed.tokenTransfers.length,
dexSwaps: parsed.dexSwaps.length,
parseTime: Date.now() - start
});
await this.insertToClickHouse(parsed);
logger.debug('Block inserted', {
slot,
totalTime: Date.now() - start
});
} catch (error) {
logger.error('Block processing failed', { slot, error: error.message });
}
}
}
ClickHouse Query Debugging
// ClickHouse query logging
class ClickHouseDebugger {
async query(sql: string, params?: any[]) {
const start = Date.now();
logger.debug('ClickHouse Query', {
sql: sql.substring(0, 200) + '...',
params: params?.length || 0
});
try {
const result = await this.client.query({ query: sql, params });
logger.debug('ClickHouse Response', {
duration: Date.now() - start,
rows: result.rows,
bytes: result.bytes
});
return result;
} catch (error) {
logger.error('ClickHouse Error', {
sql: sql.substring(0, 200),
error: error.message,
duration: Date.now() - start
});
throw error;
}
}
}
API Request Debugging
// API request tracing
app.use((req, res, next) => {
const requestId = generateRequestId();
req.requestId = requestId;
logger.debug('API Request', {
requestId,
method: req.method,
url: req.url,
userAgent: req.get('User-Agent'),
ip: req.ip
});
const start = Date.now();
res.on('finish', () => {
logger.debug('API Response', {
requestId,
statusCode: res.statusCode,
duration: Date.now() - start
});
});
next();
});
Debug Tools
ClickHouse Query Analysis
-- Monitor slow queries
SELECT
query,
query_duration_ms,
read_rows,
read_bytes,
memory_usage
FROM system.query_log
WHERE event_date = today()
AND query_duration_ms > 1000
ORDER BY query_duration_ms DESC;
-- Check table sizes
SELECT
table,
formatReadableSize(sum(bytes)) as size,
count() as parts
FROM system.parts
WHERE database = 'supascan'
GROUP BY table
ORDER BY sum(bytes) DESC;
Indexing Performance
# Monitor indexing lag
curl http://localhost:3000/debug/indexing
# Check RPC node health
curl -X POST https://api.mainnet-beta.solana.com \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'
# Test ClickHouse connection
curl 'http://localhost:8123/?query=SELECT%201'
Memory and CPU Profiling
# Start with profiling
node --inspect --max-old-space-size=4096 src/index.js
# Connect Chrome DevTools
chrome://inspect
# Monitor memory usage
node --max-old-space-size=4096 --trace-gc src/index.js
Debug Configuration
Development Config
// config/debug.ts
export const debugConfig = {
// Logging
logLevel: 'debug',
logIndexing: true,
logClickHouse: true,
logAPI: true,
logWebhooks: true,
// Performance
profileMemory: true,
trackMetrics: true,
slowQueryThreshold: 1000,
// Development
prettyPrint: true,
stackTraces: true,
verboseErrors: true
};
Debug Middleware
// API error handling
app.use((err, req, res, next) => {
if (config.debug) {
logger.error('API Error', {
error: err,
stack: err.stack,
requestId: req.requestId,
url: req.url,
method: req.method
});
res.status(500).json({
error: 'Internal Server Error',
debug: err.stack,
requestId: req.requestId
});
} else {
logger.error('API Error', { error: err.message });
res.status(500).json({ error: 'Internal Server Error' });
}
});
Common Debug Scenarios
1. Indexing Lag
# Check indexing status
curl http://localhost:3000/debug/indexing
# Check RPC node health
curl -X POST https://api.mainnet-beta.solana.com \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}'
# Check ClickHouse cluster
curl 'http://localhost:8123/?query=SELECT%20hostName(),%20uptime()%20FROM%20system.clusters'
2. ClickHouse Issues
-- Check cluster health
SELECT hostName(), uptime(), version() FROM system.clusters;
-- Check replication status
SELECT table, replica_name, is_leader, log_pointer
FROM system.replicas
WHERE database = 'supascan';
-- Monitor slow queries
SELECT query, query_duration_ms, read_rows
FROM system.query_log
WHERE event_date = today()
ORDER BY query_duration_ms DESC
LIMIT 10;
3. API Performance Issues
# Check API metrics
curl http://localhost:3000/debug/api
# Test specific endpoint
curl -H "Authorization: Bearer sk_test_123" \
http://localhost:3000/v1/tokens/So111.../analysis
# Check rate limiting
curl -H "Authorization: Bearer sk_test_123" \
http://localhost:3000/v1/debug/rate-limits
4. Memory and Performance
// Memory monitoring
setInterval(() => {
const usage = process.memoryUsage();
logger.debug('Memory snapshot', {
rss: Math.round(usage.rss / 1024 / 1024),
heap: Math.round(usage.heapUsed / 1024 / 1024),
external: Math.round(usage.external / 1024 / 1024)
});
}, 60000);
// Performance timing
class PerformanceDebugger {
private timers = new Map();
start(label: string) {
this.timers.set(label, Date.now());
logger.debug(`Timer started: ${label}`);
}
end(label: string) {
const start = this.timers.get(label);
if (start) {
const duration = Date.now() - start;
logger.debug(`Timer ended: ${label}`, { duration });
this.timers.delete(label);
}
}
}
Debug Best Practices
-
Use Structured Logging
// Good logger.debug('Block processed', { slot, transactions, duration }); // Avoid console.log(`Block ${slot} processed with ${transactions} txs`); -
Add Context to Logs
logger.debug('Indexing failed', { context: 'block_processing', slot: 12345678, error: err.message, retryCount: 3 }); -
Use Debug Namespaces
const debug = { indexing: require('debug')('supascan:indexing'), clickhouse: require('debug')('supascan:clickhouse'), api: require('debug')('supascan:api') }; -
Monitor Performance
// Track slow operations if (duration > config.slowQueryThreshold) { logger.warn('Slow operation', { operation, duration }); } -
Clean Up Debug Code
if (process.env.NODE_ENV !== 'production') { // Debug only code }
Security Considerations
⚠️ Warning: Debug mode can expose sensitive information!
- Never enable in production
- Don't log API keys or private data
- Sanitize user input in logs
- Restrict debug endpoints to admins
- Clear debug logs regularly
- Use HTTPS for debug endpoints