crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit 12ed896d2fc23b65bb2dc3da4b17e84936684581
parent 7e9c7909a6af77de116e50b193d06d618a80ba35
Author: Michael Camilleri <[email protected]>
Date:   Sat,  2 May 2026 09:52:13 +0900

Increase granularity of logging

Diffstat:
MCrossmate/Services/AppServices.swift | 30+++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/Crossmate/Services/AppServices.swift b/Crossmate/Services/AppServices.swift @@ -64,12 +64,35 @@ final class AppServices { thresholdMS: thresholdMS ) }, - afterFlush: { gameIDs in + afterFlush: { [performanceMonitor] gameIDs in + let snapshotStart = ContinuousClock.now let result = await store.createSnapshotsIfNeeded(for: gameIDs) + await performanceMonitor.record( + "moveBuffer.snapshotCheck", + durationMS: Self.milliseconds(from: snapshotStart.duration(to: .now)), + detail: "games=\(gameIDs.count) snapshots=\(result.snapshotNames.count) prunedMoves=\(result.prunedMoveNames.count)", + thresholdMS: 8 + ) + + let snapshotEnqueueStart = ContinuousClock.now for name in result.snapshotNames { await syncEngine.enqueueSnapshot(ckRecordName: name) } + await performanceMonitor.record( + "moveBuffer.snapshotEnqueue", + durationMS: Self.milliseconds(from: snapshotEnqueueStart.duration(to: .now)), + detail: "snapshots=\(result.snapshotNames.count)", + thresholdMS: 4 + ) + + let deleteEnqueueStart = ContinuousClock.now await syncEngine.enqueueDeleteRecords(result.prunedMoveNames) + await performanceMonitor.record( + "moveBuffer.deleteEnqueue", + durationMS: Self.milliseconds(from: deleteEnqueueStart.duration(to: .now)), + detail: "moves=\(result.prunedMoveNames.count)", + thresholdMS: 4 + ) }, sessionPingSink: { [preferences] gameID, authorID in let name = await MainActor.run { preferences.name } @@ -343,6 +366,11 @@ final class AppServices { syncMonitor.updateSnapshot(snapshot) } + private static func milliseconds(from duration: Duration) -> Double { + Double(duration.components.seconds) * 1000 + + Double(duration.components.attoseconds) / 1_000_000_000_000_000 + } + /// Builds the `GameStore.onGameDeleted` callback. Extracted so tests can /// drive the exact same closure that production wires up — keeps the /// colour-cleanup branch from drifting silently.