diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2021-09-14 12:15:25 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-09-14 12:15:25 +0200 |
| commit | 9dd0730bdc9ec141f6fdbb73cd69988a12f04e0f (patch) | |
| tree | 984a26abaefa328d675a76f3f23ada242cdcff80 | |
| parent | b8930db15b76d1866ab18cd58cdf9936dbe0ffa2 (diff) | |
| download | mullvadvpn-9dd0730bdc9ec141f6fdbb73cd69988a12f04e0f.tar.xz mullvadvpn-9dd0730bdc9ec141f6fdbb73cd69988a12f04e0f.zip | |
Remove log forwarder
There is no benefit in forwarding logs now when we have OSLog and problem
report controller that offers viewing on-device logs.
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 22 | ||||
| -rw-r--r-- | ios/MullvadVPN/LogStreamerViewController.swift | 189 | ||||
| -rw-r--r-- | ios/MullvadVPN/Logging/LogEntryParser.swift | 98 | ||||
| -rw-r--r-- | ios/MullvadVPN/Logging/LogStreamer.swift | 141 | ||||
| -rw-r--r-- | ios/MullvadVPN/Logging/StringStreamIterator.swift | 58 | ||||
| -rw-r--r-- | ios/MullvadVPN/Logging/TextFileStream.swift | 77 | ||||
| -rw-r--r-- | ios/MullvadVPN/SettingsViewController.swift | 17 |
7 files changed, 1 insertions, 601 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index d159f98b47..5f81d89189 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -39,7 +39,6 @@ 580EE22824B3289300F9D8A1 /* AssociatedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22724B3289300F9D8A1 /* AssociatedValue.swift */; }; 580EE22924B3289300F9D8A1 /* AssociatedValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 580EE22724B3289300F9D8A1 /* AssociatedValue.swift */; }; 5811DE50239014550011EB53 /* NEVPNStatus+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5811DE4F239014550011EB53 /* NEVPNStatus+Debug.swift */; }; - 58141EC924DAC0ED0013F79C /* TextFileStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58141EC824DAC0ED0013F79C /* TextFileStream.swift */; }; 5815039724D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */; }; 5815039824D6ECAE00C9C50E /* CustomFormatLogHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */; }; 5815039D24D6ECE600C9C50E /* TextFileOutputStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */; }; @@ -112,7 +111,6 @@ 585834FC24D2BC9500A8AF56 /* Logging in Frameworks */ = {isa = PBXBuildFile; productRef = 585834FB24D2BC9500A8AF56 /* Logging */; }; 585CA70F25F8C44600B47C62 /* UIMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585CA70E25F8C44600B47C62 /* UIMetrics.swift */; }; 585DA8AF26B9492500B8C587 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA8AE26B9492500B8C587 /* Promise.swift */; }; - 585FE2F124E1365400439C50 /* LogStreamer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585FE2F024E1365400439C50 /* LogStreamer.swift */; }; 5860392726D91B8400554C79 /* PromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58A94AE526D23C3D001CB97C /* PromiseTests.swift */; }; 5860392926DCE7AB00554C79 /* PromiseCompletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5860392826DCE7AB00554C79 /* PromiseCompletion.swift */; }; 5860392A26DCE7AB00554C79 /* PromiseCompletion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5860392826DCE7AB00554C79 /* PromiseCompletion.swift */; }; @@ -201,9 +199,6 @@ 58BFA5CD22A7CE1F00A6173D /* ApplicationConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */; }; 58C3478B26C1094F0060838B /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585DA8AE26B9492500B8C587 /* Promise.swift */; }; 58C3A4B222456F1B00340BDB /* AccountInputGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C3A4B122456F1A00340BDB /* AccountInputGroupView.swift */; }; - 58C3B06724EA768100C0348E /* LogStreamerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C3B06624EA768100C0348E /* LogStreamerViewController.swift */; }; - 58C3B06924EAA25000C0348E /* StringStreamIterator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C3B06824EAA25000C0348E /* StringStreamIterator.swift */; }; - 58C4CB0124EBE5A700A22D49 /* LogEntryParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C4CB0024EBE5A700A22D49 /* LogEntryParser.swift */; }; 58CAF4EA26025927007C5886 /* PacketTunnelIpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5845F841236CBACD00B2D93C /* PacketTunnelIpc.swift */; }; 58CAF4EF26025954007C5886 /* SimulatorTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58BA693023EADA6A009DC256 /* SimulatorTunnelProvider.swift */; }; 58CB0EE024B86751001EF0D8 /* MullvadRest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58CB0EDF24B86751001EF0D8 /* MullvadRest.swift */; }; @@ -356,7 +351,6 @@ 580EE22324B3243100F9D8A1 /* AsyncBlockOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncBlockOperation.swift; sourceTree = "<group>"; }; 580EE22724B3289300F9D8A1 /* AssociatedValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssociatedValue.swift; sourceTree = "<group>"; }; 5811DE4F239014550011EB53 /* NEVPNStatus+Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NEVPNStatus+Debug.swift"; sourceTree = "<group>"; }; - 58141EC824DAC0ED0013F79C /* TextFileStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFileStream.swift; sourceTree = "<group>"; }; 5815039324D6EB7200C9C50E /* LogRotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogRotation.swift; sourceTree = "<group>"; }; 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomFormatLogHandler.swift; sourceTree = "<group>"; }; 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFileOutputStream.swift; sourceTree = "<group>"; }; @@ -394,7 +388,6 @@ 5857F24624C882D700CF6F47 /* SelectLocationNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectLocationNavigationController.swift; sourceTree = "<group>"; }; 585CA70E25F8C44600B47C62 /* UIMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIMetrics.swift; sourceTree = "<group>"; }; 585DA8AE26B9492500B8C587 /* Promise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; }; - 585FE2F024E1365400439C50 /* LogStreamer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogStreamer.swift; sourceTree = "<group>"; }; 5860392826DCE7AB00554C79 /* PromiseCompletion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseCompletion.swift; sourceTree = "<group>"; }; 5862805322428EF100F5A6E1 /* TranslucentButtonBlurView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslucentButtonBlurView.swift; sourceTree = "<group>"; }; 5866F39B2243B82D00168AE5 /* MullvadVPN.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MullvadVPN.entitlements; sourceTree = "<group>"; }; @@ -454,9 +447,6 @@ 58BFA5C522A7C97F00A6173D /* RelayCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelayCache.swift; sourceTree = "<group>"; }; 58BFA5CB22A7CE1F00A6173D /* ApplicationConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationConfiguration.swift; sourceTree = "<group>"; }; 58C3A4B122456F1A00340BDB /* AccountInputGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountInputGroupView.swift; sourceTree = "<group>"; }; - 58C3B06624EA768100C0348E /* LogStreamerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogStreamerViewController.swift; sourceTree = "<group>"; }; - 58C3B06824EAA25000C0348E /* StringStreamIterator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringStreamIterator.swift; sourceTree = "<group>"; }; - 58C4CB0024EBE5A700A22D49 /* LogEntryParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogEntryParser.swift; sourceTree = "<group>"; }; 58C6B35322BB87C4003C19AD /* PrivateKeyWithMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateKeyWithMetadata.swift; sourceTree = "<group>"; }; 58CB0EDF24B86751001EF0D8 /* MullvadRest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MullvadRest.swift; sourceTree = "<group>"; }; 58CC40EE24A601900019D96E /* ObserverList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObserverList.swift; sourceTree = "<group>"; }; @@ -600,14 +590,10 @@ children = ( 581503A224D6F1EC00C9C50E /* ChainedError+Logger.swift */, 5815039624D6ECAE00C9C50E /* CustomFormatLogHandler.swift */, - 58C4CB0024EBE5A700A22D49 /* LogEntryParser.swift */, 581503A524D6F4AE00C9C50E /* Logging.swift */, 5815039324D6EB7200C9C50E /* LogRotation.swift */, - 585FE2F024E1365400439C50 /* LogStreamer.swift */, - 58C3B06824EAA25000C0348E /* StringStreamIterator.swift */, - 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */, - 58141EC824DAC0ED0013F79C /* TextFileStream.swift */, 5823FA4F26CA690600283BF8 /* OSLogHandler.swift */, + 5815039C24D6ECE600C9C50E /* TextFileOutputStream.swift */, ); path = Logging; sourceTree = "<group>"; @@ -759,7 +745,6 @@ 5815039F24D6ECF200C9C50E /* Logging */, 58B993B02608A34500BA7811 /* LoginContentView.swift */, 58CE5E65224146200008646E /* LoginViewController.swift */, - 58C3B06624EA768100C0348E /* LogStreamerViewController.swift */, 5840250322B11AB700E4CFEC /* MullvadEndpoint.swift */, 58CB0EDF24B86751001EF0D8 /* MullvadRest.swift */, 5866F39B2243B82D00168AE5 /* MullvadVPN.entitlements */, @@ -1241,7 +1226,6 @@ 5873884D239E6D7E00E96C4E /* EmbeddedViewContainerView.swift in Sources */, 583BC70724FE4DC500C9DE04 /* Optional+DispatchQueue.swift in Sources */, 58F3C0A4249CB069003E76BE /* HeaderBarView.swift in Sources */, - 585FE2F124E1365400439C50 /* LogStreamer.swift in Sources */, 58B9EB132488ED2100095626 /* AlertPresenter.swift in Sources */, 587A01FC23F1F0BE00B68763 /* SimulatorTunnelProviderHost.swift in Sources */, 5862805422428EF100F5A6E1 /* TranslucentButtonBlurView.swift in Sources */, @@ -1264,7 +1248,6 @@ 58ACF64F26567A7100ACE4B7 /* CustomSwitchContainer.swift in Sources */, 5857F24324C8662600CF6F47 /* SelectLocationHeaderView.swift in Sources */, 58AEEF652344A36000C9BBD5 /* KeychainError.swift in Sources */, - 58C3B06924EAA25000C0348E /* StringStreamIterator.swift in Sources */, 580EE22824B3289300F9D8A1 /* AssociatedValue.swift in Sources */, 581503A624D6F4AE00C9C50E /* Logging.swift in Sources */, 58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */, @@ -1288,15 +1271,12 @@ 587AD7C623421D7000E93A53 /* TunnelSettings.swift in Sources */, 581503A324D6F1EC00C9C50E /* ChainedError+Logger.swift in Sources */, 58FD5BF024238EB300112C88 /* SKProduct+Formatting.swift in Sources */, - 58C3B06724EA768100C0348E /* LogStreamerViewController.swift in Sources */, 58B43C1925F77DB60002C8C3 /* ConnectMainContentView.swift in Sources */, 58561C99239A5D1500BD6B5E /* IPEndpoint.swift in Sources */, 58FD5BF22424F7D700112C88 /* UserInterfaceInteractionRestriction.swift in Sources */, 5823FA5026CA690600283BF8 /* OSLogHandler.swift in Sources */, 5811DE50239014550011EB53 /* NEVPNStatus+Debug.swift in Sources */, - 58141EC924DAC0ED0013F79C /* TextFileStream.swift in Sources */, 58C3A4B222456F1B00340BDB /* AccountInputGroupView.swift in Sources */, - 58C4CB0124EBE5A700A22D49 /* LogEntryParser.swift in Sources */, 58F840B22464491D0044E708 /* ChainedError.swift in Sources */, 58E1338126D2BF5C00CC316B /* Promise+Result.swift in Sources */, 58FAEDFF24533A7000CB0F5B /* KeychainReturn.swift in Sources */, diff --git a/ios/MullvadVPN/LogStreamerViewController.swift b/ios/MullvadVPN/LogStreamerViewController.swift deleted file mode 100644 index 7774fdf810..0000000000 --- a/ios/MullvadVPN/LogStreamerViewController.swift +++ /dev/null @@ -1,189 +0,0 @@ -// -// LogStreamerViewController.swift -// MullvadVPN -// -// Created by pronebird on 17/08/2020. -// Copyright © 2020 Mullvad VPN AB. All rights reserved. -// - -#if DEBUG - -import Foundation -import UIKit -import Logging - -class LogStreamerViewController: UIViewController, UITextViewDelegate { - - private let textView = UITextView() - private let streamer: LogStreamer<UTF8> - private let logEntryParser = LogEntryParser() - private var currentTextColor: UIColor? - private let timestampFormatter: DateFormatter = { - let formatter = DateFormatter() - formatter.dateFormat = "HH:mm:ss.SSS" - return formatter - }() - - private var autoScrollButtonItem: UIBarButtonItem { - return UIBarButtonItem(barButtonSystemItem: autoScroll ? .pause : .play, target: self, action: #selector(handleToggleAutoscroll(_:))) - } - - private var dismissButtonItem: UIBarButtonItem { - return UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDismissButton(_:))) - } - - var autoScroll: Bool = true { - didSet { - updateAutoScrollBarItem() - handleAutoScroll() - } - } - - init(fileURLs: [URL]) { - streamer = LogStreamer(fileURLs: fileURLs) - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - // MARK: - View lifecycle - - override func viewDidLoad() { - super.viewDidLoad() - - navigationItem.title = "App logs" - navigationItem.leftBarButtonItem = autoScrollButtonItem - navigationItem.rightBarButtonItem = dismissButtonItem - - addSubviews() - startStreamer() - } - - // MARK: - UITextViewDelegate - - func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { - let translation = scrollView.panGestureRecognizer.translation(in: scrollView.superview) - - // Disable autoscroll if user scrolled up - if translation.y > 0 { - autoScroll = false - } else if translation.y < 0 { - // Enable autoscroll if user scrolled to the bottom of the view - let maxScrollY = scrollView.contentSize.height - scrollView.frame.height - - if targetContentOffset.pointee.y >= maxScrollY { - autoScroll = true - } - } - } - - func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { - // Disable autoscroll when user requested scroll to top - autoScroll = false - return true - } - - // MARK: - Private - - private func addSubviews() { - textView.translatesAutoresizingMaskIntoConstraints = false - textView.isEditable = false - if #available(iOS 13.0, *) { - textView.font = UIFont.monospacedSystemFont(ofSize: UIFont.systemFontSize, weight: .regular) - } else { - textView.font = UIFont(name: "Courier", size: UIFont.systemFontSize) - } - textView.delegate = self - - view.addSubview(textView) - - NSLayoutConstraint.activate([ - textView.topAnchor.constraint(equalTo: view.topAnchor), - textView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - textView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - textView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - ]) - } - - private func startStreamer() { - self.streamer.start { [weak self] (str) in - guard let self = self else { return } - - DispatchQueue.main.async { - // Try parsing the entry - let entry = self.logEntryParser.parse(str) - - // Since the log streamer sends the log file line-by-line, it's possible that only a - // part of a multiline message is captured at first. - let message = entry.map { (entry) -> String in - // Reformat the log entry date - let timestamp = self.timestampFormatter.string(from: entry.timestamp) - - return "\(timestamp) \(entry.module) \(entry.message)\n" - } ?? "\(str)\n" - - - // Compute the range for replacing the text color - let start = self.textView.text.utf16.count - let end = start + message.utf16.count - let textRange = NSRange(start..<end) - - self.textView.insertText(message) - self.handleAutoScroll() - - // Update the current log entry color - if let logLevel = entry?.level { - self.currentTextColor = self.textColor(for: logLevel) - } - - // Apply the color attribute to the inserted text - if let textColor = self.currentTextColor { - self.textView.textStorage.addAttributes([.foregroundColor: textColor], range: textRange) - } - } - } - } - - private func handleAutoScroll() { - if autoScroll && !textView.isTracking && (!textView.isDragging || textView.isDecelerating) { - scrollToBottom() - } - } - - private func scrollToBottom() { - let textRange = NSRange(..<textView.text.endIndex, in: textView.text) - - textView.scrollRangeToVisible(textRange) - } - - private func updateAutoScrollBarItem() { - navigationItem.leftBarButtonItem = autoScrollButtonItem - } - - private func textColor(for logLevel: Logger.Level) -> UIColor { - switch logLevel { - case .debug, .trace: - return .lightGray - case .error, .critical: - return .red - case .info, .notice: - return .blue - case .warning: - return .orange - } - } - - // MARK: - Actions - - @objc func handleDismissButton(_ sender: Any) { - dismiss(animated: true) - } - - @objc func handleToggleAutoscroll(_ sender: Any) { - autoScroll = !autoScroll - } -} - -#endif diff --git a/ios/MullvadVPN/Logging/LogEntryParser.swift b/ios/MullvadVPN/Logging/LogEntryParser.swift deleted file mode 100644 index c7b3a68db7..0000000000 --- a/ios/MullvadVPN/Logging/LogEntryParser.swift +++ /dev/null @@ -1,98 +0,0 @@ -// -// LogEntryParser.swift -// MullvadVPN -// -// Created by pronebird on 18/08/2020. -// Copyright © 2020 Mullvad VPN AB. All rights reserved. -// - -#if DEBUG - -import Foundation -import Logging - -struct ParsedLogEntry { - let timestamp: Date - let level: Logger.Level - let module: String - let message: String -} - -class LogEntryParser { - /// Date formatter used for decoding the timestamp - private let dateFormatter = CustomFormatLogHandler.makeDateFormatter() - - /// Parse a log entry in the following format: - /// [<DATE>][<MODULE>][<LOG_LEVEL>] <MESSAGE> - func parse(_ str: String) -> ParsedLogEntry? { - let ranges = Self.stringRangesWithinSquareBrackets(string: str, maxResults: 3) - guard ranges.count == 3 else { - return nil - } - - let strings = ranges.map { String(str[$0]) } - - guard let timestamp = dateFormatter.date(from: strings[0]), - let logLevel = Logger.Level(rawValue: strings[2]) else { - return nil - } - - // Extract the log message following the log level - let startIndex = str.index(ranges.last!.upperBound, offsetBy: 1, limitedBy: str.endIndex) - let message = startIndex.map({ (startIndex) -> String in - return str[startIndex..<str.endIndex].trimmingCharacters(in: .whitespaces) - }) ?? "" - - return ParsedLogEntry( - timestamp: timestamp, - level: logLevel, - module: strings[1], - message: message - ) - } - - /// Find consecutive ranges of strings within square brackets. - private static func stringRangesWithinSquareBrackets(string: String, maxResults: Int) -> [Range<String.Index>] { - var results = [Range<String.Index>]() - var maybeStartIndex: String.Index? - - guard maxResults > 0 else { return results } - - loop: for (offset, char) in string.enumerated() { - switch char { - case "[": - if maybeStartIndex == nil { - maybeStartIndex = string.index(string.startIndex, offsetBy: offset + 1, limitedBy: string.endIndex) - } else { - // out of order - break loop - } - - case "]": - if let startIndex = maybeStartIndex { - maybeStartIndex = nil - - let endIndex = string.index(string.startIndex, offsetBy: offset) - - results.append((startIndex..<endIndex)) - - if results.count >= maxResults { - // done - break loop - } - } else { - // out of order - break loop - } - - default: - continue - } - } - - return results - } - -} - -#endif diff --git a/ios/MullvadVPN/Logging/LogStreamer.swift b/ios/MullvadVPN/Logging/LogStreamer.swift deleted file mode 100644 index 23da9fae31..0000000000 --- a/ios/MullvadVPN/Logging/LogStreamer.swift +++ /dev/null @@ -1,141 +0,0 @@ -// -// LogStreamer.swift -// MullvadVPN -// -// Created by pronebird on 10/08/2020. -// Copyright © 2020 Mullvad VPN AB. All rights reserved. -// - -#if DEBUG - -import Foundation - -private let kLogPollIntervalSeconds = 2 - -/// A class that consolidates multiple log streams into one -class LogStreamer<Codec> where Codec: UnicodeCodec { - private let fileURLs: [URL] - private var pendingFileURLs: [URL] - private var streams = [TextFileStream<Codec>]() - private var eventSources = [DispatchSourceFileSystemObject]() - private let queue = DispatchQueue(label: "net.mullvad.MullvadVPN.LogStreamer<\(Codec.self)>") - private var retry: DispatchWorkItem? - private var handlerBlock: ((String) -> Void)? - private var isStarted = false - - init(fileURLs: [URL]) { - self.fileURLs = fileURLs - self.pendingFileURLs = fileURLs - } - - deinit { - cancelAndRemoveAllEventSources() - } - - func start(handler: @escaping (String) -> Void) { - queue.async { - guard !self.isStarted else { return } - - self.isStarted = true - self.handlerBlock = handler - self.poll() - } - } - - func stop() { - queue.async { - guard self.isStarted else { return } - - self.isStarted = false - - self.retry?.cancel() - self.handlerBlock = nil - - self.cancelAndRemoveAllEventSources() - self.streams.removeAll() - self.pendingFileURLs = self.fileURLs - } - } - - private func openRemainingStreams() -> Bool { - var failedURLs = [URL]() - for fileURL in pendingFileURLs { - if let stream = TextFileStream<Codec>(fileURL: fileURL, separator: "\n") { - streams.append(stream) - - stream.read { [weak self] (s) in - guard let self = self else { return } - - self.queue.async { - self.handlerBlock?(s) - } - } - - addFileWatch(fileURL: fileURL, stream: stream) - } else { - failedURLs.append(fileURL) - } - } - - pendingFileURLs = failedURLs - - return failedURLs.isEmpty - } - - private func poll() { - if !self.openRemainingStreams() { - self.scheduleRetry() - } - } - - private func scheduleRetry() { - let workItem = DispatchWorkItem(block: { [weak self] in - guard let self = self, self.isStarted else { return } - - self.poll() - }) - queue.asyncAfter(wallDeadline: .now() + .seconds(kLogPollIntervalSeconds), execute: workItem) - retry = workItem - } - - /// Watch file renames and re-add the stream once that happens - private func addFileWatch(fileURL: URL, stream: TextFileStream<Codec>) { - let source = DispatchSource.makeFileSystemObjectSource( - fileDescriptor: stream.fileDescriptor, - eventMask: .rename, - queue: queue - ) - - source.setEventHandler { [weak self, weak source] in - guard let self = self, let source = source, self.isStarted else { return } - - // Cancel current event source - source.cancel() - - // Release the stream - self.streams.removeAll { (s) -> Bool in - return stream === s - } - - // Release the current event source - self.eventSources.removeAll { (s) -> Bool in - return source === s - } - - // Add the file URL to backlog & start polling - self.pendingFileURLs.append(fileURL) - self.poll() - } - - source.activate() - - eventSources.append(source) - } - - private func cancelAndRemoveAllEventSources() { - eventSources.forEach { $0.cancel() } - eventSources.removeAll() - } -} - -#endif diff --git a/ios/MullvadVPN/Logging/StringStreamIterator.swift b/ios/MullvadVPN/Logging/StringStreamIterator.swift deleted file mode 100644 index c13b921c33..0000000000 --- a/ios/MullvadVPN/Logging/StringStreamIterator.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// StringStreamIterator.swift -// MullvadVPN -// -// Created by pronebird on 17/08/2020. -// Copyright © 2020 Mullvad VPN AB. All rights reserved. -// - -#if DEBUG - -import Foundation - -class StringStreamIterator<Codec>: IteratorProtocol where Codec: UnicodeCodec { - let separator: Character - - private var string = "" - private var data = [Codec.CodeUnit]() - private var parser = Codec.ForwardParser() - - init(separator: Character) { - self.separator = separator - } - - func append<S>(bytes: S) where S: Sequence, S.Element == Codec.CodeUnit { - data.append(contentsOf: bytes) - } - - func next() -> String? { - var dataIterator = data.makeIterator() - var bytesRead = 0 - - defer { - if bytesRead > 0 { - data.removeSubrange(..<bytesRead) - } - } - - while case .valid(let encodedScalar) = parser.parseScalar(from: &dataIterator) { - let unicodeScalar = Codec.decode(encodedScalar) - let character = Character(unicodeScalar) - - bytesRead += encodedScalar.count - - if character == separator { - let returnString = string - string = "" - - return returnString - } else { - string.append(character) - } - } - - return nil - } -} - -#endif diff --git a/ios/MullvadVPN/Logging/TextFileStream.swift b/ios/MullvadVPN/Logging/TextFileStream.swift deleted file mode 100644 index de1aad6d91..0000000000 --- a/ios/MullvadVPN/Logging/TextFileStream.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// TextFileStream.swift -// MullvadVPN -// -// Created by pronebird on 05/08/2020. -// Copyright © 2020 Mullvad VPN AB. All rights reserved. -// - -#if DEBUG - -import Foundation -import Darwin - -class TextFileStream<Codec> where Codec: UnicodeCodec { - let fileDescriptor: Int32 - - private let readSource: DispatchSourceRead - private let queue = DispatchQueue(label: "net.mullvad.MullvadVPN.TextFileStream<\(Codec.self)>") - private let stringStream: StringStreamIterator<Codec> - - init?(fileURL: URL, separator: Character) { - let filePath = fileURL.path.utf8CString.map { $0 } - - let fileDescriptor = open(filePath, O_RDONLY) - if (fileDescriptor == -1) { - return nil - } - - // Avoid blocking the read operation - _ = fcntl(fileDescriptor, F_SETFL, O_NONBLOCK); - - let readSource = DispatchSource.makeReadSource(fileDescriptor: fileDescriptor, queue: queue) - readSource.setCancelHandler { - close(fileDescriptor) - } - - stringStream = StringStreamIterator(separator: separator) - - self.readSource = readSource - self.fileDescriptor = fileDescriptor - } - - deinit { - readSource.cancel() - } - - func read(_ handler: @escaping (String) -> Void) { - readSource.setEventHandler { [weak self] in - guard let self = self else { return } - - let estimated = Int(self.readSource.data + 1) - var buffer = [Codec.CodeUnit](repeating: 0, count: estimated) - let actual = Darwin.read(self.fileDescriptor, &buffer, estimated) - - if actual == -1 { - print("TextFileStream<\(Codec.self)>: read error: \(errno)") - } - - if actual > 0 { - let bytes = buffer[..<actual] - self.stringStream.append(bytes: bytes) - - while let s = self.stringStream.next() { - handler(s) - } - } - } - readSource.activate() - } - - func cancel() { - readSource.cancel() - } - -} - -#endif diff --git a/ios/MullvadVPN/SettingsViewController.swift b/ios/MullvadVPN/SettingsViewController.swift index 769181dfc8..a2a7f91208 100644 --- a/ios/MullvadVPN/SettingsViewController.swift +++ b/ios/MullvadVPN/SettingsViewController.swift @@ -143,23 +143,6 @@ class SettingsViewController: UITableViewController, AccountObserver { middleSection.addRows([versionRow]) staticDataSource.addSections([middleSection]) - #if DEBUG - let logStreamerRow = StaticTableViewRow(reuseIdentifier: CellIdentifier.basicCell.rawValue) { (_, cell) in - let cell = cell as! SettingsCell - - cell.titleLabel.text = "App logs" - } - logStreamerRow.actionBlock = { [weak self] (indexPath) in - let logController = LogStreamerViewController(fileURLs: ApplicationConfiguration.logFileURLs) - let navController = UINavigationController(rootViewController: logController) - - navController.modalPresentationStyle = .fullScreen - - self?.present(navController, animated: true) - } - middleSection.addRows([logStreamerRow]) - #endif - let bottomSection = StaticTableViewSection() let problemReportRow = StaticTableViewRow(reuseIdentifier: CellIdentifier.basicCell.rawValue) { (indexPath, cell) in |
