Quellcode durchsuchen

Write logs into a file

Ivan Valkou vor 5 Jahren
Ursprung
Commit
c35b96015d

+ 4 - 0
FreeAPS.xcodeproj/project.pbxproj

@@ -198,6 +198,7 @@
 		38E98A2D25F52DC400C0CED0 /* NSLocking+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A2C25F52DC400C0CED0 /* NSLocking+Extensions.swift */; };
 		38E98A3025F52FF700C0CED0 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A2F25F52FF700C0CED0 /* Config.swift */; };
 		38E98A3725F5509500C0CED0 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E98A3625F5509500C0CED0 /* String+Extensions.swift */; };
+		38EA05DA261F6E7C0064E39B /* SimpleLogReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38EA05D9261F6E7C0064E39B /* SimpleLogReporter.swift */; };
 		38F37828261260DC009DB701 /* Color+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38F37827261260DC009DB701 /* Color+Extensions.swift */; };
 		38F3B2EF25ED8E2A005C48AA /* TempTargetsStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38F3B2EE25ED8E2A005C48AA /* TempTargetsStorage.swift */; };
 		38FCF3D625E8FDF40078B0D1 /* MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38FCF3D525E8FDF40078B0D1 /* MD5.swift */; };
@@ -479,6 +480,7 @@
 		38E98A2C25F52DC400C0CED0 /* NSLocking+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSLocking+Extensions.swift"; sourceTree = "<group>"; };
 		38E98A2F25F52FF700C0CED0 /* Config.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = "<group>"; };
 		38E98A3625F5509500C0CED0 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
+		38EA05D9261F6E7C0064E39B /* SimpleLogReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleLogReporter.swift; sourceTree = "<group>"; };
 		38F37827261260DC009DB701 /* Color+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Extensions.swift"; sourceTree = "<group>"; };
 		38F3783A2613555C009DB701 /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
 		38F3B2EE25ED8E2A005C48AA /* TempTargetsStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempTargetsStorage.swift; sourceTree = "<group>"; };
@@ -1188,6 +1190,7 @@
 			children = (
 				38E98A1E25F52C9300C0CED0 /* IssueReporter.swift */,
 				38E98A2025F52C9300C0CED0 /* CollectionIssueReporter.swift */,
+				38EA05D9261F6E7C0064E39B /* SimpleLogReporter.swift */,
 			);
 			path = IssueReporter;
 			sourceTree = "<group>";
@@ -1702,6 +1705,7 @@
 				3811DE3525C9D49500A708ED /* HomeRootView.swift in Sources */,
 				3811DEC325C9D99900A708ED /* UIContainer.swift in Sources */,
 				38E98A2925F52C9300C0CED0 /* Error+Extensions.swift in Sources */,
+				38EA05DA261F6E7C0064E39B /* SimpleLogReporter.swift in Sources */,
 				3811DE6125C9D4D500A708ED /* ViewModifiers.swift in Sources */,
 				3811DEAC25C9D88300A708ED /* NightscoutManager.swift in Sources */,
 				3811DE3325C9D49500A708ED /* HomeBuilder.swift in Sources */,

+ 8 - 1
FreeAPS/Sources/Containers/ServiceContainer.swift

@@ -7,6 +7,13 @@ enum ServiceContainer: DependeciesContainer {
     static func register(container: Container) {
         container.register(NotificationCenter.self) { _ in Foundation.NotificationCenter.default }
         container.register(Broadcaster.self) { _ in BaseBroadcaster() }
-        container.register(GroupedIssueReporter.self) { _ in CollectionIssueReporter() }
+        container.register(GroupedIssueReporter.self) { _ in
+            let reporter = CollectionIssueReporter()
+            reporter.add(reporters: [
+                SimpleLogReporter()
+            ])
+            reporter.setup()
+            return reporter
+        }
     }
 }

+ 88 - 0
FreeAPS/Sources/Logger/IssueReporter/SimpleLogReporter.swift

