slogan3

Adviseer mij over geavanceerde Capacitor app foutafhandeling en logging

description

Met deze prompt kan ik mijn Capacitor app voorzien van een geavanceerd systeem voor foutafhandeling en logging, wat bijdraagt aan betere stabiliteit, eenvoudiger debuggen en snellere probleemoplossing. Dit is effectiever dan basis foutafhandeling omdat het ook externe services en configuraties omvat voor diepgaand inzicht.

prompt

Help mij een robuust foutafhandelings- en loggingsysteem te ontwerpen voor mijn Capacitor app. Beschrijf hoe ik foutmeldingen effectief kan opvangen en loggen, inclusief het gebruik van externe logging services of lokale opslag ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Een robuust foutafhandelings- en loggingsysteem voor je Capacitor-app op iOS kan je betrouwbaarheid en onderhoudbaarheid aanzienlijk verbeteren. Hier zijn stappen en voorbeelden om dit te realiseren: 1. Vervang console.log door een gestructureerde loggingstrategie 2. Gebruik externe logging services voor centrale monitoring 3. Log ook lokale fouten zodat ze niet verloren gaan 4. Integreer foutafhandeling in je app-levenscyclus en API-calls --- ### 1. Logging bibliotheek kiezen Gebruik bijvoorbeeld een populaire logging library zoals [Winston](https://github.com/winstonjs/winston) of [loglevel](https://github.com/pimterry/loglevel), of maak een eenvoudige wrapper: ```typescript // log.ts export enum LogLevel { DEBUG, INFO, WARN, ERROR, } export class Logger { static logLevel: LogLevel = LogLevel.INFO; static log(level: LogLevel, message: string, data?: any) { if (level >= this.logLevel) { const prefix = LogLevel[level]; console.log(`[${prefix}] ${message}`, data || ''); } // Hier kan je ook een externe service aanroepen } static error(message: string, error?: any) { this.log(LogLevel.ERROR, message, error); // Voeg hier externe logging toe sendErrorToService(message, error); } static info(message: string, data?: any) { this.log(LogLevel.INFO, message, data); } } function sendErrorToService(message: string, error?: any) { // Voorbeeld: Log naar een externe service zoals Sentry, Loggly, etc. // Hier moet je de SDK integreren } ``` --- ### 2. Externe logging service integreren Voor iOS kun je bijvoorbeeld Sentry gebruiken: ```bash npm install @sentry/capacitor npx cap sync ``` In je app initialiseren: ```typescript import * as Sentry from '@sentry/capacitor'; Sentry.init({ dsn: 'JE_DSN_URL', // vervang door jouw DSN tracesSampleRate: 1.0, }); ``` En voor het loggen van fouten: ```typescript async function sendErrorToService(message: string, error?: any) { try { await Sentry.captureException(error || new Error(message)); } catch (e) { // fallback: log naar lokale opslag LocalErrorLogger.log(error || new Error(message)); } } ``` --- ### 3. Lokale opslag voor foutmeldingen Gebruik bijvoorbeeld [Capacitor Storage](https://capacitorjs.com/docs/apis/storage) om fouten lokaal op te slaan: ```typescript import { Storage } from '@capacitor/storage'; class LocalErrorLogger { static async log(error: any) { const timestamp = new Date().toISOString(); const errorEntry = { timestamp, message: error.message || error.toString(), stack: error.stack || null, }; const existing = await Storage.get({ key: 'errorLogs' }); let logs = []; if (existing.value) { logs = JSON.parse(existing.value); } logs.push(errorEntry); await Storage.set({ key: 'errorLogs', value: JSON.stringify(logs), }); } static async getLogs() { const { value } = await Storage.get({ key: 'errorLogs' }); return value ? JSON.parse(value) : []; } static async clearLogs() { await Storage.remove({ key: 'errorLogs' }); } } ``` --- ### 4. Foutafhandeling in je app Gebruik try/catch blokken en centraliseer foutmeldingen: ```typescript async function fetchData() { try { const response = await fetch('https://api.example.com/data'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); return data; } catch (error) { Logger.error('Fout tijdens fetchData', error); } } ``` --- ### 5. Gecombineerde aanpak - Vervang `console.log` door `Logger` met niveaus - Fouten worden gelogd naar externe services en lokaal - Bij app crashes of onopgevangen fouten: registreer global error handler: ```typescript window.onerror = (message, source, lineno, colno, error) => { Logger.error('Onverwachte fout', error); return false; // of true om te voorkomen dat de standaard alert verschijnt }; ``` --- ### Samenvatting - Gebruik een gestructureerde logger - Integreer een externe service zoals Sentry voor centrale monitoring - Log ook fouten lokaal om gegevens niet te verliezen - Implementeer global error handlers - Test je systeem door fouten bewust op te roepen Met deze aanpak maak je je foutafhandeling veel robuuster en krijg je waardevolle inzichten in problemen in je iOS Capacitor app.
provider: deepseek
model: deepseek-chat
Zeker! Hier is een robuust foutafhandelings- en loggingsysteem voor je Capacitor iOS app: ## 1. Basis Foutafhandelingsstructuur ### Globale Error Handler ```typescript // src/utils/errorHandler.ts class ErrorHandler { private isInitialized = false; init() { if (this.isInitialized) return; // Vang onafhandelde Promise rejections window.addEventListener('unhandledrejection', (event) => { this.logError('UNHANDLED_PROMISE_REJECTION', { reason: event.reason, stack: event.reason?.stack }); }); // Vang globale JavaScript errors window.addEventListener('error', (event) => { this.logError('GLOBAL_ERROR', { message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, error: event.error }); }); this.isInitialized = true; } async handleError(error: any, context?: string) { const errorInfo = { message: error?.message || 'Unknown error', stack: error?.stack, context: context || 'Unknown context', timestamp: new Date().toISOString(), platform: 'ios', appVersion: await this.getAppVersion() }; await this.logError('HANDLED_ERROR', errorInfo); return errorInfo; } private async getAppVersion(): Promise<string> { try { const { getAppInfo } = await import('@capacitor/app'); const info = await getAppInfo(); return `${info.version} (${info.build})`; } catch { return 'unknown'; } } } export const errorHandler = new ErrorHandler(); ``` ## 2. Logging Service met Meerdere Backends ```typescript // src/services/logger.ts import { Preferences } from '@capacitor/preferences'; import { Filesystem, Directory } from '@capacitor/filesystem'; interface LogEntry { level: 'ERROR' | 'WARN' | 'INFO' | 'DEBUG'; message: string; timestamp: string; context?: string; extraData?: any; } class Logger { private readonly MAX_LOCAL_LOGS = 1000; private readonly LOG_FILE = 'app_logs.json'; async log(level: LogEntry['level'], message: string, context?: string, extraData?: any) { const entry: LogEntry = { level, message, timestamp: new Date().toISOString(), context, extraData }; // Console logging (alleen in development) if (import.meta.env.DEV) { this.consoleLog(entry); } // Lokale opslag await this.saveToLocalStorage(entry); // File systeem logging voor persistente opslag await this.saveToFileSystem(entry); // Externe service (bij productie errors) if (level === 'ERROR' && !import.meta.env.DEV) { await this.sendToExternalService(entry); } } private consoleLog(entry: LogEntry) { const styles = { ERROR: 'color: red; font-weight: bold;', WARN: 'color: orange; font-weight: bold;', INFO: 'color: blue;', DEBUG: 'color: gray;' }; console.log( `%c[${entry.level}] ${entry.timestamp}${entry.context ? ` [${entry.context}]` : ''}: ${entry.message}`, styles[entry.level] ); if (entry.extraData) { console.log('Extra data:', entry.extraData); } } private async saveToLocalStorage(entry: LogEntry) { try { const { value } = await Preferences.get({ key: 'app_logs' }); const logs: LogEntry[] = value ? JSON.parse(value) : []; logs.push(entry); // Beperk het aantal logs if (logs.length > this.MAX_LOCAL_LOGS) { logs.splice(0, logs.length - this.MAX_LOCAL_LOGS); } await Preferences.set({ key: 'app_logs', value: JSON.stringify(logs) }); } catch (error) { console.error('Failed to save log to localStorage:', error); } } private async saveToFileSystem(entry: LogEntry) { try { // Check of bestand bestaat let existingLogs: LogEntry[] = []; try { const contents = await Filesystem.readFile({ path: this.LOG_FILE, directory: Directory.Data }); existingLogs = JSON.parse(contents.data); } catch { // Bestand bestaat niet - normaal bij eerste run } existingLogs.push(entry); // Beperk file logs if (existingLogs.length > this.MAX_LOCAL_LOGS) { existingLogs.splice(0, existingLogs.length - this.MAX_LOCAL_LOGS); } await Filesystem.writeFile({ path: this.LOG_FILE, data: JSON.stringify(existingLogs), directory: Directory.Data, encoding: 'utf8' }); } catch (error) { console.error('Failed to save log to filesystem:', error); } } private async sendToExternalService(entry: LogEntry) { try { // Voorbeeld: Sentry integratie if (typeof window !== 'undefined' && (window as any).Sentry) { (window as any).Sentry.captureException(new Error(entry.message), { extra: { context: entry.context, timestamp: entry.timestamp, ...entry.extraData } }); } // Of je eigen backend await fetch('https://your-logging-service.com/api/logs', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...entry, deviceInfo: await this.getDeviceInfo() }) }); } catch (error) { console.warn('Failed to send log to external service:', error); } } private async getDeviceInfo() { const { getDeviceInfo } = await import('@capacitor/device'); return await getDeviceInfo(); } // Helper methods voor verschillende log levels async error(message: string, context?: string, extraData?: any) { await this.log('ERROR', message, context, extraData); } async warn(message: string, context?: string, extraData?: any) { await this.log('WARN', message, context, extraData); } async info(message: string, context?: string, extraData?: any) { await this.log('INFO', message, context, extraData); } async debug(message: string, context?: string, extraData?: any) { await this.log('DEBUG', message, context, extraData); } // Log retrieval methods async getLocalLogs(): Promise<LogEntry[]> { try { const { value } = await Preferences.get({ key: 'app_logs' }); return value ? JSON.parse(value) : []; } catch { return []; } } async getFileLogs(): Promise<LogEntry[]> { try { const contents = await Filesystem.readFile({ path: this.LOG_FILE, directory: Directory.Data }); return JSON.parse(contents.data); } catch { return []; } } async clearLogs() { await Preferences.remove({ key: 'app_logs' }); try { await Filesystem.deleteFile({ path: this.LOG_FILE, directory: Directory.Data }); } catch { // Bestand bestaat niet } } } export const logger = new Logger(); ``` ## 3. Gebruik in je App ### Initialisatie ```typescript // src/main.ts of App.vue import { errorHandler } from './utils/errorHandler'; import { logger } from './services/logger'; // Initialiseer error handling errorHandler.init(); // Voorbeeld: App start logging logger.info('App gestart', 'AppInitialization'); ``` ### Gebruik in Components ```typescript // In je Vue component import { logger, errorHandler } from '../services/logger'; export default { methods: { async fetchData() { try { logger.info('Start data fetch', 'DataService'); const response = await fetch('https://api.example.com/data'); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); logger.info('Data succesvol opgehaald', 'DataService', { itemCount: data.length }); return data; } catch (error) { const errorInfo = await errorHandler.handleError(error, 'fetchData'); logger.error('Data fetch gefaald', 'DataService', errorInfo); // Toon gebruikersvriendelijke foutmelding this.showError('Kon data niet ophalen. Probeer het later opnieuw.'); } }, showError(message: string) { // Gebruik Capacitor Toast of eigen modal import('@capacitor/toast').then(({ Toast }) => { Toast.show({ text: message, duration: 'long' }); }); } } } ``` ## 4. Capacitor Configuratie ### capacitor.config.ts ```typescript import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { appId: 'com.jouwapp.app', appName: 'Jouw App', webDir: 'dist', server: { androidScheme: 'https' }, plugins: { Preferences: {}, Filesystem: {}, Toast: { text: 'Hello!', duration: 'short' } } }; export default config; ``` ## 5. Externe Logging Services ### Sentry Configuratie ```typescript // src/utils/sentry.ts import * as Sentry from '@sentry/capacitor'; import * as SentryVue from '@sentry/vue'; export const initSentry = (app: any) => { if (!import.meta.env.DEV) { Sentry.init({ app, dsn: 'JOUW_SENTRY_DSN_HIER', integrations: [ new SentryVue.BrowserTracing({ trackComponents: true, }), ], tracesSampleRate: 0.1, // 10% van requests }); } }; ``` ## 6. Log Viewer voor Development ```typescript // src/utils/logViewer.ts (alleen voor development) import { logger } from '../services/logger'; export const setupLogViewer = () => { if (import.meta.env.DEV) { // Maak logger globaal beschikbaar in development (window as any).$logger = logger; console.log('🔍 Logger is beschikbaar als window.$logger'); console.log('Beschikbare commands:'); console.log(' - $logger.getLocalLogs()'); console.log(' - $logger.getFileLogs()'); console.log(' - $logger.clearLogs()'); } }; ``` ## Gebruik: 1. **Initialiseer** in je main.ts: ```typescript errorHandler.init(); setupLogViewer(); ``` 2. **Log errors** in je code: ```typescript try { // je code } catch (error) { await logger.error('Operation failed', 'ComponentName', { userId: 123 }); } ``` 3. **Log informatie**: ```typescript await logger.info('User action', 'ButtonClick', { buttonId: 'submit' }); ``` Dit systeem biedt: - ✅ Meerdere logging backends (console, localStorage, filesystem, extern) - ✅ Automatische error capturing - ✅ Gebruikersvriendelijke foutmeldingen - ✅ Persistente log opslag - ✅ Development tools - ✅ Schaalbaar voor productie gebruik Je kunt eenvoudig externe services zoals Sentry, LogRocket of je eigen backend toevoegen via de `sendToExternalService` methode.