diff --git a/Sources/PulseCore/LoggerStore+MOM.swift b/Sources/PulseCore/LoggerStore+MOM.swift index af326840..7f4c32bb 100644 --- a/Sources/PulseCore/LoggerStore+MOM.swift +++ b/Sources/PulseCore/LoggerStore+MOM.swift @@ -44,8 +44,7 @@ public extension LoggerStore { NSAttributeDescription(name: "currentRequest", type: .binaryDataAttributeType), NSAttributeDescription(name: "response", type: .binaryDataAttributeType), NSAttributeDescription(name: "error", type: .binaryDataAttributeType), - NSAttributeDescription(name: "metrics", type: .binaryDataAttributeType), - NSAttributeDescription(name: "lastTransactionDetails", type: .binaryDataAttributeType), + NSAttributeDescription(name: "metrics", type: .binaryDataAttributeType) ] requestProgress.properties = [ @@ -221,9 +220,6 @@ public final class LoggerNetworkRequestDetailsEntity: NSManagedObject { @NSManaged public var error: Data? /// Contains JSON-encoded ``NetworkLoggerMetrics``. @NSManaged public var metrics: Data? - /// Contains JSON-encoded ``NetworkLoggerTransactionDetailedMetrics`` for - /// the last transaction from metrics. - @NSManaged public var lastTransactionDetails: Data? } // MARK: - Helpers diff --git a/Sources/PulseCore/LoggerStore.swift b/Sources/PulseCore/LoggerStore.swift index 6662fbe3..2ff86057 100644 --- a/Sources/PulseCore/LoggerStore.swift +++ b/Sources/PulseCore/LoggerStore.swift @@ -409,7 +409,6 @@ extension LoggerStore { details.response = try? encoder.encode(event.response) details.error = try? encoder.encode(event.error) details.metrics = try? encoder.encode(event.metrics) - details.lastTransactionDetails = try? encoder.encode(event.metrics?.transactions.last?.details) // Completed if let progress = request.progress { diff --git a/Sources/PulseCore/LoggerStoreInsights.swift b/Sources/PulseCore/LoggerStoreInsights.swift new file mode 100644 index 00000000..531c79dd --- /dev/null +++ b/Sources/PulseCore/LoggerStoreInsights.swift @@ -0,0 +1,39 @@ +// The MIT License (MIT) +// +// Copyright (c) 2020–2022 Alexander Grebenyuk (github.com/kean). + +import Foundation +import Combine +import SwiftUI + +public final class LoggerStoreInsights: ObservableObject { + private weak var logger: LoggerStore? + private var cancellable: AnyCancellable? + + @Published private(set) var totalBytesSent: Int64 = 0 + @Published private(set) var bodyBytesSent: Int64 = 0 + @Published private(set) var headersBytesSent: Int64 = 0 + + @Published private(set) var totalBytesReceived: Int64 = 0 + @Published private(set) var bodyBytesReceived: Int64 = 0 + @Published private(set) var headersBytesReceived: Int64 = 0 + + public init(logger: LoggerStore) { + cancellable = logger.events.receive(on: DispatchQueue.main).sink { [weak self] in + self?.process(event: $0) + } + } + + private func process(event: LoggerStoreEvent) { + switch event { + case .messageStored: break + case .networkTaskCreated: break + case .networkTaskProgressUpdated: break + case .networkTaskCompleted(let event): process(event: event) + } + } + + private func process(event: LoggerStoreEvent.NetworkTaskCompleted) { + + } +} diff --git a/Sources/PulseCore/NetworkLoggerEntities.swift b/Sources/PulseCore/NetworkLoggerEntities.swift index 2b144a86..edf3235e 100644 --- a/Sources/PulseCore/NetworkLoggerEntities.swift +++ b/Sources/PulseCore/NetworkLoggerEntities.swift @@ -114,6 +114,7 @@ public struct NetworkLoggerMetrics: Codable { public let taskInterval: DateInterval public let redirectCount: Int public let transactions: [NetworkLoggerTransactionMetrics] + public var transferSize: TransferSize { TransferSize(metrics: self) } public init(metrics: URLSessionTaskMetrics) { self.taskInterval = metrics.taskInterval @@ -126,6 +127,29 @@ public struct NetworkLoggerMetrics: Codable { self.redirectCount = redirectCount self.transactions = transactions } + + /// Total transfer size across all transactions. + public struct TransferSize { + public var totalBytesSent: Int64 = 0 + public var bodyBytesSent: Int64 = 0 + public var headersBytesSent: Int64 = 0 + public var totalBytesReceived: Int64 = 0 + public var bodyBytesReceived: Int64 = 0 + public var headersBytesReceived: Int64 = 0 + + public init() {} + + public init(metrics: NetworkLoggerMetrics) { + for details in metrics.transactions.compactMap(\.details) { + totalBytesSent += details.countOfRequestBodyBytesBeforeEncoding + details.countOfRequestHeaderBytesSent + bodyBytesSent += details.countOfRequestBodyBytesSent + headersBytesSent += details.countOfRequestHeaderBytesSent + totalBytesReceived += details.countOfResponseBodyBytesReceived + details.countOfResponseHeaderBytesReceived + bodyBytesReceived += details.countOfResponseBodyBytesReceived + headersBytesReceived += details.countOfResponseHeaderBytesReceived + } + } + } } public struct NetworkLoggerTransactionMetrics: Codable { diff --git a/Sources/PulseCore/RemoteLogger/RemoteLogger-Store.swift b/Sources/PulseCore/RemoteLogger/RemoteLogger-Store.swift index 8d3600fb..18a09247 100644 --- a/Sources/PulseCore/RemoteLogger/RemoteLogger-Store.swift +++ b/Sources/PulseCore/RemoteLogger/RemoteLogger-Store.swift @@ -5,7 +5,6 @@ import Foundation import Network import Combine -import SwiftUI @available(iOS 14.0, tvOS 14.0, *) extension RemoteLogger { diff --git a/Sources/PulseUI/Features/Inspector/Metrics/NetworkInspectorTransferInfoView.swift b/Sources/PulseUI/Features/Inspector/Metrics/NetworkInspectorTransferInfoView.swift index 72144759..f4f5e134 100644 --- a/Sources/PulseUI/Features/Inspector/Metrics/NetworkInspectorTransferInfoView.swift +++ b/Sources/PulseUI/Features/Inspector/Metrics/NetworkInspectorTransferInfoView.swift @@ -111,11 +111,9 @@ struct NetworkInspectorTransferInfoView_Previews: PreviewProvider { } private let mockModel = NetworkInspectorTransferInfoViewModel( - details: mockMetrics.transactions.last!.details!, taskType: .dataTask + metrics: LoggerStore.preview.entity(for: .login).metrics!, taskType: .dataTask ) -private let mockMetrics = LoggerStore.preview.entity(for: .login).metrics! - #endif // MARK: - ViewModel @@ -132,25 +130,27 @@ struct NetworkInspectorTransferInfoViewModel { let isUpload: Bool init(empty: Bool) { - self.totalBytesSent = "–" - self.bodyBytesSent = "–" - self.headersBytesSent = "–" - self.totalBytesReceived = "–" - self.bodyBytesReceived = "–" - self.headersBytesReceived = "–" - self.isUpload = false + totalBytesSent = "–" + bodyBytesSent = "–" + headersBytesSent = "–" + totalBytesReceived = "–" + bodyBytesReceived = "–" + headersBytesReceived = "–" + isUpload = false } - init(details: NetworkLoggerTransactionDetailedMetrics, taskType: NetworkLoggerTaskType) { - self.totalBytesSent = formatBytes(details.countOfRequestBodyBytesBeforeEncoding + details.countOfRequestHeaderBytesSent) - self.bodyBytesSent = formatBytes(details.countOfRequestBodyBytesSent) - self.headersBytesSent = formatBytes(details.countOfRequestHeaderBytesSent) + init(metrics: NetworkLoggerMetrics, taskType: NetworkLoggerTaskType) { + let transfer = metrics.transferSize - self.totalBytesReceived = formatBytes(details.countOfResponseBodyBytesReceived + details.countOfResponseHeaderBytesReceived) - self.bodyBytesReceived = formatBytes(details.countOfResponseBodyBytesReceived) - self.headersBytesReceived = formatBytes(details.countOfResponseHeaderBytesReceived) + totalBytesSent = formatBytes(transfer.totalBytesSent) + bodyBytesSent = formatBytes(transfer.bodyBytesSent) + headersBytesSent = formatBytes(transfer.headersBytesSent) - self.isUpload = taskType == .uploadTask + totalBytesReceived = formatBytes(transfer.totalBytesReceived) + bodyBytesReceived = formatBytes(transfer.bodyBytesReceived) + headersBytesReceived = formatBytes(transfer.headersBytesReceived) + + isUpload = taskType == .uploadTask } } diff --git a/Sources/PulseUI/Features/Inspector/NetworkInspectorSummaryViewModel.swift b/Sources/PulseUI/Features/Inspector/NetworkInspectorSummaryViewModel.swift index d9df30ad..e16fda6b 100644 --- a/Sources/PulseUI/Features/Inspector/NetworkInspectorSummaryViewModel.swift +++ b/Sources/PulseUI/Features/Inspector/NetworkInspectorSummaryViewModel.swift @@ -57,8 +57,8 @@ final class NetworkInspectorSummaryViewModel: ObservableObject { // MARK: - Header var transferViewModel: NetworkInspectorTransferInfoViewModel? { - details.lastTransactionDetails.map { - NetworkInspectorTransferInfoViewModel(details: $0, taskType: request.taskType ?? .dataTask) + details.metrics.map { + NetworkInspectorTransferInfoViewModel(metrics: $0, taskType: request.taskType ?? .dataTask) } } diff --git a/Sources/PulseUI/Helpers/DecodedNetworkRequestDetailsEntity.swift b/Sources/PulseUI/Helpers/DecodedNetworkRequestDetailsEntity.swift index 3b02cae3..be7d45b6 100644 --- a/Sources/PulseUI/Helpers/DecodedNetworkRequestDetailsEntity.swift +++ b/Sources/PulseUI/Helpers/DecodedNetworkRequestDetailsEntity.swift @@ -15,7 +15,6 @@ final class DecodedNetworkRequestDetailsEntity { private(set) lazy var response = decode(NetworkLoggerResponse.self, from: details.response) private(set) lazy var error = decode(NetworkLoggerError.self, from: details.error) private(set) lazy var metrics = decode(NetworkLoggerMetrics.self, from: details.metrics) - private(set) lazy var lastTransactionDetails = decode(NetworkLoggerTransactionDetailedMetrics.self, from: details.lastTransactionDetails) init(request: LoggerNetworkRequestEntity) { self.details = request.details