# logging-debugging > How to use the logging system and debug the 10K Scorekeeper app. - Author: Mason Campbell - Repository: zekkathura/10K_Project - Version: 20260124180122 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-07 - Source: https://github.com/zekkathura/10K_Project - Web: https://mule.run/skillshub/@@zekkathura/10K_Project~logging-debugging:20260124180122 --- # Logging & Debugging Skill How to use the logging system and debug the 10K Scorekeeper app. --- ## Logger Overview **File:** `src/lib/logger.ts` The app uses a centralized logger with these features: - **PII sanitization** - Emails, UUIDs, tokens are redacted - **Backend control** - Debug logs can be enabled remotely without a new build - **Error reporting** - Errors are sent to Supabase `error_logs` table ### Log Levels | Level | When to Use | Visibility | |-------|-------------|------------| | `logger.debug()` | Detailed flow info | Dev mode OR backend-enabled | | `logger.info()` | General app flow | Dev mode OR backend-enabled | | `logger.warn()` | Potential issues | Dev mode OR backend-enabled | | `logger.error()` | Actual errors | **Always** (+ sent to Supabase) | ### Usage ```typescript import { logger } from '../lib/logger'; // Simple debug logger.debug('Loading game', gameId); // With object context logger.debug('[DELETE] Edge Function returned:', { data, hasError: !!error }); // Errors (always logged + sent to backend) logger.error('Failed to save game', error, { screen: 'GameScreen', action: 'saveGame' }); // Scoped logger for a component const log = logger.scope('GameScreen'); log.debug('Mounted'); log.error('Save failed', error); ``` --- ## Backend Debug Control Enable debug logging in production without rebuilding: 1. Go to **Supabase Dashboard** → **Table Editor** → `app_config` 2. Find key: `debug_logging_enabled` 3. Set value to `true` or `false` When `true`, all `logger.debug/info/warn` calls will output to console even in production builds. --- ## Viewing Logs ### Expo Go (Development) Logs appear in the terminal running `npm start`: ```bash npm start # Logs show here in real-time ``` ### iOS (Expo Go on iPad/iPhone) When connected via Expo Go, logs appear in the terminal running the dev server: ``` LOG [DEBUG] [ALERT] show() called: Delete Account? platform: ios LOG [DEBUG] [ALERT] Using native iOS Alert LOG [DEBUG] [DELETE] confirmDeleteAccount called ``` ### Android (Logcat) For installed APKs: ```bash # View all logs adb logcat # Filter for app logs adb logcat | grep -i "10k\|tenk\|DEBUG\|ERROR" # Clear and watch adb logcat -c && adb logcat | grep -i "DEBUG\|ERROR" ``` ### Production Errors (Supabase) View logged errors: 1. Go to **Supabase Dashboard** → **Table Editor** → `error_logs` 2. Or run query: ```sql SELECT created_at, level, message, error_name, screen, action, platform, app_version FROM error_logs ORDER BY created_at DESC LIMIT 50; ``` --- ## Debug Patterns ### Prefix Convention Use bracketed prefixes for easy filtering: ```typescript logger.debug('[DELETE] Starting account deletion'); logger.debug('[ALERT] Showing modal:', title); logger.debug('[GAME] Round completed:', roundNumber); ``` ### Tracing Flow For complex async operations, log entry/exit points: ```typescript const handleSubmit = async () => { logger.debug('[SUBMIT] Starting...'); try { logger.debug('[SUBMIT] Calling API...'); const result = await api.call(); logger.debug('[SUBMIT] API returned:', { success: true }); } catch (error) { logger.debug('[SUBMIT] API failed:', error?.message); logger.error('Submit failed', error); } }; ``` --- ## Common Debugging Scenarios ### iOS Modal Not Appearing On iOS, modals inside modals don't work. ThemedAlert uses native `Alert.alert()` on iOS to avoid this. If modals aren't appearing: 1. Check logs for `[ALERT] show() called` - if present, the call is happening 2. Check for `[ALERT] Using native iOS Alert` - confirms iOS path is taken 3. If neither appears, the alert.show() call isn't being reached ### Edge Function Errors ```typescript logger.debug('[DELETE] Calling Edge Function...'); const { data, error } = await supabase.functions.invoke('delete-account'); logger.debug('[DELETE] Response:', { data, hasError: !!error }); if (error) { // FunctionsHttpError has response body in error.context const errorData = await error.context?.json?.(); logger.debug('[DELETE] Error context:', errorData); } ``` ### Button Not Responding Add logging to verify handler is called: ```typescript const handlePress = () => { logger.debug('[BUTTON] handlePress called'); // ... rest of handler }; ``` --- ## Error Logs Table Schema ```sql CREATE TABLE error_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), created_at TIMESTAMPTZ DEFAULT now(), user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL, level TEXT NOT NULL, -- 'error' or 'warn' message TEXT NOT NULL, error_name TEXT, error_stack TEXT, screen TEXT, action TEXT, app_version TEXT, platform TEXT, extra_data JSONB DEFAULT '{}' ); ``` --- ## Never Use console.log Always use `logger.debug()` instead of `console.log()`: ```typescript // Bad - bypasses backend control console.log('Debug info:', data); // Good - respects debug_logging_enabled flag logger.debug('Debug info:', data); ``` The only exception is in `logger.ts` itself during initialization.