From 45217104b35a1fe723d63f028ef07bd2cd3fe75b Mon Sep 17 00:00:00 2001 From: Vova Ignatov Date: Fri, 19 Jul 2024 11:00:59 +0100 Subject: [PATCH] IOS-3180 Support debug run profiler in debug menu --- .../Debug/DebugMenuView.swift | 38 +++++++++++++------ .../Debug/DebugMenuViewModel.swift | 31 +++++++++++++++ .../Sources/Services/Debug/DebugService.swift | 7 ++++ 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/Anytype/Sources/PresentationLayer/Debug/DebugMenuView.swift b/Anytype/Sources/PresentationLayer/Debug/DebugMenuView.swift index f0279e034c..bde1065dfb 100644 --- a/Anytype/Sources/PresentationLayer/Debug/DebugMenuView.swift +++ b/Anytype/Sources/PresentationLayer/Debug/DebugMenuView.swift @@ -81,29 +81,32 @@ struct DebugMenuView: View { private var mainActions: some View { VStack { - HStack { - StandardButton("Logs ๐Ÿงป", style: .secondaryLarge) { - showLogs.toggle() - } + StandardButton("Logs ๐Ÿงป", style: .secondaryLarge) { + showLogs.toggle() } StandardButton("Export localstore ๐Ÿ“", style: .secondaryLarge) { UIImpactFeedbackGenerator(style: .heavy).impactOccurred() model.getLocalStoreData() } + + if case .done(url: let url) = model.debugRunProfilerData { + StandardButton("Download Debug Run Profiler Data ๐Ÿ’ฟ", style: .secondaryLarge) { + UIImpactFeedbackGenerator(style: .heavy).impactOccurred() + model.shareUrlContent(url: url) + } + } } } private var moreActions: some View { VStack { - HStack { - StandardButton("Crash ๐Ÿ”ฅ", style: .primaryLarge) { - let crash: [Int] = [] - _ = crash[1] - } - StandardButton("Assert ๐Ÿฅฒ", style: .secondaryLarge) { - anytypeAssertionFailure("Test assert") - } + StandardButton("Crash ๐Ÿ”ฅ", style: .primaryLarge) { + let crash: [Int] = [] + _ = crash[1] + } + StandardButton("Assert ๐Ÿฅฒ", style: .secondaryLarge) { + anytypeAssertionFailure("Test assert") } StandardButton("Membership debug ๐Ÿ’ธ", style: .secondaryLarge) { @@ -119,6 +122,17 @@ struct DebugMenuView: View { UIImpactFeedbackGenerator(style: .heavy).impactOccurred() try await model.onSpaceDebug() } + + switch model.debugRunProfilerData { + case .empty, .done: + StandardButton("Run debug profiler ๐Ÿค“", style: .secondaryLarge) { + UIImpactFeedbackGenerator(style: .heavy).impactOccurred() + model.onDebugRunProfiler() + } + case .inProgress: + Text("Profiling in progress ...") + } + StandardButton("Export full directory ๐Ÿค", style: .secondaryLarge) { UIImpactFeedbackGenerator(style: .heavy).impactOccurred() model.zipWorkingDirectory() diff --git a/Anytype/Sources/PresentationLayer/Debug/DebugMenuViewModel.swift b/Anytype/Sources/PresentationLayer/Debug/DebugMenuViewModel.swift index 21234f8dae..728def073a 100644 --- a/Anytype/Sources/PresentationLayer/Debug/DebugMenuViewModel.swift +++ b/Anytype/Sources/PresentationLayer/Debug/DebugMenuViewModel.swift @@ -4,6 +4,12 @@ import AnytypeCore import Services import ZIPFoundation +enum DebugRunProfilerState: Codable { + case empty + case inProgress + case done(url: URL) +} + @MainActor final class DebugMenuViewModel: ObservableObject { @@ -12,6 +18,9 @@ final class DebugMenuViewModel: ObservableObject { @Published var showZipPicker = false @Published private(set) var flags = [FeatureFlagSection]() + @Published var debugRunProfilerData = DebugRunProfilerState.empty + @UserDefault("DebugRunProfiler", defaultValue: .empty) private var debugRunProfilerDataStore: DebugRunProfilerState + @Injected(\.debugService) private var debugService: any DebugServiceProtocol @Injected(\.localAuthService) @@ -29,6 +38,7 @@ final class DebugMenuViewModel: ObservableObject { init() { updateFlags() + debugRunProfilerData = debugRunProfilerDataStore } func removeRecoveryPhraseFromDevice() { @@ -93,6 +103,27 @@ final class DebugMenuViewModel: ObservableObject { shareUrlFile = jsonFile } + func onDebugRunProfiler() { + debugRunProfilerData = .inProgress + debugRunProfilerDataStore = .inProgress + + Task.detached { [self] in + let path = try await debugService.debugRunProfiler() + let zipFile = FileManager.default.createTempDirectory().appendingPathComponent("debugRunProfiler.zip") + try FileManager.default.zipItem(at: URL(fileURLWithPath: path), to: zipFile) + + + Task { @MainActor in + debugRunProfilerData = .done(url: zipFile) + debugRunProfilerDataStore = .done(url: zipFile) + } + } + } + + func shareUrlContent(url: URL) { + shareUrlFile = url + } + // MARK: - Private private func updateFlags() { diff --git a/Modules/Services/Sources/Services/Debug/DebugService.swift b/Modules/Services/Sources/Services/Debug/DebugService.swift index f02c83e7d0..e0f62fcae2 100644 --- a/Modules/Services/Sources/Services/Debug/DebugService.swift +++ b/Modules/Services/Sources/Services/Debug/DebugService.swift @@ -6,6 +6,7 @@ public protocol DebugServiceProtocol: AnyObject, Sendable { func exportLocalStore() async throws -> String func exportStackGoroutines() async throws -> String func exportSpaceDebug(spaceId: String) async throws -> String + func debugRunProfiler() async throws -> String } final class DebugService: DebugServiceProtocol { @@ -37,4 +38,10 @@ final class DebugService: DebugServiceProtocol { }).invoke() return try result.jsonString() } + + public func debugRunProfiler() async throws -> String { + return try await ClientCommands.debugRunProfiler(.with { + $0.durationInSeconds = 60 + }).invoke().path + } }