Back to PXL-808
PXL-808Documentation
Session Logging System - Technical Design Document
For task: π± Track sessions on device with cloud sync
Debugging sync race conditions (PXL-801) and other issues is extremely difficult with live logs because:
- βIssues are intermittent and hard to reproduce
- βBy the time an issue is noticed, the relevant logs have scrolled away
- βNo way to capture logs from real-world usage sessions
- βCan't debug issues that happen when not connected to Xcode
Create an on-device session logging system that:
- βCaptures all console output to a local log file per app session
- βSyncs logs to CloudKit public database for cross-device access
- βTracks session status (active/terminated/crashed)
- βProvides UI for viewing and exporting logs
- βAuto-cleans old logs (7 days local, 30 days remote)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β APP LAUNCH β
β β β
β ββββββββββββββββββββββββββΌβββββββββββββββββββββββββ β
β βΌ βΌ βΌ β
β βββββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββββββ β
β β Create new β β Check for previous β β Cleanup remote β β
β β session log β β incomplete sessions β β logs > 30 days β β
β β (local) β β (crashed last time?) β β for this user β β
β βββββββββββββββ ββββββββββββ¬ββββββββββββ ββββββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββ β
β β Upload unsynced prev β β
β β session as "CRASHED" β β
β ββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β APP RUNNING β
β β β
β ββββββββββββββββββββββββββ΄βββββββββββββββββββββββββ β
β βΌ βΌ β
β βββββββββββββββββββ βββββββββββββββββββββββ β
β β Log to file β β Every 60 seconds: β β
β β continuously β β Upload to CloudKit β β
β β (local) β β status: "ACTIVE" β β
β βββββββββββββββββββ βββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β APP STATE CHANGES β
β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββ β
β β BACKGROUNDED β β FOREGROUNDED β β TERMINATED β β
β β β’ Flush buffer β β β’ Log "resumed"β β β’ Mark TERMINATED β β
β β β’ Keep logging β β β’ Upload to CK β β β’ Final flush β β
β β β β immediately β β β’ Upload to CK β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β APP CRASH β
β β β
β βΌ β
β βββββββββββββββββββββββββββββββββββββββ β
β β β No time to handle during crash β β
β β β β
β β β
On NEXT launch: β β
β β β’ Detect incomplete session β β
β β (no SESSION END marker) β β
β β β’ Upload with status: "CRASHED" β β
β βββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Record Type: SessionLog β
β Database: Public (developer-accessible from any device) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Fields: β
β βββββββββββββββββββββ¬ββββββββββββββ¬ββββββββββββββββββββββββββββ
β β Field β Type β Example ββ
β βββββββββββββββββββββΌββββββββββββββΌβββββββββββββββββββββββββββ€β
β β userId β String β "abc123-def456-..." ββ
β β cloudKitUserId β String β "_abc123xyz..." ββ
β β sessionId β String β "2025-12-30_14-32-05" ββ
β β filename β String β "abc123_session_..." ββ
β β logFile β CKAsset β (the .log file) ββ
β β status β String β "active"/"terminated"/ ββ
β β β β "crashed" ββ
β β startedAt β Date β 2025-12-30T14:32:05Z ββ
β β lastUpdatedAt β Date β 2025-12-30T15:45:00Z ββ
β β endedAt β Date? β null (if active) ββ
β β deviceModel β String β "iPhone 15 Pro" ββ
β β iosVersion β String β "18.2" ββ
β β appVersion β String β "1.2.3 (456)" ββ
β β fileSizeBytes β Int64 β 1048576 ββ
β βββββββββββββββββββββ΄ββββββββββββββ΄ββββββββββββββββββββββββββββ
β β
β Record ID: {userId}_{sessionId} β
β (allows upsert on each upload) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
================================================================================
SESSION: {userId}_{sessionId}
STATUS: ACTIVE
LAST UPDATED: 2025-12-30 15:45:00.123
================================================================================
Device: iPhone 15 Pro
iOS: 18.2
App: NutriKit 1.2.3 (456)
User ID: abc123-def456-...
CloudKit ID: _abc123xyz...
================================================================================
[14:32:05.001] [INFO] [App] π± Session started
[14:32:05.045] [INFO] [Sync] Starting full sync...
[14:35:20.234] [INFO] [MealCreate] New meal: "Breakfast"
[14:40:05.567] [INFO] [App] βΈοΈ Entering background
[15:15:30.001] [INFO] [App] βΆοΈ Returning to foreground
[15:15:30.002] [INFO] [App] βοΈ Uploading log to CloudKit...
[15:20:45.123] [INFO] [MealCreate] New meal: "Lunch"
...
================================================================================
SESSION END: 2025-12-30 18:45:12.789
STATUS: TERMINATED
DURATION: 4h 13m 7s
================================================================================
Admin Sheet (existing, with new row)
βββββββββββββββββββββββββββββββββββββββββββββββ
β β Admin β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β DATA MANAGEMENT β
β βββββββββββββββββββββββββββββββββββββββ β
β β π Restore Meals from Backup > β β
β βββββββββββββββββββββββββββββββββββββββ€ β
β β π² Generate Dummy Data > β β
β βββββββββββββββββββββββββββββββββββββββ€ β
β β ποΈ Delete Data > β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β DIAGNOSTICS β
β βββββββββββββββββββββββββββββββββββββββ β
β β π Session Logs > β β
β β 12 sessions β’ 2.4 MB β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββ
Session Logs List View
βββββββββββββββββββββββββββββββββββββββββββββββ
β β Session Logs Edit β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β [Local βΌ] [Cloud] β Segment picker β
β β
β π’ CURRENT SESSION (this device) β
β βββββββββββββββββββββββββββββββββββββββ β
β β π± iPhone 15 Pro > β β
β β Today, 2:32 PM β’ Running β’ 1.8 MB β β
β β βοΈ Last synced: 2 min ago β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β CLOUD SESSIONS (all devices, 30 days) β
β βββββββββββββββββββββββββββββββββββββββ β
β β π± iPhone 15 Pro ACTIVE > β β
β β Today, 2:32 PM β’ 1.8 MB β β
β βββββββββββββββββββββββββββββββββββββββ€ β
β β π± iPhone 15 Pro TERMINATED> β β
β β Yesterday, 8:30 AM β’ 3.2 MB β β
β βββββββββββββββββββββββββββββββββββββββ€ β
β β π» iPad Pro TERMINATED> β β
β β Dec 28, 10:15 AM β’ 2.1 MB β β
β βββββββββββββββββββββββββββββββββββββββ€ β
β β π± iPhone 15 Pro CRASHED > β β
β β Dec 27, 3:45 PM β’ 1.5 MB β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββ β
β β ποΈ Delete All Cloud Logs β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β Cloud logs auto-delete after 30 days β
β β
βββββββββββββββββββββββββββββββββββββββββββββββ
Log Detail View
βββββββββββββββββββββββββββββββββββββββββββββββ
β β Yesterday, 8:30 AM β Share β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β SESSION INFO β
β βββββββββββββββββββββββββββββββββββββββ β
β β Started Dec 29, 8:30:15 AM β β
β β Ended Dec 29, 10:52:30 PM β β
β β Duration 14h 22m 15s β β
β β File Size 3.2 MB β β
β β Device iPhone 15 Pro β β
β β iOS 18.2 β β
β β App Ver 1.2.3 (456) β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β LOG CONTENT [Search π] β
β βββββββββββββββββββββββββββββββββββββββ β
β β [08:30:15] π± Session started β β
β β [08:30:16] [Sync] Starting... β β
β β [08:35:20] [MealCreate] Breakfast β β
β β [08:40:05] βΈοΈ Entering background β β
β β [12:15:30] βΆοΈ Returning foreground β β
β β [12:15:32] [Sync] Starting... β β
β β [12:20:45] [MealCreate] Lunch β β
β β [12:25:10] βΈοΈ Entering background β β
β β [18:30:00] βΆοΈ Returning foreground β β
β β [18:35:22] [MealCreate] Dinner β β
β β [18:40:15] βΈοΈ Entering background β β
β β [22:52:30] π Session terminated β β
β β βΌ scroll β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββ β
β β π€ Export Log File β β
β βββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββ
Time Event Local CloudKit
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
14:32 App launches π Created
14:32 Session starts βοΈ Writing
14:33 +60 sec timer fires βοΈ Writing βοΈ Upload (ACTIVE)
14:34 +60 sec timer fires βοΈ Writing βοΈ Upload (ACTIVE)
14:35 User backgrounds app βοΈ Flush
14:40 User foregrounds βοΈ Writing βοΈ Upload (ACTIVE)
14:41 +60 sec timer fires βοΈ Writing βοΈ Upload (ACTIVE)
...
18:45 User terminates app π Complete βοΈ Upload (TERMINATED)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
CRASH SCENARIO:
14:32 App launches π Created
14:33 +60 sec timer fires βοΈ Writing βοΈ Upload (ACTIVE)
14:34 π₯ CRASH π Incomplete βοΈ Still "ACTIVE"
(next launch)
14:40 App launches π Detect orphan βοΈ Upload (CRASHED)
Per-Session Size Analysis
| Log Verbosity | Lines/Hour | Bytes/Line | Size/Hour | 8hr Session |
|---|---|---|---|---|
| Light use | ~500 | ~100 | ~50 KB | ~400 KB |
| Normal use | ~2,000 | ~120 | ~240 KB | ~2 MB |
| Heavy use | ~5,000 | ~150 | ~750 KB | ~6 MB |
| Debug sync | ~10,000 | ~150 | ~1.5 MB | ~12 MB |
Realistic estimate: 2-4 MB per session (normal use)
30-Day Storage per User
| Usage Pattern | Sessions/Day | Size/Session | 30-Day Total |
|---|---|---|---|
| Casual | 1 | 2 MB | ~60 MB |
| Regular | 1-2 | 3 MB | ~120 MB |
| Power user | 2-3 | 4 MB | ~300 MB |
| Debug mode | 2-3 | 10 MB | ~900 MB |
Typical user: ~100-200 MB per 30 days
CloudKit Public Database Capacity
With 1 PB total storage:
- β1 user: 200 MB = 0.00002% of capacity
- β100 users: 20 GB = 0.002% of capacity
- β1,000 users: 200 GB = 0.02% of capacity
- β10,000 users: 2 TB = 0.2% of capacity
- β100,000 users: 20 TB = 2% of capacity
Verdict: Storage is not a concern with 1 PB capacity and 30-day cleanup
Documents/
βββ Logs/
βββ session_2025-12-30_14-32-05.log β Current (in progress)
βββ session_2025-12-30_10-15-32.log β 312 KB
βββ session_2025-12-29_20-30-15.log β 1.2 MB
βββ session_2025-12-29_12-45-00.log β 245 KB
βββ session_2025-12-28_15-20-30.log β 567 KB
(Auto-cleanup: files older than 7 days deleted on app launch)
- β
Packages/App/Sources/App/Services/SessionLogger.swift- βCore logging service with stdout/stderr capture
- βFile creation at Documents/Logs/
- βTimestamp formatting
- βSession header/footer writing
- βFlush mechanism
- β
Packages/App/Sources/App/Services/SessionLogCloudKitManager.swift- βCloudKit sync with public database
- βUpload/fetch/delete operations
- βCrash detection logic
- β
NutriKit/Views/Debug/SessionLogsView.swift- βList view with Local/Cloud segments
- βSession rows with status badges
- β
NutriKit/Views/Debug/SessionLogDetailView.swift- βDetail view with session info
- βScrollable log content
- βSearch and export functionality
- β
NutriKit/NutriKitApp.swift- βInitialize SessionLogger on launch
- βHandle scene phase changes
- βRegister for termination notification
- β
NutriKit/Views/Debug/AdminSheet.swift- βAdd "DIAGNOSTICS" section
- βAdd "Session Logs" navigation row
- β
Packages/App/Sources/App/Extensions/Logger.swift- βIntegrate OSLog with session file writing
- βSession continues through backgrounding, only ends on true termination
- βCrash detection relies on missing SESSION END marker
- βCloudKit uploads use CKAsset for efficient large file handling
- β60-second upload interval balances freshness vs. battery/network
- βPublic database allows developer access from any device
- βBuffer flush on background ensures no data loss if iOS kills app
Created Dec 30, 2025, 1:33 PM Β· Updated Dec 30, 2025, 1:36 PM