@@ -0,0 +1,88 @@
+import Foundation
+import SwiftDate
+
+final class SimpleLogReporter: IssueReporter {
+    private let fileManager = FileManager.default
+
+    private var dateFormatter: DateFormatter {
+        let dateFormatter = DateFormatter()
+        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
+        return dateFormatter
+    }
+
+    func setup() {}
+
+    func setUserIdentifier(_: String?) {}
+
+    func reportNonFatalIssue(withName _: String, attributes _: [String: String]) {}
+
+    func reportNonFatalIssue(withError _: NSError) {}
+
+    func log(_ category: String, _ message: String, file: String, function: String, line: UInt) {
+        let now = Date()
+        let startOfDay = Calendar.current.startOfDay(for: now)
+
+        if !fileManager.fileExists(atPath: SimpleLogReporter.logDir) {
+            try? fileManager.createDirectory(
+                atPath: SimpleLogReporter.logDir,
+                withIntermediateDirectories: false,
+                attributes: nil
+            )
+        }
+
+        if !fileManager.fileExists(atPath: SimpleLogReporter.logFile) {
+            createFile(at: startOfDay)
+        } else {
+            if let attributes = try? fileManager.attributesOfItem(atPath: SimpleLogReporter.logFile),
+               let creationDate = attributes[.creationDate] as? Date, creationDate < startOfDay
+            {
+                try? fileManager.moveItem(atPath: SimpleLogReporter.logFile, toPath: SimpleLogReporter.logFilePrev)
+                createFile(at: startOfDay)
+            }
+        }
+
+        let logEntry = "\(dateFormatter.string(from: now)) [\(category)] \(file.file) - \(function) - \(line) - \(message)\n"
+        let data = logEntry.data(using: .utf8)!
+        try? data.append(fileURL: URL(fileURLWithPath: SimpleLogReporter.logFile))
+    }
+
+    private func createFile(at date: Date) {
+        fileManager.createFile(atPath: SimpleLogReporter.logFile, contents: nil, attributes: [.creationDate: date])
+    }
+
+    static var logFile: String {
+        getDocumentsDirectory().appendingPathComponent("logs/log.txt").path
+    }
+
+    static var logDir: String {
+        getDocumentsDirectory().appendingPathComponent("logs").path
+    }
+
+    static var logFilePrev: String {
+        getDocumentsDirectory().appendingPathComponent("logs/log_prev.txt").path
+    }
+
+    static func getDocumentsDirectory() -> URL {
+        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
+        let documentsDirectory = paths[0]
+        return documentsDirectory
+    }
+}
+
+private extension Data {
+    func append(fileURL: URL) throws {
+        if let fileHandle = FileHandle(forWritingAtPath: fileURL.path) {
+            defer {
+                fileHandle.closeFile()
+            }
+            fileHandle.seekToEndOfFile()
+            fileHandle.write(self)
+        } else {
+            try write(to: fileURL, options: .atomic)
+        }
+    }
+}
+
+private extension String {
+    var file: String { components(separatedBy: "/").last ?? "" }
+}

+ 15 - 0
FreeAPS/Sources/Modules/Settings/SettingsViewModel.swift

@@ -4,6 +4,7 @@ extension Settings {
     class ViewModel<Provider>: BaseViewModel<Provider>, ObservableObject where Provider: SettingsProvider {
         @Injected() private var settingsManager: SettingsManager!
         @Injected() private var broadcaster: Broadcaster!
+        @Injected() private var fileManager: FileManager!
         @Published var closedLoop = false
 
         @Published var debugOptions = false
@@ -24,6 +25,20 @@ extension Settings {
 
             buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "Unknown"
         }
+
+        func logItems() -> [URL] {
+            var items: [URL] = []
+
+            if fileManager.fileExists(atPath: SimpleLogReporter.logFile) {
+                items.append(URL(fileURLWithPath: SimpleLogReporter.logFile))
+            }
+
+            if fileManager.fileExists(atPath: SimpleLogReporter.logFilePrev) {
+                items.append(URL(fileURLWithPath: SimpleLogReporter.logFilePrev))
+            }
+
+            return items
+        }
     }
 }
 

+ 11 - 0
FreeAPS/Sources/Modules/Settings/View/SettingsRootView.swift

@@ -3,6 +3,7 @@ import SwiftUI
 extension Settings {
     struct RootView: BaseView {
         @EnvironmentObject var viewModel: ViewModel<Provider>
+        @State private var showShareSheet = false
 
         var body: some View {
             Form {
@@ -82,6 +83,16 @@ extension Settings {
                         }
                     }
                 }
+
+                Section {
+                    Text("Share logs").chevronCell()
+                        .onTapGesture {
+                            showShareSheet = true
+                        }
+                }
+            }
+            .sheet(isPresented: $showShareSheet) {
+                ShareSheet(activityItems: viewModel.logItems())
             }
             .navigationTitle("Settings")
             .navigationBarItems(leading: Button("Close", action: viewModel.hideModal))